From c8edc19729d7b972f48d88c7bbebaa7379d961aa Mon Sep 17 00:00:00 2001 From: Taksh Date: Wed, 8 Jul 2026 16:59:12 +0530 Subject: [PATCH 1/5] fix(scene): warn when overlapping .animate targets share play() Detect multiple _MethodAnimation instances in one play() that touch the same mobject family and log a warning about argument-order overrides. Fixes #4865 Co-authored-by: Cursor --- manim/scene/scene.py | 25 +++++++++++++++++++++++++ tests/module/scene/test_scene.py | 19 ++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/manim/scene/scene.py b/manim/scene/scene.py index 845fafd0b9..6a87973a15 100644 --- a/manim/scene/scene.py +++ b/manim/scene/scene.py @@ -994,8 +994,33 @@ def compile_animations( for k, v in kwargs.items(): setattr(animation, k, v) + self._warn_if_overlapping_animate_targets(animations) + return animations + @staticmethod + def _warn_if_overlapping_animate_targets(animations: list[Animation]) -> None: + from ..animation.transform import _MethodAnimation + + method_anims = [anim for anim in animations if isinstance(anim, _MethodAnimation)] + if len(method_anims) < 2: + return + + seen: set[int] = set() + for anim in method_anims: + for member in anim.mobject.get_family(): + member_id = id(member) + if member_id in seen: + logger.warning( + "Multiple .animate animations in the same play() affect " + "the same mobject (%s). Later animations override earlier " + "ones for unchanged attributes; reorder arguments or " + "animate mobjects individually.", + member.__class__.__name__, + ) + return + seen.add(member_id) + def _get_animation_time_progression( self, animations: list[Animation], duration: float ) -> tqdm[float]: diff --git a/tests/module/scene/test_scene.py b/tests/module/scene/test_scene.py index c64fbd46ac..d76af11ee5 100644 --- a/tests/module/scene/test_scene.py +++ b/tests/module/scene/test_scene.py @@ -4,7 +4,7 @@ import pytest -from manim import Circle, Dot, FadeIn, Group, Mobject, Scene, Square +from manim import Circle, Dot, FadeIn, Group, Mobject, RIGHT, Scene, Square, VGroup from manim.animation.animation import Wait @@ -146,3 +146,20 @@ def test_random_color_reproducibility_with_seed(dry_run): # The interrupted colors should be different (seeded with 999) assert colors_interrupted != colors_first_run[:3] + + +def test_warn_overlapping_animate_targets(caplog) -> None: + scene = Scene() + square = Square() + circle = Circle() + group = VGroup(square, circle) + + with caplog.at_level("WARNING"): + scene.compile_animations( + group.animate.shift(RIGHT), + circle.animate.set_opacity(0.5), + ) + + assert any( + "Multiple .animate animations" in record.message for record in caplog.records + ) From 8a5a6bfeb43ad0169cc9314a2a65c02fa6dc0f50 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:30:12 +0000 Subject: [PATCH 2/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/scene/scene.py | 4 +++- tests/module/scene/test_scene.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/manim/scene/scene.py b/manim/scene/scene.py index 6a87973a15..cc7ee8bfb5 100644 --- a/manim/scene/scene.py +++ b/manim/scene/scene.py @@ -1002,7 +1002,9 @@ def compile_animations( def _warn_if_overlapping_animate_targets(animations: list[Animation]) -> None: from ..animation.transform import _MethodAnimation - method_anims = [anim for anim in animations if isinstance(anim, _MethodAnimation)] + method_anims = [ + anim for anim in animations if isinstance(anim, _MethodAnimation) + ] if len(method_anims) < 2: return diff --git a/tests/module/scene/test_scene.py b/tests/module/scene/test_scene.py index d76af11ee5..9dc87ce183 100644 --- a/tests/module/scene/test_scene.py +++ b/tests/module/scene/test_scene.py @@ -4,7 +4,7 @@ import pytest -from manim import Circle, Dot, FadeIn, Group, Mobject, RIGHT, Scene, Square, VGroup +from manim import RIGHT, Circle, Dot, FadeIn, Group, Mobject, Scene, Square, VGroup from manim.animation.animation import Wait From bd7ff2e9f3cffcdc205954f102ea9f210161ab6c Mon Sep 17 00:00:00 2001 From: Taksh Date: Wed, 8 Jul 2026 17:22:04 +0530 Subject: [PATCH 3/5] test(scene): capture manim logger in overlap warning test manim.logger has propagate=False; target it explicitly in caplog. Co-authored-by: Cursor --- tests/module/scene/test_scene.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/module/scene/test_scene.py b/tests/module/scene/test_scene.py index 9dc87ce183..2112c8fd48 100644 --- a/tests/module/scene/test_scene.py +++ b/tests/module/scene/test_scene.py @@ -4,7 +4,7 @@ import pytest -from manim import RIGHT, Circle, Dot, FadeIn, Group, Mobject, Scene, Square, VGroup +from manim import RIGHT, Circle, Dot, FadeIn, Group, Mobject, Scene, Square, VGroup, logger from manim.animation.animation import Wait @@ -154,7 +154,7 @@ def test_warn_overlapping_animate_targets(caplog) -> None: circle = Circle() group = VGroup(square, circle) - with caplog.at_level("WARNING"): + with caplog.at_level("WARNING", logger=logger.name): scene.compile_animations( group.animate.shift(RIGHT), circle.animate.set_opacity(0.5), From 93401d25701d5effb26ace37f9e2895874b40824 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:52:21 +0000 Subject: [PATCH 4/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/module/scene/test_scene.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/module/scene/test_scene.py b/tests/module/scene/test_scene.py index 2112c8fd48..52d8746310 100644 --- a/tests/module/scene/test_scene.py +++ b/tests/module/scene/test_scene.py @@ -4,7 +4,18 @@ import pytest -from manim import RIGHT, Circle, Dot, FadeIn, Group, Mobject, Scene, Square, VGroup, logger +from manim import ( + RIGHT, + Circle, + Dot, + FadeIn, + Group, + Mobject, + Scene, + Square, + VGroup, + logger, +) from manim.animation.animation import Wait From b4b49c76d406218f8786eecf8e5edda166e8088c Mon Sep 17 00:00:00 2001 From: Taksh Date: Wed, 8 Jul 2026 17:27:50 +0530 Subject: [PATCH 5/5] test(scene): mock logger.warning for overlap warning test caplog does not capture manim.logger (propagate=False + RichHandler). Co-authored-by: Cursor --- tests/module/scene/test_scene.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/module/scene/test_scene.py b/tests/module/scene/test_scene.py index 52d8746310..4ad0ae5434 100644 --- a/tests/module/scene/test_scene.py +++ b/tests/module/scene/test_scene.py @@ -1,6 +1,7 @@ from __future__ import annotations import datetime +from unittest.mock import patch import pytest @@ -159,18 +160,17 @@ def test_random_color_reproducibility_with_seed(dry_run): assert colors_interrupted != colors_first_run[:3] -def test_warn_overlapping_animate_targets(caplog) -> None: +def test_warn_overlapping_animate_targets() -> None: scene = Scene() square = Square() circle = Circle() group = VGroup(square, circle) - with caplog.at_level("WARNING", logger=logger.name): + with patch.object(logger, "warning") as warn: scene.compile_animations( group.animate.shift(RIGHT), circle.animate.set_opacity(0.5), ) - assert any( - "Multiple .animate animations" in record.message for record in caplog.records - ) + warn.assert_called_once() + assert "Multiple .animate animations" in warn.call_args[0][0]