mirror of
https://github.com/ManimCommunity/manim.git
synced 2026-06-22 10:01:47 +00:00
* adding codespell precommit hook * adding codespell config file * fixing typos * tweaking variable names to please codespell
592 lines
20 KiB
ReStructuredText
592 lines
20 KiB
ReStructuredText
====================
|
||
Adding Documentation
|
||
====================
|
||
|
||
When submitting a new class through a PR, or any changes in general,
|
||
there should be documentation where possible. Here are our guidelines
|
||
for writing documentation.
|
||
|
||
Guidelines for examples
|
||
-----------------------
|
||
|
||
Everybody is welcome to contribute examples to the documentation. Since straightforward examples are a great resource for quickly learning manim, here are some guidelines.
|
||
|
||
What makes a great example
|
||
--------------------------
|
||
|
||
.. note::
|
||
|
||
As soon as a new version of manim is released, the documentation will be a snapshot of that version. Examples contributed after the release will only be shown in the latest documentation.
|
||
|
||
* Examples should be ready to copy and paste for use.
|
||
|
||
* Examples should be brief yet still easy to understand.
|
||
|
||
* Examples don't require the ``from manim import *`` statement, this will be added automatically when the docs are built.
|
||
|
||
* There should be a balance of animated and non-animated examples.
|
||
|
||
- As manim makes animations, we can include lots of animated examples; however, our RTD has a maximum 15 minutes to build. Animated examples should only be used when necessary, as last frame examples render faster.
|
||
|
||
- Lots of examples (e.g. size of a plot-axis, setting opacities, making texts, etc.) will also work as images. It is a lot more convenient to see the end product immediately instead of waiting for an animation to reveal it.
|
||
|
||
* Please ensure the examples run on the current master when you contribute an example.
|
||
|
||
How examples are structured
|
||
---------------------------
|
||
|
||
* Examples can be organized into chapters and subchapters.
|
||
|
||
- When you create examples, the beginning example chapter should focus on only one functionality. When the functionality is simple, multiple ideas can be illustrated under a single example.
|
||
|
||
- As soon as simple functionalities are explained, the chapter may include more complex examples which build on the simpler ideas.
|
||
|
||
Writing examples
|
||
~~~~~~~~~~~~~~~~
|
||
|
||
When you want to add/edit examples, they can be found in the ``docs/source/`` directory, or directly in the manim source code (e.g. ``manim/mobject/mobject.py``). The examples are written in
|
||
``rst`` format and use the manim directive (see :mod:`~.manim_directive` ), ``.. manim::``. Every example is in its own block, and looks like this:
|
||
|
||
.. code:: rst
|
||
|
||
Formulas
|
||
========
|
||
|
||
.. manim:: Formula1
|
||
:save_last_frame:
|
||
|
||
class Formula1(Scene):
|
||
def construct(self):
|
||
t = MathTex(r"\int_a^b f'(x) dx = f(b) - f(a)")
|
||
self.add(t)
|
||
self.wait(1)
|
||
|
||
In the building process of the docs, all ``rst`` files are scanned, and the
|
||
manim directive (``.. manim::``) blocks are identified as scenes that will be run
|
||
by the current version of manim.
|
||
Here is the syntax:
|
||
|
||
* ``.. manim:: [SCENE_NAME]`` has no indentation and ``SCENE_NAME`` refers to the name of the class below.
|
||
|
||
* The flags are followed in the next line (no blank line here!), with the indentation level of one tab.
|
||
|
||
All possible flags can be found at :mod:`~.manim_directive`.
|
||
|
||
In the example above, the ``Formula1`` following ``.. manim::`` is the scene
|
||
that the directive expects to render; thus, in the python code, the class
|
||
has the same name: ``class Formula1(Scene)``.
|
||
|
||
.. note::
|
||
|
||
Sometimes, when you reload an example in your browser, it has still the old
|
||
website somewhere in its cache. If this is the case, delete the website cache,
|
||
or open a new incognito tab in your browser, then the latest docs
|
||
should be shown.
|
||
**Only for locally built documentation:** If this still doesn't work, you may need
|
||
to delete the contents of ``docs/source/references`` before rebuilding
|
||
the documentation.
|
||
|
||
Formatting and Running Tests
|
||
----------------------------
|
||
|
||
Please begin the description of the class/function in the same line as
|
||
the 3 quotes:
|
||
|
||
.. code:: py
|
||
|
||
def do_this():
|
||
"""This is correct.
|
||
(...)
|
||
"""
|
||
|
||
|
||
def dont_do_this():
|
||
"""
|
||
This is incorrect.
|
||
(...)
|
||
"""
|
||
|
||
NumPy Format
|
||
------------
|
||
|
||
Use the numpy format for sections and formatting - see
|
||
https://numpydoc.readthedocs.io/en/latest/format.html.
|
||
|
||
This includes:
|
||
|
||
1. The usage of ``Attributes`` to specify ALL ATTRIBUTES that a
|
||
class can have, their respective types, and a brief (or long, if
|
||
needed) description. (See more on :ref:`types<types>`)
|
||
|
||
Also, ``__init__`` parameters should be specified as ``Parameters`` **on
|
||
the class docstring**, *rather than under* ``__init__``. Note that this
|
||
can be omitted if the parameters and the attributes are the same
|
||
(i.e., dataclass) - priority should be given to the ``Attributes``
|
||
section, in this case, which must **always be present**, unless the
|
||
class specifies no attributes at all. (See more on Parameters in number
|
||
2 of this list.)
|
||
|
||
Example:
|
||
|
||
.. code:: py
|
||
|
||
class MyClass:
|
||
"""My cool class. Long or short (whatever is more appropriate) description here.
|
||
|
||
Parameters
|
||
----------
|
||
name : :class:`str`
|
||
The class's name.
|
||
id : :class:`int`
|
||
The class's id.
|
||
mobj : Optional[:class:`~.Mobject`], optional
|
||
The mobject linked to this instance. Defaults to `Mobject()` \
|
||
(is set to that if `None` is specified).
|
||
|
||
Attributes
|
||
----------
|
||
name : :class:`str`
|
||
The user's name.
|
||
id : :class:`int`
|
||
The user's id.
|
||
singleton : :class:`MyClass`
|
||
Something.
|
||
mobj : :class:`~.Mobject`
|
||
The mobject linked to this instance.
|
||
"""
|
||
|
||
def __init__(
|
||
name, id, singleton, mobj=None
|
||
): # in-code typehints are optional for now
|
||
...
|
||
|
||
2. The usage of ``Parameters`` on functions to specify how
|
||
every parameter works and what it does. This should be excluded if
|
||
the function has no parameters. Note that you **should not** specify
|
||
the default value of the parameter on the type. On the documentation
|
||
render, this is already specified on the function's signature. If you
|
||
need to indicate a further consequence of value omission or simply
|
||
want to specify it on the docs, make sure to **specify it in the
|
||
parameter's DESCRIPTION**.
|
||
|
||
See an example on list item 4.
|
||
|
||
.. note::
|
||
|
||
When documenting varargs (args and kwargs), make sure to
|
||
document them by listing the possible types of each value specified,
|
||
like this:
|
||
|
||
::
|
||
|
||
Parameters
|
||
----------
|
||
args : Union[:class:`int`, :class:`float`]
|
||
The args specified can be either an int or a float.
|
||
kwargs : :class:`float`
|
||
The kwargs specified can only be a float.
|
||
|
||
Note that, if the kwargs expect specific values, those can be specified
|
||
in a section such as ``Other Parameters``:
|
||
|
||
::
|
||
|
||
Other Parameters
|
||
----------------
|
||
kwarg_param_1 : :class:`int`
|
||
Parameter documentation here
|
||
(etc)
|
||
|
||
3. The usage of ``Returns`` to indicate what is the type of this
|
||
function's return value and what exactly it returns (i.e., a brief -
|
||
or long, if needed - description of what this function returns). Can
|
||
be omitted if the function does not explicitly return (i.e., always
|
||
returns ``None`` because ``return`` is never specified, and it is
|
||
very clear why this function does not return at all). In all other
|
||
cases, it should be specified.
|
||
|
||
See an example on list item 4.
|
||
|
||
4. The usage of ``Examples`` in order to specify an example of usage of
|
||
a function **is highly encouraged** and, in general, should be
|
||
specified for *every function* unless its usage is **extremely
|
||
obvious**, which can be debatable. Even if it is, it's always a good
|
||
idea to add an example in order to give a better orientation to the
|
||
documentation user. Use the following format for Python code:
|
||
|
||
.. code:: rst
|
||
|
||
::
|
||
|
||
# python code here
|
||
|
||
.. note::
|
||
Also, if this is a video- or animation-related change, please
|
||
try to add an example GIF or video if possible for demonstration
|
||
purposes.
|
||
|
||
Make sure to be as explicit as possible in your documentation. We all
|
||
want the users to have an easier time using this library.
|
||
|
||
Example:
|
||
|
||
.. code:: py
|
||
|
||
def my_function(thing, other, name, *, d, test=45): # typings are optional for now
|
||
"""My cool function. Builds and modifies an :class:`EpicClassInThisFile` instance with the given
|
||
parameters.
|
||
|
||
Parameters
|
||
----------
|
||
thing : :class:`int`
|
||
Specifies the index of life.
|
||
other : :class:`numpy.ndarray`
|
||
Specifies something cool.
|
||
name : :class:`str`
|
||
Specifies my name.
|
||
d : :class:`~.SomeClassFromFarAway`
|
||
Sets thing D to this value.
|
||
test : :class:`int`, optional
|
||
Defines the amount of times things should be tested. \
|
||
Defaults to 45, because that is almost the meaning of life.
|
||
|
||
Returns
|
||
-------
|
||
:class:`EpicClassInThisFile`
|
||
The generated EpicClass with the specified attributes and modifications.
|
||
|
||
Examples
|
||
--------
|
||
Normal usage::
|
||
|
||
my_function(5, np.array([1, 2, 3]), "Chelovek", d=SomeClassFromFarAway(cool=True), test=5)
|
||
"""
|
||
# code...
|
||
pass
|
||
|
||
.. _types:
|
||
|
||
Reference to types in documentation
|
||
-----------------------------------
|
||
|
||
Always specify types with the correct **role** (see
|
||
https://www.sphinx-doc.org/en/1.7/domains.html#python-roles) for the
|
||
sake of proper rendering. E.g.: Use ``:class:`int``` to refer to an int
|
||
type, and in general ``:class:`<path>``` to refer to a certain class
|
||
(see ``Path specification`` below). See after for more specific
|
||
instructions.
|
||
|
||
Path specifications
|
||
~~~~~~~~~~~~~~~~~~~
|
||
|
||
1. If it's on stdlib: Use ``<name>`` directly. If it's a class, just the
|
||
name is enough. If it's a method (``:meth:``) or attribute
|
||
(``:attr:``), dotted names may be used (e.g.
|
||
``:meth:`str.to_lower```).
|
||
|
||
Example: ``:class:`int```, ``:class:`str```, ``:class:`float```,
|
||
``:class:`bool```
|
||
|
||
2. If it's on the same file as the docstring or, for methods and
|
||
attributes, under the same class, then the name may also be specified
|
||
directly.
|
||
|
||
Example: ``:class:`MyClass``` referring to a class in the same file;
|
||
``:meth:`push``` referring to a method in the same class;
|
||
``:meth:`MyClass.push``` referring to a method in a different class in
|
||
the same file; ``:attr:`color``` referring to an attribute in the same
|
||
class; ``:attr:`MyClass.color``` referring to an attribute in a
|
||
different class in the same file.
|
||
|
||
3. If it's on a different file, then you may either use the full dotted
|
||
name (e.g. ``~manim.animations.Animation``) or simply use the
|
||
shortened way (``~.Animation``). Note that, if there is ambiguity,
|
||
then the full dotted name must be used where the actual class can't
|
||
be deduced. Also, note the ``~`` before the path - this is so that it
|
||
displays just ``Animation`` instead of the full location in the
|
||
rendering. It can be removed for disambiguation purposes only.
|
||
|
||
Example: ``:class:`~.Animation```, ``:meth:`~.VMobject.set_color```,
|
||
``:attr:`~.VMobject.color```
|
||
|
||
4. If it's a class from a different module, specify the full dotted
|
||
syntax.
|
||
|
||
Example: ``:class:`numpy.ndarray``` for a numpy ndarray.
|
||
|
||
Reference type specifications
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
**The following instructions refer to types of attributes, parameters,
|
||
and return values.** When specifying a type mid-text, it does not
|
||
necessarily have to be typeset. However, if it's a class name, a method,
|
||
or an enum's attribute/variant, then it is recommended to be typeset at
|
||
least on the first occurrence of the name so that the users can quickly
|
||
jump to the related documentation.
|
||
|
||
1. Class names should be wrapped in ``:class:`path_goes_here```. See
|
||
examples in the subsection above.
|
||
2. Method names should be wrapped in ``:meth:`path_goes_here```. See
|
||
examples in the subsection above.
|
||
3. Attribute names should be wrapped in ``:attr:`path_goes_here```. See
|
||
examples in the subsection above.
|
||
4. If ``None`` can also be specified, use ``Optional[type]``, where
|
||
``type`` must follow the guidelines in the current section.
|
||
|
||
Example: ``Optional[:class:`str`]`` means you can either specify a
|
||
``str`` or ``None``.
|
||
|
||
5. If more than one type is possible, use
|
||
``Union[type_1, type_2, (...), type_n]``, where all the ``type_n``
|
||
must follow the guidelines in the current section. Note that, if one
|
||
of these types is ``None``, then the Union should be wrapped with
|
||
``Optional`` instead.
|
||
|
||
Example: ``Union[:class:`str`, :class:`int`]`` for either ``str`` or
|
||
``int``. ``Optional[Union[:class:`int`, :class:`bool`]]`` for either
|
||
``int``, ``bool`` or ``None``.
|
||
|
||
6. **Dictionaries:** Use ``Dict[key_type, value_type]``, where
|
||
``key_type`` and ``value_type`` must follow the guidelines in the
|
||
current section.
|
||
|
||
Example: ``Dict[:class:`str`, :class:`~.Mobject`]`` is a dictionary that
|
||
maps strings to Mobjects.
|
||
``Dict[:class:`str`, Union[:class:`int`, :class:`MyClass`]]`` is a
|
||
dictionary that maps a string to either an int or an instance of
|
||
``MyClass``.
|
||
|
||
7. **If the parameter is a list:** Note that it is very rare to require
|
||
the parameter to be exactly a ``list`` type. One could usually
|
||
specify a ``tuple`` instead, for example. So, in order to cover all
|
||
cases, consider:
|
||
|
||
1. If the parameter only needs to be an ``Iterable``, i.e., if the
|
||
function only requires being able to iterate over this parameter's
|
||
value (e.g. can be a ``list``, ``tuple``, ``str``, but also
|
||
``zip()``, ``iter()`` and so on), then specify
|
||
``Iterable[type_here]``, where ``type_here`` is the type of the
|
||
iterable's yielded elements and should follow the format in the
|
||
present section (``Type specifications``).
|
||
|
||
Example: ``Iterable[:class:`str`]`` for any iterable of strings;
|
||
``Iterable[:class:`~.Mobject`]`` for an iterable of Mobjects; etc.
|
||
|
||
2. If you require being able to index the parameter (i.e. ``x[n]``)
|
||
or retrieve its length (i.e. ``len(x)``), or even just pass it to
|
||
a function that requires any of those, then specify ``Sequence``,
|
||
which allows any list-like object to be specified (e.g. ``list``,
|
||
``tuple``...)
|
||
|
||
Example: ``Sequence[:class:`str`]`` for a sequence of strings;
|
||
``Sequence[Union[:class:`str`, :class:`int`]]`` for a sequence of
|
||
integers or strings.
|
||
|
||
3. If you EXPLICITLY REQUIRE it to be a ``list`` for some reason,
|
||
then use ``List[type]``, where ``type`` is the type that any
|
||
element in the list will have. It must follow the guidelines in
|
||
the current section.
|
||
|
||
8. **If the return type is a list or tuple:** Specify ``List[type]`` for
|
||
a list, ``Tuple[type_a, type_b, (...), type_n]`` for a tuple (if the
|
||
elements are all different) or ``Tuple[type, ...]`` (if all elements
|
||
have the same type). Each ``type_n`` on those representations
|
||
corresponds to elements in the returned list/tuple and must follow
|
||
the guidelines in the current section.
|
||
|
||
Example: ``List[Optional[:class:`str`]]`` for a list that returns
|
||
elements that are either a ``str`` or ``None``;
|
||
``Tuple[:class:`str`, :class:`int`]`` for a tuple of type
|
||
``(str, int)``; ``Tuple[:class:`int`, ...]`` for a tuple of variable
|
||
length with only integers.
|
||
|
||
.. note::
|
||
As a helper for tool for typesets, you can use `typestring-parser
|
||
<https://github.com/Dominik1123/typestring-parser>`_
|
||
which can be accessed by first installing it via ``pip`` - ``pip install typestring-parser`` and
|
||
then using ``from typestring_parser import parse``.
|
||
|
||
.. doctest::
|
||
:options: +SKIP
|
||
|
||
>>> from typestring_parser import parse
|
||
>>> parse("int")
|
||
<class 'int'>
|
||
>>> parse("int or str")
|
||
typing.Union[int, str]
|
||
>>> parse("list of str or str")
|
||
typing.Union[typing.List[str], str]
|
||
>>> parse("list of (int, str)")
|
||
typing.List[typing.Tuple[int, str]]
|
||
|
||
|
||
Adding type hints to functions and parameters
|
||
---------------------------------------------
|
||
|
||
.. warning::
|
||
This section is still a work in progress.
|
||
|
||
If you've never used type hints before, this is a good place to get started:
|
||
https://realpython.com/python-type-checking/#hello-types.
|
||
|
||
When adding type hints to manim, there are some guidelines that should be followed:
|
||
|
||
* Coordinates have the typehint ``Sequence[float]``, e.g.
|
||
|
||
.. code:: py
|
||
|
||
def set_points_as_corners(self, points: Sequence[float]) -> "VMobject":
|
||
"""Given an array of points, set them as corner of the Vmobject."""
|
||
|
||
* ``**kwargs`` has no typehint
|
||
|
||
* Mobjects have the typehint "Mobject", e.g.
|
||
|
||
.. code:: py
|
||
|
||
def match_color(self, mobject: "Mobject"):
|
||
"""Match the color with the color of another :class:`~.Mobject`."""
|
||
return self.set_color(mobject.get_color())
|
||
|
||
* Colors have the typehint ``Color``, e.g.
|
||
|
||
.. code:: py
|
||
|
||
def set_color(self, color: Color = YELLOW_C, family: bool = True):
|
||
"""Condition is function which takes in one arguments, (x, y, z)."""
|
||
|
||
* As ``float`` and ``Union[int, float]`` are the same, use only ``float``
|
||
|
||
* For numpy arrays use the typehint ``np.ndarray``
|
||
|
||
* 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. )
|
||
|
||
.. code:: py
|
||
|
||
def height(self, value) -> None:
|
||
self.scale_to_fit_height(value)
|
||
|
||
* Parameters that are None by default should get the type hint ``Optional``
|
||
|
||
.. code:: py
|
||
|
||
def rotate(
|
||
self,
|
||
angle,
|
||
axis=OUT,
|
||
about_point: Optional[Sequence[float]] = None,
|
||
**kwargs,
|
||
):
|
||
pass
|
||
|
||
|
||
* the .__init__() method always should have None as its return type.
|
||
|
||
* functions and lambda functions should get the typehint ``Callable``
|
||
|
||
.. code:: py
|
||
|
||
rate_func: Callable[[float], float] = lambda t: smooth(1 - t)
|
||
|
||
* numpy arrays can get type hints with ``np.ndarray``
|
||
|
||
* assuming that typical path objects are either Paths or strs, one can use the typehint ``typing.Union[str, pathlib.Path]``
|
||
|
||
|
||
|
||
Adding Blocks for Tip, Note, Important etc. (Admonitions)
|
||
---------------------------------------------------------
|
||
|
||
The following directives are called Admonitions. You
|
||
can use them to point out additional or important
|
||
information. Here are some examples:
|
||
|
||
See also
|
||
~~~~~~~~
|
||
|
||
.. code-block:: rest
|
||
|
||
.. seealso::
|
||
Some ideas at :mod:`~.tex_mobject`, :class:`~.Mobject`, :meth:`~.Mobject.add_updater`, :attr:`~.Mobject.depth`, :func:`~.make_config_parser`
|
||
|
||
.. seealso::
|
||
Some ideas at :mod:`~.tex_mobject`, :class:`~.Mobject`, :meth:`~.Mobject.add_updater`, :attr:`~.Mobject.depth`, :func:`~.make_config_parser`
|
||
|
||
.. index:: reST directives; note
|
||
|
||
|
||
|
||
Note
|
||
~~~~
|
||
|
||
.. code-block:: rest
|
||
|
||
.. note::
|
||
A note
|
||
|
||
.. note::
|
||
A note
|
||
|
||
Tip
|
||
~~~
|
||
|
||
.. code-block:: rest
|
||
|
||
.. tip::
|
||
A tip
|
||
|
||
.. tip::
|
||
A tip
|
||
|
||
You may also use the admonition **hint**, but this is very similar
|
||
and **tip** is more commonly used in the documentation.
|
||
|
||
Important
|
||
~~~~~~~~~
|
||
|
||
.. code-block:: rest
|
||
|
||
.. important::
|
||
Some important information which should be considered.
|
||
|
||
.. important::
|
||
Some important information which should be considered.
|
||
|
||
Warning
|
||
~~~~~~~
|
||
|
||
.. code-block:: rest
|
||
|
||
.. warning::
|
||
Some text pointing out something that people should be warned about.
|
||
|
||
.. warning::
|
||
Some text pointing out something that people should be warned about.
|
||
|
||
You may also use the admonitions **caution** or even **danger** if the
|
||
severity of the warning must be stressed.
|
||
|
||
Attention
|
||
~~~~~~~~~
|
||
|
||
.. code-block:: rest
|
||
|
||
.. attention::
|
||
A attention
|
||
|
||
.. attention::
|
||
A attention
|
||
|
||
You can find further information about Admonitions here: https://pradyunsg.me/furo/reference/admonitions/
|
||
|
||
|
||
|
||
Missing Sections for typehints are:
|
||
-----------------------------------
|
||
* Tools for typehinting
|
||
* Link to MyPy
|
||
* Mypy and numpy import errors: https://realpython.com/python-type-checking/#running-mypy
|
||
* Where to find the alias
|
||
* When to use Object and when to use "Object".
|
||
* The use of a TypeVar on the type hints for copy().
|
||
* The definition and use of Protocols (like Sized, or Sequence, or Iterable...)
|