| 
2 | 2 | Adding Typings  | 
3 | 3 | ==============  | 
4 | 4 | 
 
  | 
 | 5 | +.. warning::  | 
 | 6 | +   This section is still a work in progress.  | 
 | 7 | + | 
5 | 8 | Adding type hints to functions and parameters  | 
6 | 9 | ---------------------------------------------  | 
7 | 10 | 
 
  | 
8 |  | -.. warning::  | 
9 |  | -   This section is still a work in progress.  | 
 | 11 | +Manim is currently in the process of adding type hints into the library. In this  | 
 | 12 | +section, you will find information about the standards used and some general  | 
 | 13 | +guidelines.  | 
10 | 14 | 
 
  | 
11 | 15 | If you've never used type hints before, this is a good place to get started:  | 
12 | 16 | https://realpython.com/python-type-checking/#hello-types.  | 
13 | 17 | 
 
  | 
14 |  | -When adding type hints to manim, there are some guidelines that should be followed:  | 
 | 18 | +Typing standards  | 
 | 19 | +~~~~~~~~~~~~~~~~  | 
15 | 20 | 
 
  | 
16 |  | -* Coordinates have the typehint ``Sequence[float]``, e.g.  | 
 | 21 | +Manim uses `mypy`_ to type check its codebase. You will find a list of  | 
 | 22 | +configuration values in the ``mypy.ini`` configuration file.  | 
17 | 23 | 
 
  | 
18 |  | -.. code:: py  | 
 | 24 | +To be able to use the newest typing features not available in the lowest  | 
 | 25 | +supported Python version, make use of `typing_extensions`_.  | 
19 | 26 | 
 
  | 
20 |  | -    def set_points_as_corners(self, points: Sequence[float]) -> "VMobject":  | 
21 |  | -        """Given an array of points, set them as corner of the Vmobject."""  | 
 | 27 | +To be able to use the new Union syntax (``|``) and builtins subscripting, use  | 
 | 28 | +the ``from __future__ import annotations`` import.  | 
22 | 29 | 
 
  | 
23 |  | -* ``**kwargs`` has no typehint  | 
 | 30 | +.. _mypy: https://mypy-lang.org/  | 
 | 31 | +.. _typing_extensions: https://pypi.org/project/typing-extensions/  | 
24 | 32 | 
 
  | 
25 |  | -* Mobjects have the typehint "Mobject", e.g.  | 
 | 33 | +Typing guidelines  | 
 | 34 | +~~~~~~~~~~~~~~~~~  | 
26 | 35 | 
 
  | 
27 |  | -.. code:: py  | 
 | 36 | +* Manim has a dedicated :mod:`~.typing` module where type aliases are provided.  | 
 | 37 | +  Most of them may seem redundant, in particular the ones related to ``numpy``.  | 
 | 38 | +  This is in anticipation of the support for shape type hinting  | 
 | 39 | +  (`related issue <https://github.com/numpy/numpy/issues/16544>`_). Besides the  | 
 | 40 | +  pending shape support, using the correct type aliases will help users understand  | 
 | 41 | +  which shape should be used.  | 
28 | 42 | 
 
  | 
29 |  | -    def match_color(self, mobject: "Mobject"):  | 
30 |  | -        """Match the color with the color of another :class:`~.Mobject`."""  | 
31 |  | -        return self.set_color(mobject.get_color())  | 
32 |  | -
  | 
33 |  | -* Colors have the typehint ``Color``, e.g.  | 
34 |  | - | 
35 |  | -.. code:: py  | 
36 |  | -
  | 
37 |  | -    def set_color(self, color: Color = YELLOW_C, family: bool = True):  | 
38 |  | -        """Condition is function which takes in one arguments, (x, y, z)."""  | 
39 |  | -
  | 
40 |  | -* As ``float`` and ``Union[int, float]`` are the same, use only ``float``  | 
41 |  | - | 
42 |  | -* For numpy arrays use the typehint ``np.ndarray``  | 
43 |  | - | 
44 |  | -* Functions that does not return a value should get the type hint ``None``. (This annotations help catch the kinds of subtle bugs where you are trying to use a meaningless return value. )  | 
 | 43 | +* Always use a type hint of ``None`` for functions that does not return  | 
 | 44 | +  a value (this also applies to ``__init__``), e.g.:  | 
45 | 45 | 
 
  | 
46 | 46 | .. code:: py  | 
47 | 47 | 
  | 
