Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typings to tex_mobject.py and numbers.py #4015

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

chopan050
Copy link
Contributor

Important remarks:

  • For some reason, MyPy can't determine the type of VMobject.color, even when I add typings to Mobject.color and OpenGLMobject.color. For this reason, I added # type: ignore [has-type] comments every time the .color attribute was used.
  • I added a TextLike type alias. I didn't know how to make it a TypeVar for a more proper usage in DecimalNumber._string_to_mob(), because MyPy always reported a Type variable TextLike is unbound error, and I couldn't cover the different possible cases. Any suggestions are welcome.

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

manim/mobject/text/numbers.py Dismissed Show dismissed Hide dismissed
manim/mobject/text/numbers.py Dismissed Show dismissed Hide dismissed
manim/mobject/text/numbers.py Dismissed Show dismissed Hide dismissed
manim/mobject/text/numbers.py Dismissed Show dismissed Hide dismissed
manim/mobject/text/numbers.py Dismissed Show dismissed Hide dismissed
manim/mobject/text/tex_mobject.py Dismissed Show dismissed Hide dismissed
sub_families = [x.get_family() for x in self.submobjects]
all_mobjects = [self] + list(it.chain(*sub_families))
return remove_list_redundancies(all_mobjects)

def family_members_with_points(self) -> list[Self]:
def family_members_with_points(self) -> Sequence[Self]:
return [m for m in self.get_family() if m.get_num_points() > 0]
Copy link

Choose a reason for hiding this comment

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

Isn't the usual recommendation to have type annotations for function inputs be as general as possible and have type annotations for function outputs be as specific as possible? It's similar to Postel's law: "be conservative in what you send, be liberal in what you accept". So, I think the return types here should be list[...].

Copy link
Contributor Author

@chopan050 chopan050 Nov 14, 2024

Choose a reason for hiding this comment

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

That's generally very true, but there's an issue with returning, say, a list[Mobject]: subclasses like VMobject cannot be typehinted to return a list[VMobject], because both lists are incompatible, even though VMobject is a subclass of Mobject. This does not happen when we use Sequence, which makes it the most specific type without that issue.

Therefore, the rule we apply here is:

  • If it's a method of a class meant to be subclassed, use Sequence.
  • Otherwise, use list. There are some plain functions, not methods, which are typehinted to return a list.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure that this logic applies here, because of the usage of Self. From a quick test it seems that we should be able to do it with list.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to use list because of an error MyPy threw. Somewhere, I had a list of SingleStringMathTex and MyPy couldn't let me append a MathTex. I'll take a look again to see if there's another way of solving this, though.

Copy link
Member

@JasonGrace2282 JasonGrace2282 left a comment

Choose a reason for hiding this comment

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

Amazing PR, these are not easy modules to get through with type hinting :)

Comment on lines +107 to +110
self.name: str = self.__class__.__name__ if name is None else name
self.dim: int = dim
self.target: Mobject | None = target
self.z_index: float = z_index
Copy link
Member

Choose a reason for hiding this comment

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

It's kind of weird that mypy doesn't infer these? It should be able to 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should be able to infer them. I've just seen a lot of attribute typehints around the source code, so I thought I should do the same here.

sub_families = [x.get_family() for x in self.submobjects]
all_mobjects = [self] + list(it.chain(*sub_families))
return remove_list_redundancies(all_mobjects)

def family_members_with_points(self) -> list[Self]:
def family_members_with_points(self) -> Sequence[Self]:
return [m for m in self.get_family() if m.get_num_points() > 0]
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure that this logic applies here, because of the usage of Self. From a quick test it seems that we should be able to do it with list.

Comment on lines +114 to +126
self.number: float | complex = number
self.num_decimal_places: int = num_decimal_places
self.include_sign: bool = include_sign
self.mob_class: type[TextLike] = mob_class
self.group_with_commas: bool = group_with_commas
self.digit_buff_per_font_unit: float = digit_buff_per_font_unit
self.show_ellipsis: bool = show_ellipsis
self.unit: str | None = unit
self.unit_buff_per_font_unit: float = unit_buff_per_font_unit
self.include_background_rectangle: bool = include_background_rectangle
self.edge_to_fix: Vector3D = edge_to_fix
self._font_size: float = font_size
self.fill_opacity: float = fill_opacity
Copy link
Member

Choose a reason for hiding this comment

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

Again, this feels a little bit suspicious - mypy should be able to figure out types from assignment?

manim/mobject/text/numbers.py Outdated Show resolved Hide resolved
manim/mobject/text/numbers.py Show resolved Hide resolved
manim/mobject/text/tex_mobject.py Outdated Show resolved Hide resolved
manim/mobject/text/tex_mobject.py Outdated Show resolved Hide resolved
manim/mobject/text/tex_mobject.py Outdated Show resolved Hide resolved
manim/mobject/text/tex_mobject.py Outdated Show resolved Hide resolved
mypy.ini Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 👀 In review
Development

Successfully merging this pull request may close these issues.

3 participants