Skip to content

Conversation

henrikmidtiby
Copy link
Contributor

@henrikmidtiby henrikmidtiby commented Aug 10, 2025

Overview: What does this pull request change?

This PR add type annotations to mobject.py.

Issue #3375.

Reviewer Checklist

  • The PR title is descriptive enough for the changelog, and the PR is labeled correctly
  • If applicable: newly added non-private functions and classes have a docstring including a short summary and a PARAMETERS section
  • If applicable: newly added functions and classes are tested

Comment on lines 652 to 656
# error: Argument "tip" to "add_tip" of "TipableVMobject" has incompatible type "VMobject"; expected "ArrowTip | None" [arg-type]
self.add_tip(tip=old_tips[0])
if has_start_tip:
# error: Argument "tip" to "add_tip" of "TipableVMobject" has incompatible type "VMobject"; expected "ArrowTip | None" [arg-type]
self.add_tip(tip=old_tips[1], at_start=True)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These issues can be handled by typing.cast, but I don't think that is the best way to deal with them.

Comment on lines 2294 to 2296
def __getitem__(self, key: int) -> VMobject:
return self.submobjects[key]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is used to define the return type when indexing into a VGroup. If the super class was used, this would return a Mobject, but in a VGroup it should be a VMobject.

Comment on lines +286 to +288
temp = self.get_basis_vectors()
i_hat = temp.submobjects[0]
j_hat = temp.submobjects[1]
Copy link
Contributor Author

@henrikmidtiby henrikmidtiby Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently the trick for defining the type of elements in a VGroup to be VMobject's does not work here. Which is the reason for this workaround.

Comment on lines +524 to +526
temp = array.get_entries()
x_coord = temp.submobjects[0]
y_coord = temp.submobjects[1]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently the trick for defining the type of elements in a VGroup to be VMobject's does not work here. Which is the reason for this workaround.

@@ -1409,7 +1409,7 @@ def invert_color(color: ManimColorT) -> ManimColorT:
def color_gradient(
reference_colors: Sequence[ParsableManimColor],
length_of_output: int,
) -> list[ManimColor] | ManimColor:
) -> list[ManimColor]:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same change as in PR #4380

@@ -1426,7 +1426,7 @@ def color_gradient(
A :class:`ManimColor` or a list of interpolated :class:`ManimColor`'s.
"""
if length_of_output == 0:
return ManimColor(reference_colors[0])
return [ManimColor(reference_colors[0])]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same change as in PR #4380.

Comment on lines +96 to +99
animation_overrides: dict[
type[Animation],
FunctionOverride,
] = {}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By specifying the type of animation_overrides here, a lot of type errors like "type[Mobject]" has no attribute "animation_overrides" are removed.

@@ -1227,7 +1244,7 @@

return self

def scale(self, scale_factor: float, **kwargs) -> Self:
def scale(self, scale_factor: float, **kwargs: Any) -> Self:

Check notice

Code scanning / CodeQL

Mismatch between signature and use of an overridden method Note

Overridden method signature does not match
call
, where it is passed too many arguments. Overriding method
method VMobject.scale
matches the call.
Overridden method signature does not match
call
, where it is passed too many arguments. Overriding method
method VMobject.scale
matches the call.
Overridden method signature does not match
call
, where it is passed too many arguments. Overriding method
method VMobject.scale
matches the call.
Overridden method signature does not match
call
, where it is passed too many arguments. Overriding method
method VMobject.scale
matches the call.
Overridden method signature does not match
call
, where it is passed too many arguments. Overriding method
method VMobject.scale
matches the call.
@henrikmidtiby
Copy link
Contributor Author

henrikmidtiby commented Aug 11, 2025

One of the main contributions in this PR is that when accessing elements in a VGroup, the type of these elements are now recognized as VMobjects.

This is achieved by adding/modifying these methods including type annotations to the VMobject class.

def __iter__(self) -> Iterator[VMobject]:
    return iter(self.split())
def split(self) -> list[VMobject]:
    result: list[VMobject] = [self] if len(self.points) > 0 else []
    return result + self.submobjects

And these to the VGroup class.

def __getitem__(self, key: int) -> VMobject:
    return self.submobjects[key]

Replace self.lines with self.lines_chars and self.lines_alignment.
@henrikmidtiby henrikmidtiby changed the title Typing mobject.py Add type annotations to mobject.py Aug 13, 2025
@henrikmidtiby henrikmidtiby mentioned this pull request Aug 13, 2025
22 tasks
@henrikmidtiby henrikmidtiby marked this pull request as ready for review August 21, 2025 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 New
Development

Successfully merging this pull request may close these issues.

1 participant