48 | 48 |     def height(self, value) -> None:  | 
49 | 49 |         self.scale_to_fit_height(value)  | 
50 | 50 | 
  | 
51 |  | -* Parameters that are None by default should get the type hint ``Optional``  | 
52 |  | - | 
53 |  | -.. code:: py  | 
 | 51 | +* For variables representing paths, use the ``StrPath`` or ``StrOrBytesPath``  | 
 | 52 | +  type alias defined in the :mod:`~.typing` module.  | 
54 | 53 | 
 
  | 
55 |  | -    def rotate(  | 
56 |  | -        self,  | 
57 |  | -        angle,  | 
58 |  | -        axis=OUT,  | 
59 |  | -        about_point: Optional[Sequence[float]] = None,  | 
60 |  | -        **kwargs,  | 
61 |  | -    ):  | 
62 |  | -        pass  | 
 | 54 | +* ``*args`` and ``**kwargs`` shouldn't be left untyped (in most cases you can  | 
 | 55 | +  use ``Any``).  | 
63 | 56 | 
 
  | 
 | 57 | +* Following `PEP 484 <https://peps.python.org/pep-0484/#the-numeric-tower>`_,  | 
 | 58 | +  use ``float`` instead of ``int | float``.  | 
64 | 59 | 
 
  | 
65 |  | -* The ``__init__()`` method always should have None as its return type.  | 
66 |  | - | 
67 |  | -* Functions and lambda functions should get the typehint ``Callable``  | 
 | 60 | +* Mobjects have the typehint ``Mobject``, e.g.:  | 
68 | 61 | 
 
  | 
69 | 62 | .. code:: py  | 
70 | 63 | 
  | 
71 |  | -    rate_func: Callable[[float], float] = lambda t: smooth(1 - t)  | 
72 |  | -
  | 
73 |  | -
  | 
74 |  | -* Assuming that typical path objects are either Paths or strs, one can use the typehint ``typing.Union[str, pathlib.Path]``  | 
 | 64 | +    def match_color(self, mobject: "Mobject"):  | 
 | 65 | +        """Match the color with the color of another :class:`~.Mobject`."""  | 
 | 66 | +        return self.set_color(mobject.get_color())  | 
75 | 67 | 
  | 
76 |  | -.. note::  | 
77 |  | -   As a helper for tool for typesets, you can use `typestring-parser  | 
78 |  | -   <https://github.com/Dominik1123/typestring-parser>`_  | 
79 |  | -   which can be accessed by first installing it via ``pip`` - ``pip install typestring-parser`` and  | 
80 |  | -   then using ``from typestring_parser import parse``.  | 
 | 68 | +* Always parametrize generics (``list[int]`` instead of ``list``,  | 
 | 69 | +  ``type[Any]`` instead of ``type``, etc.). This also applies to callables:  | 
81 | 70 | 
 
  | 
82 |  | -.. doctest::  | 
83 |  | -    :options: +SKIP  | 
 | 71 | +.. code:: py  | 
84 | 72 | 
  | 
85 |  | -    >>> from typestring_parser import parse  | 
86 |  | -    >>> parse("int")  | 
87 |  | -    <class 'int'>  | 
88 |  | -    >>> parse("int or str")  | 
89 |  | -    typing.Union[int, str]  | 
90 |  | -    >>> parse("list of str or str")  | 
91 |  | -    typing.Union[typing.List[str], str]  | 
92 |  | -    >>> parse("list of (int, str)")  | 
93 |  | -    typing.List[typing.Tuple[int, str]]  | 
 | 73 | +    rate_func: Callable[[float], float] = lambda t: smooth(1 - t)  | 
94 | 74 | 
  | 
95 | 75 | Missing Sections for typehints are:  | 
96 | 76 | -----------------------------------  | 
97 |  | -* Tools for typehinting  | 
98 |  | -* Link to MyPy  | 
 | 77 | + | 
99 | 78 | * Mypy and numpy import errors: https://realpython.com/python-type-checking/#running-mypy  | 
100 |  | -* Where to find the alias  | 
101 |  | -* When to use Object and when to use "Object".  | 
102 |  | -* The use of a TypeVar on the type hints for copy().  | 
103 |  | -* The definition and use of Protocols (like Sized, or Sequence, or Iterable...)  | 
 | 79 | +* When to use ``object`` vs ``Any``  | 
 | 80 | +* The use of a TypeVar on the type hints for ``copy()``.  | 
 | 81 | +* The definition and use of Protocols (like ``Sized``, ``Sequence``, ``Iterable``...)  | 
0 commit comments