From 52ee67ed836510b4676f8d438a5cfcbf4f9a0449 Mon Sep 17 00:00:00 2001 From: Henrik Skov Midtiby Date: Mon, 4 Aug 2025 08:59:41 +0200 Subject: [PATCH 1/2] Add type annotations to `mobject_update_utils.py` --- manim/animation/animation.py | 1 + .../updaters/mobject_update_utils.py | 33 +++++++++++-------- mypy.ini | 3 -- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/manim/animation/animation.py b/manim/animation/animation.py index 2e31edbeaa..56d916dd88 100644 --- a/manim/animation/animation.py +++ b/manim/animation/animation.py @@ -144,6 +144,7 @@ def __init__( ) -> None: self._typecheck_input(mobject) self.run_time: float = run_time + self.total_time: float self.rate_func: Callable[[float], float] = rate_func self.reverse_rate_function: bool = reverse_rate_function self.name: str | None = name diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index 213180f3bd..ffaea9fb36 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -15,7 +15,7 @@ import inspect -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING, Any, Callable import numpy as np @@ -26,6 +26,7 @@ if TYPE_CHECKING: from manim.animation.animation import Animation + from manim.typing import Vector3DLike def assert_is_mobject_method(method: Callable) -> None: @@ -34,25 +35,27 @@ def assert_is_mobject_method(method: Callable) -> None: assert isinstance(mobject, (Mobject, OpenGLMobject)) -def always(method: Callable, *args, **kwargs) -> Mobject: +def always(method: Callable, *args: Any, **kwargs: Any) -> Mobject | OpenGLMobject: assert_is_mobject_method(method) - mobject = method.__self__ + mobject: Mobject | OpenGLMobject = method.__self__ func = method.__func__ mobject.add_updater(lambda m: func(m, *args, **kwargs)) return mobject -def f_always(method: Callable[[Mobject], None], *arg_generators, **kwargs) -> Mobject: +def f_always( + method: Callable[[Mobject], None], *arg_generators: Any, **kwargs: Any +) -> Mobject | OpenGLMobject: """ More functional version of always, where instead of taking in args, it takes in functions which output the relevant arguments. """ assert_is_mobject_method(method) - mobject = method.__self__ + mobject: Mobject | OpenGLMobject = method.__self__ func = method.__func__ - def updater(mob): + def updater(mob: Mobject | OpenGLMobject) -> None: args = [arg_generator() for arg_generator in arg_generators] func(mob, *args, **kwargs) @@ -60,7 +63,7 @@ def updater(mob): return mobject -def always_redraw(func: Callable[[], Mobject]) -> Mobject: +def always_redraw(func: Callable[[], Mobject]) -> Mobject | OpenGLMobject: """Redraw the mobject constructed by a function every frame. This function returns a mobject with an attached updater that @@ -106,8 +109,8 @@ def construct(self): def always_shift( - mobject: Mobject, direction: np.ndarray[np.float64] = RIGHT, rate: float = 0.1 -) -> Mobject: + mobject: Mobject | OpenGLMobject, direction: Vector3DLike = RIGHT, rate: float = 0.1 +) -> Mobject | OpenGLMobject: """A mobject which is continuously shifted along some direction at a certain rate. @@ -144,7 +147,9 @@ def construct(self): return mobject -def always_rotate(mobject: Mobject, rate: float = 20 * DEGREES, **kwargs) -> Mobject: +def always_rotate( + mobject: Mobject | OpenGLMobject, rate: float = 20 * DEGREES, **kwargs: Any +) -> Mobject | OpenGLMobject: """A mobject which is continuously rotated at a certain rate. Parameters @@ -178,8 +183,8 @@ def construct(self): def turn_animation_into_updater( - animation: Animation, cycle: bool = False, delay: float = 0, **kwargs -) -> Mobject: + animation: Animation, cycle: bool = False, delay: float = 0, **kwargs: Any +) -> Mobject | OpenGLMobject: """ Add an updater to the animation's mobject which applies the interpolation and update functions of the animation @@ -210,7 +215,7 @@ def construct(self): animation.begin() animation.total_time = -delay - def update(m: Mobject, dt: float): + def update(m: Mobject, dt: float) -> None: if animation.total_time >= 0: run_time = animation.get_run_time() time_ratio = animation.total_time / run_time @@ -230,5 +235,5 @@ def update(m: Mobject, dt: float): return mobject -def cycle_animation(animation: Animation, **kwargs) -> Mobject: +def cycle_animation(animation: Animation, **kwargs: Any) -> Mobject | OpenGLMobject: return turn_animation_into_updater(animation, cycle=True, **kwargs) diff --git a/mypy.ini b/mypy.ini index 42c31f08ef..91bef87ce7 100644 --- a/mypy.ini +++ b/mypy.ini @@ -81,9 +81,6 @@ ignore_errors = True [mypy-manim.animation.transform] ignore_errors = True -[mypy-manim.animation.updaters.mobject_update_utils] -ignore_errors = True - [mypy-manim.camera.mapping_camera] ignore_errors = True From 81b4bf70c5524fde0b13fb87e37dd06eeabb42f4 Mon Sep 17 00:00:00 2001 From: Henrik Skov Midtiby Date: Fri, 8 Aug 2025 13:17:06 +0200 Subject: [PATCH 2/2] Insert mypy errors as comments. --- manim/animation/updaters/mobject_update_utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index ffaea9fb36..cbeacfbb93 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -37,7 +37,9 @@ def assert_is_mobject_method(method: Callable) -> None: def always(method: Callable, *args: Any, **kwargs: Any) -> Mobject | OpenGLMobject: assert_is_mobject_method(method) + # error: "Callable[..., Any]" has no attribute "__self__" [attr-defined] mobject: Mobject | OpenGLMobject = method.__self__ + # error: "Callable[..., Any]" has no attribute "__func__" [attr-defined] func = method.__func__ mobject.add_updater(lambda m: func(m, *args, **kwargs)) return mobject @@ -52,7 +54,9 @@ def f_always( the relevant arguments. """ assert_is_mobject_method(method) + # error: "Callable[[Mobject], None]" has no attribute "__self__" [attr-defined] mobject: Mobject | OpenGLMobject = method.__self__ + # error: "Callable[[Mobject], None]" has no attribute "__func__" [attr-defined] func = method.__func__ def updater(mob: Mobject | OpenGLMobject) -> None: