summaryrefslogtreecommitdiff
path: root/doc/development/tutorials
diff options
context:
space:
mode:
authorigo95862 <igo95862@yandex.ru>2021-03-08 12:18:25 +0300
committerigo95862 <igo95862@yandex.ru>2021-03-09 17:56:46 +0300
commit1ac05a2a832dfecfbf9431e919cb9f3b99ebf11f (patch)
treebee385fc213df9a3a647c7a392e671014379127f /doc/development/tutorials
parentff49bfa003b1caf67edb146181ecec234ee647de (diff)
downloadsphinx-git-1ac05a2a832dfecfbf9431e919cb9f3b99ebf11f.tar.gz
doc: Create autodoc extension tutorial
Diffstat (limited to 'doc/development/tutorials')
-rw-r--r--doc/development/tutorials/autodoc_ext.rst140
-rw-r--r--doc/development/tutorials/examples/autodoc_intenum.py52
2 files changed, 192 insertions, 0 deletions
diff --git a/doc/development/tutorials/autodoc_ext.rst b/doc/development/tutorials/autodoc_ext.rst
new file mode 100644
index 000000000..eca0e5120
--- /dev/null
+++ b/doc/development/tutorials/autodoc_ext.rst
@@ -0,0 +1,140 @@
+Developing autodoc extension for IntEnum
+========================================
+
+The objective of this tutorial is to create an extension that adds
+support for new type for autodoc. This autodoc extension will format
+the ``IntEnum`` class from Python standard library. (module ``enum``)
+
+Overview
+--------
+
+We want the extension that will create auto-documentation for IntEnum.
+``IntEnum`` is the integer enum class from standard library ``enum`` module.
+
+Currently this class has no special auto documentation behavior.
+
+We want to add following to autodoc:
+
+* A new ``autointenum`` directive that will document the ``IntEnum`` class.
+* The generated documentation will have all the enum possible values
+ with names.
+* The ``autointenum`` directive will have an option ``:hex:`` which will
+ cause the integers be printed in hexadecimal form.
+
+
+Prerequisites
+-------------
+
+We need the same setup as in :doc:`the previous extensions <todo>`. This time,
+we will be putting out extension in a file called :file:`autodoc_intenum.py`.
+The :file:`my_enums.py` will contain the sample enums we will document.
+
+Here is an example of the folder structure you might obtain:
+
+.. code-block:: text
+
+ └── source
+    ├── _ext
+ │   └── autodoc_intenum.py
+    ├── conf.py
+    ├── index.rst
+    └── my_enums.py
+
+
+Writing the extension
+---------------------
+
+Start with ``setup`` function for the extension.
+
+.. literalinclude:: examples/autodoc_intenum.py
+ :language: python
+ :linenos:
+ :pyobject: setup
+
+
+The :meth:`~Sphinx.setup_extension` method will pull the autodoc extension
+because our new extension depends on autodoc. :meth:`~Sphinx.add_autodocumenter`
+is the method that registers our new auto documenter class.
+
+We want to import certain objects from the autodoc extension:
+
+.. literalinclude:: examples/autodoc_intenum.py
+ :language: python
+ :linenos:
+ :lines: 1-7
+
+
+There are several different documenter classes such as ``MethodDocumenter``
+or ``AttributeDocumenter`` available in the autodoc extension but
+our new class is the subclass of ``ClassDocumenter`` which a
+documenter class used by autodoc to document classes.
+
+This is the definition of our new the auto-documenter class:
+
+.. literalinclude:: examples/autodoc_intenum.py
+ :language: python
+ :linenos:
+ :pyobject: IntEnumDocumenter
+
+
+Important attributes of the new class:
+
+**objtype**
+ This attribute determines the ``auto`` directive name. In
+ this case the auto directive will be ``autointenum``.
+
+**directivetype**
+ This attribute sets the generated directive name. In
+ this example the generated directive will be ``.. :py:class::``.
+
+**priority**
+ the larger the number the higher is the priority. We want our
+ documenter be higher priority than the parent.
+
+**option_spec**
+ option specifications. We copy the parent class options and
+ add a new option *hex*.
+
+
+Overridden members:
+
+**can_document_member**
+ This member is important to override. It should
+ return *True* when the passed object can be documented by this class.
+
+**add_directive_header**
+ This method generates the directive header. We add
+ **:final:** directive option. Remember to call **super** or no directive
+ will be generated.
+
+**add_content**
+ This method generates the body of the class documentation.
+ After calling the super method we generate lines for enum description.
+
+
+Using the extension
+-------------------
+
+You can now use the new autodoc directive to document any ``IntEnum``.
+
+For example, you have the following ``IntEnum``:
+
+.. code-block:: python
+ :caption: my_enums.py
+
+ class Colors(IntEnum):
+ """Colors enumerator"""
+ NONE = 0
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+
+
+This will be the documentation file with auto-documentation directive:
+
+.. code-block:: rst
+ :caption: index.rst
+
+ .. autointenum:: my_enums.Colors
+
+
diff --git a/doc/development/tutorials/examples/autodoc_intenum.py b/doc/development/tutorials/examples/autodoc_intenum.py
new file mode 100644
index 000000000..7fb85d066
--- /dev/null
+++ b/doc/development/tutorials/examples/autodoc_intenum.py
@@ -0,0 +1,52 @@
+from enum import IntEnum
+from typing import Any, Optional
+
+from docutils.statemachine import StringList
+
+from sphinx.application import Sphinx
+from sphinx.ext.autodoc import ClassDocumenter, bool_option
+
+
+class IntEnumDocumenter(ClassDocumenter):
+ objtype = 'intenum'
+ directivetype = 'class'
+ priority = 10 + ClassDocumenter.priority
+ option_spec = dict(ClassDocumenter.option_spec)
+ option_spec['hex'] = bool_option
+
+ @classmethod
+ def can_document_member(cls,
+ member: Any, membername: str,
+ isattr: bool, parent: Any) -> bool:
+ return isinstance(member, IntEnum)
+
+ def add_directive_header(self, sig: str) -> None:
+ super().add_directive_header(sig)
+ self.add_line(' :final:', self.get_sourcename())
+
+ def add_content(self,
+ more_content: Optional[StringList],
+ no_docstring: bool = False
+ ) -> None:
+
+ super().add_content(more_content, no_docstring)
+
+ source_name = self.get_sourcename()
+ enum_object: IntEnum = self.object
+ use_hex = self.options.hex
+ self.add_line('', source_name)
+
+ for enum_value in enum_object:
+ the_value_name = enum_value.name
+ the_value_value = enum_value.value
+ if use_hex:
+ the_value_value = hex(the_value_value)
+
+ self.add_line(
+ f"**{the_value_name}**: {the_value_value}", source_name)
+ self.add_line('', source_name)
+
+
+def setup(app: Sphinx) -> None:
+ app.setup_extension('sphinx.ext.autodoc') # Require autodoc extension
+ app.add_autodocumenter(IntEnumDocumenter)