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

Code before:

    def _typecheck_input(self, mobject: Mobject | None) -> None:
        if mobject is None:
            logger.debug("Animation with empty mobject")
        elif not isinstance(mobject, (Mobject, OpenGLMobject)):
            raise TypeError("Animation only works on Mobjects")

    def __str__(self) -> str:
        if self.name:
            return self.name
        return f"{self.__class__.__name__}({str(self.mobject)})"

    def __repr__(self) -> str:
        return str(self)

    def begin(self) -> None:
        """Begin the animation.

        This method is called right as an animation is being played. As much
        initialization as possible, especially any mobject copying, should live in this
        method.

        """
        if self.run_time <= 0:
            raise ValueError(
                f"{self} has a runtime of 0 seconds. Which cannot be rendered correctly! please set a runtime > 0"
            )
        self.starting_mobject = self.create_starting_mobject()
        if self.suspend_mobject_updating:
            # All calls to self.mobject's internal updaters
            # during the animation, either from this Animation
            # or from the surrounding scene, should do nothing.
            # It is, however, okay and desirable to call
            # the internal updaters of self.starting_mobject,
            # or any others among self.get_all_mobjects()
            self.mobject.suspend_updating()
        self.interpolate(0)

    def finish(self) -> None:
        # TODO: begin and finish should require a scene as parameter.
        # That way Animation.clean_up_from_screen and Scene.add_mobjects_from_animations
        # could be removed as they fulfill basically the same purpose.
        """Finish the animation.

        This method gets called when the animation is over.

        """
        self.interpolate(1)
        if self.suspend_mobject_updating and self.mobject is not None:
            self.mobject.resume_updating()


Review comment (suggestion):
```suggestion
                f"{self} has a runtime of <= 0 seconds, which cannot be rendered correctly! please set a runtime > 0"
```

Code after:

    def _typecheck_input(self, mobject: Mobject | None) -> None:
        if mobject is None:
            logger.debug("Animation with empty mobject")
        elif not isinstance(mobject, (Mobject, OpenGLMobject)):
            raise TypeError("Animation only works on Mobjects")

    def __str__(self) -> str:
        if self.name:
            return self.name
        return f"{self.__class__.__name__}({str(self.mobject)})"

    def __repr__(self) -> str:
        return str(self)

    def begin(self) -> None:
        """Begin the animation.

        This method is called right as an animation is being played. As much
        initialization as possible, especially any mobject copying, should live in this
        method.

        """
        if self.run_time <= 0:
            raise ValueError(
                f"{self} has a runtime of <= 0 seconds, which cannot be rendered correctly! please set a runtime > 0"
            )
        self.starting_mobject = self.create_starting_mobject()
        if self.suspend_mobject_updating:
            # All calls to self.mobject's internal updaters
            # during the animation, either from this Animation
            # or from the surrounding scene, should do nothing.
            # It is, however, okay and desirable to call
            # the internal updaters of self.starting_mobject,
            # or any others among self.get_all_mobjects()
            self.mobject.suspend_updating()
        self.interpolate(0)

    def finish(self) -> None:
        # TODO: begin and finish should require a scene as parameter.
        # That way Animation.clean_up_from_screen and Scene.add_mobjects_from_animations
        # could be removed as they fulfill basically the same purpose.
        """Finish the animation.

        This method gets called when the animation is over.

        """
        self.interpolate(1)
        if self.suspend_mobject_updating and self.mobject is not None:
            self.mobject.resume_updating()