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

Use autodoc for Python API reference #1172

Open
brenthuisman opened this issue Oct 5, 2020 · 4 comments
Open

Use autodoc for Python API reference #1172

brenthuisman opened this issue Oct 5, 2020 · 4 comments
Assignees
Labels
documentation Documentation itself, or building and deployment of documentation.
Projects

Comments

@brenthuisman
Copy link
Contributor

brenthuisman commented Oct 5, 2020

Using the sphinx.ext.autodoc plugin to autogenerate Python Api documentation accomplishes the following:

  • API documentation is never out of sync with the code.
  • Less work: write documentation once!
  • Consistency: help() and the docs will show the same documentation.

Requirements:

Options:

  • Module, class, member function or variable documentation can be inlined anywhere in the docs to facilitate deviation in the docs w.r.t docstrings if needed. Let's do this as little as possible (creates one more thing to track!).
  • Autodoc shows all members by default. Can be tuned, this removes everything I consider noise for a full module documentation page:
.. automodule:: arbor
    :imported-members:
    :members:
    :undoc-members:
    :special-members: __init__
    :inherited-members:
@brenthuisman brenthuisman added the documentation Documentation itself, or building and deployment of documentation. label Oct 5, 2020
@brenthuisman brenthuisman added this to Backlog in Arbor-dev via automation Feb 4, 2021
@brenthuisman brenthuisman changed the title Auto-generate Python API reference Use autodoc for Python API reference Feb 5, 2021
@brenthuisman brenthuisman self-assigned this Feb 5, 2021
@brenthuisman brenthuisman added the AEP Arbor Enhancement Proposal label Feb 5, 2021
@brenthuisman brenthuisman removed the AEP Arbor Enhancement Proposal label Mar 19, 2021
@brenthuisman brenthuisman moved this from Backlog to Next Release in Arbor-dev Mar 19, 2021
@brenthuisman
Copy link
Contributor Author

brenthuisman commented Mar 29, 2021

Regarding type signatures, things are hairy. An incomplete list of ingredients/options for generation the eventual html docs:

Python code:

Python docstrings:

Signatures in docs is a duplication of information that you have to keep synchronized with API manually, and therefore has not my preference.

Pybind:

Sphinx:

  • distinguishes type labels/field from type option/hint and formats them differently. I strongly prefer type options/hints. In the image: field/label up top, option/hint on the bottom image
    As you see in the comment, I'm unable to generate a type option/hint from docstrings currently.

Various stubgens:

  • pygenstub: does not generate type options/hints for member funcs.
  • pybind11-stubgen generates stubs and copies docstrings, but fails to resolve some C++ types and does not seem to handle overloads; only shows func(*args, **kwargs) -> Any type of signatures in such case.
  • mypy-stubgen. Does good job at type resolution (succeeds where pybind11-stubgen fails), but does not preserve docstrings. Misses some types still.
  • The Sphinx Autodoc plugin sadly ignores type information provided in .pyi files.
    • They are actually valid Python code, so they could be used together with autodoc. However, the output is unordered, so there are many objects referred while not yet defined. Looked into MagicMock or other ways to autocorrect the order, no succes.

Problem:

  • I want type option/hint output for any members, including readonly properties. Lower example in image demonstrates this.
  • Sphinx/autodoc ignore type signatures on properties, which is how Pybind translates .def_readonly() etc. Bug in Python, so that seems why Sphinx can't generate the desired output, and pydoc doesn't show it (eg pydoc arbor.location.branch)
    • Using stubgen, we can verify that Pybind generates the correct signatures (arbor.location.branch has one). Using Pydoc, you can see that type information is not shown, indicating it never reaches Sphinx.
  • Overloaded methods are not handled: Rework function signatures in docstrings of overloaded functions pybind/pybind11#2621

Summary:

At this time I'm not able to get the outputs (pervasive type options/hints) automatically generated, or documented in member docstrings. Potential alternatives that are not sufficient after all:

  • Use mypy-stubgen generated stubs as importable modules for autdoc. This requires solving unconverted types, and does not work around the fact that docutils (?) does not show type info on properties.
  • Document members in the class docstring. This duplicates info, and thus imposes a minor maintenance burden. This formats members yet another way, namely with a parameters label/field, but at least the type info is inline. Type info entered thus not available through help()/pydoc. Also, type info is not rendered as option/hint.
  • Change nothing. Document members in the Sphinx sources as we do now. Is duplication, further removed from the code so an increased maintenance burden compared to previous option/hint. Type info entered thus not available through help()/pydoc.

Action:

@brenthuisman
Copy link
Contributor Author

##An option in the meantime:

In an earlier PR #1176, I wrote a script that hooks into Sphinx to dump the reST generated by autodoc to disk.

We could generate the autodoc reST out of band, demo, and then add in the type annotation by hand. For instance, arbor.location as generated from current docstrings:

.. py:class:: location(self: arbor.location, branch: int, pos: float) -> None
   :noindex:
   :module: arbor

   A location on a cable cell.

   A location on :attr:`branch`, where :attr:`pos`, in the range ``0 ≤ pos ≤ 1``,
   gives the relative position
   between the proximal and distal ends of the branch. The position is in terms
   of branch path length, so for example, on a branch of path length 100 μm ``pos=0.2``
   corresponds to 20 μm and 80 μm from the proximal and distal ends of the
   branch respectively.


   .. py:method:: location.branch
      :noindex:
      :module: arbor
      :property:

      The id of the branch.


   .. py:method:: location.pos
      :noindex:
      :module: arbor
      :property:

      The relative position on the branch (∈ [0.,1.], where 0. means proximal and 1. distal).

Adding in the type annotations by hand for the getters isn't much work:

.. py:class:: location(self: arbor.location, branch: int, pos: float) -> None
   :noindex:
   :module: arbor

   A location on a cable cell.

   A location on :attr:`branch`, where :attr:`pos`, in the range ``0 ≤ pos ≤ 1``,
   gives the relative position
   between the proximal and distal ends of the branch. The position is in terms
   of branch path length, so for example, on a branch of path length 100 μm ``pos=0.2``
   corresponds to 20 μm and 80 μm from the proximal and distal ends of the
   branch respectively.


   .. py:method:: location.branch() -> int
      :noindex:
      :module: arbor
      :property:

      The id of the branch.


   .. py:method:: location.pos() -> float
      :noindex:
      :module: arbor
      :property:

      The relative position on the branch (∈ [0.,1.], where 0. means proximal and 1. distal).

Which produces acceptable output:
Naamloos

Updating is manual, but by checking the full reference in, a difftool can be used.

@brenthuisman brenthuisman moved this from Next Release to Backlog in Arbor-dev May 18, 2021
@thorstenhater
Copy link
Contributor

Hi,

this has been dormant for quite some time, what's the current stance on this?

@brenthuisman
Copy link
Contributor Author

Took a tour of the above linked blocking issues/PRs, no progress:

python/cpython#83306
pybind/pybind11#2621
sphinx-doc/sphinx#4824

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Documentation itself, or building and deployment of documentation.
Projects
Arbor-dev
Backlog
Development

No branches or pull requests

2 participants