|
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