Repository: ManimCommunity/manim
File: manim/scene/scene.py (Python)

Code before:
                            "from_animation_number"
                        ]
                    # # TODO: This option only makes sense if embed_2() is run at the
                    # # end of a scene by default.
                    # if "upto_animation_number" in kwargs:
                    #     config["upto_animation_number"] = kwargs[
                    #         "upto_animation_number"
                    #     ]

                    keyboard_thread.join()
                    raise RerunSceneException
                elif tup[0].startswith("exit"):
                    keyboard_thread.join()
                    keyboard_thread_needs_join = False
                    break
                else:
                    method, args, kwargs = tup
                    self.saved_methods[method](*args, **kwargs)
            else:
                self.renderer.animation_start_time = 0
                dt = 1 / config["frame_rate"]
                self.renderer.render(self, dt, self.moving_mobjects)
                self.update_mobjects(dt)

        # Restore overridden methods.
        for name, method in self.saved_methods.items():
            setattr(self, name, method)
        self.saved_methods = {}

        # Join the keyboard thread if necessary.
        if shell is not None and keyboard_thread_needs_join:
            shell.pt_app.app.exit(exception=EOFError)
            keyboard_thread.join()

        if self.renderer.window.is_closing:
            self.renderer.window.destroy()

    def embed(self):
        if not config["preview"]:
            logger.warning("Called embed() while no preview window is available.")
            return
        if config["write_to_movie"]:
            logger.warning("embed() is skipped while writing to a file.")
            return

        self.renderer.animation_start_time = 0
        self.renderer.render(self, -1, self.moving_mobjects)

        # Configure IPython shell.
        from IPython.terminal.embed import InteractiveShellEmbed


Review comment (suggestion):
To follow best practices, I believe that the logic of `interact` alone, without the logic needed for `embed`, should be in its own function because none of the normal `interact` logic depends on the logic needed for `embed`. As a result, there should be two `interact` functions, one to be used alone and the other is a private function to be used with `interactive_embed`

Code after:
                    # # end of a scene by default.
                    # if "upto_animation_number" in kwargs:
                    #     config["upto_animation_number"] = kwargs[
                    #         "upto_animation_number"
                    #     ]

                    keyboard_thread.join()
                    raise RerunSceneException
                elif tup[0].startswith("exit"):
                    keyboard_thread.join()
                    keyboard_thread_needs_join = False
                    break
                else:
                    method, args, kwargs = tup
                    getattr(self, method)(*args, **kwargs)
            else:
                self.renderer.animation_start_time = 0
                dt = 1 / config["frame_rate"]
                self.renderer.render(self, dt, self.moving_mobjects)
                self.update_mobjects(dt)

        # Join the keyboard thread if necessary.
        if shell is not None and keyboard_thread_needs_join:
            shell.pt_app.app.exit(exception=EOFError)
            keyboard_thread.join()

        if self.renderer.window.is_closing:
            self.renderer.window.destroy()

    def embed(self):
        if not config["preview"]:
            logger.warning("Called embed() while no preview window is available.")
            return
        if config["write_to_movie"]:
            logger.warning("embed() is skipped while writing to a file.")
            return

        self.renderer.animation_start_time = 0
        self.renderer.render(self, -1, self.moving_mobjects)

        # Configure IPython shell.
        from IPython.terminal.embed import InteractiveShellEmbed

        shell = InteractiveShellEmbed()

        # Have the frame update after each command
        shell.events.register(
            "post_run_cell",
            lambda *a, **kw: self.renderer.render(self, -1, self.moving_mobjects),
        )