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

By default, make Autosummary templates generate documentation pages for classes, functions, exceptions etc #7912

Open
JamesALeedham opened this issue Jul 4, 2020 · 19 comments
Labels
extensions:autosummary type:enhancement enhance or introduce a new feature

Comments

@JamesALeedham
Copy link

Is your feature request related to a problem? Please describe.
The new :recursive: option for sphinx.ext.autosummary is great. I can point Sphinx at the top of my package and have it find every module, however deeply nested. For each module it creates neat summary tables listing all the attributes, classes, exceptions and functions in those modules. This is all fantastic.

To generate actual documentation pages for these attributes, classes, exceptions and functions, however, and link to them from the summary tables, I have to copy the default module.rst and class.rst templates locally and edit them. I would like to think this is what most people would want. So I think it should be the default behavior - and those who don't want this should have to customize the templates.

Describe the solution you'd like
I've described the solution I'd like to see here. There's a Github test implementation here and a sample ReadTheDocs user experience here.

(I'm sure you know what the current user experience is like but, just to be clear, you can reproduce it by cloning the Github test project and deleting the :template: custom-module-template.rst line in docs/source/index.rst.)

Basically, the solution involves adding a :toctree: option to every .. autosummary:: directive in the default module.rst template so that documentation pages get generated for attributes, classes, exceptions and functions out-of-the-box, like this:

site-packages/sphinx/ext/autosummary/templates/autosummary/module.rst (additional lines noted on right):

{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}
  
   {% block attributes %}
   {% if attributes %}
   .. rubric:: Module Attributes

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in attributes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block functions %}
   {% if functions %}
   .. rubric:: {{ _('Functions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in functions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block classes %}
   {% if classes %}
   .. rubric:: {{ _('Classes') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in classes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block exceptions %}
   {% if exceptions %}
   .. rubric:: {{ _('Exceptions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in exceptions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

{% block modules %}
{% if modules %}
.. rubric:: Modules

.. autosummary::
   :toctree:
   :recursive:
{% for item in modules %}
   {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
@JamesALeedham JamesALeedham added the type:enhancement enhance or introduce a new feature label Jul 4, 2020
@tk0miya
Copy link
Member

tk0miya commented Jul 5, 2020

Thank you for proposal. Good idea!
I think it would be better to generate javadoc-like documents. So +1 for adding :toctree: option to module.rst.
https://docs.oracle.com/en/java/javase/13/docs/api/java.logging/java/util/logging/package-summary.html

On the other hand, I prefer to show the methods and attributes of the class in the same file (like Javadoc does). So it would be nice if we'll add autoclass or automethod (autoattributes) to class.rst.
https://docs.oracle.com/en/java/javase/13/docs/api/java.logging/java/util/logging/Logger.html

Anyway, the modification of the template brings a breaking change. So we have to change them on 4.0 release.

@tk0miya
Copy link
Member

tk0miya commented Jul 5, 2020

Note: Adding :toctree: option to module.rst causes recursive stub-file generation for the given module. We should consider the side effect of the change carefully.

@tk0miya tk0miya added this to the 4.0.0 milestone Jul 5, 2020
guyer added a commit to usnistgov/steppyngstounes that referenced this issue Jan 26, 2021
The Sphinx documentation is opaque, to put it mildly, but this
seems to work.

These were helpful:
 - https://romanvm.pythonanywhere.com/post/autodocumenting-your-python-code-sphinx-part-ii-6/
 - sphinx-doc/sphinx#7912
@rickstaa
Copy link

rickstaa commented Feb 25, 2021

@JamesALeedham First of all, thanks a lot for the solution on the StackOverflow question. I think it would make the auto_summary extension even more useful. There are, however, several problems I noticed while using the the StackOverflow question or the solution in this issue:

Stackoverflow version

The solution breaks if classes are imported onto a higher namespace using an init.py file

Let's say we have the following project structure:

└── package
    └── submodule
        ├── __init__.py
        └── subsubmodule
            └── subsubsubmodule.py

Now try to make the package.submodule.subsubmodule.subsubsubmodule.Class available on the package.submodule namespace using the following __init__.py file:

package.submodule.init.py

from package.submodule.subsubmodule.subsubmodule import Class

This prevents the auto summaries for the classes, functions and methods of the package.submodule.subsubmodule.subsubsubmodule from being generated and showing up using the :recursive: option. I still have to add the following code to make them show up manually:

   .. rubric:: Classes

   .. autosummary::
      :toctree:
      :template: custom-class-template.rst
   
      Class


   .. rubric:: Functions

   .. autosummary::
      :toctree:
   
      function_1

This is related to this sphinx issue. This can be solved by using the autosummary_imported_members = True option so should not be such a problem. I however think it would be more user friendly if the autosummary extension was able to show Classes and functions on their original namespace when they are imported onto another namespace inside the same package. This would lead to a cleaner API and also shows docstrings that are placed at the top of the imported modules.

The templates don't work nicely with intersphinx bindings

When I use this workaround combined with the intersphinx bindings, it could lead to possible errors if a class inherits from a base class that contains sphinx errors. I, for example, use the https://github.com/mr-ubik/tensorflow-intersphinx/ TensorFlow bindings, which contain several errors. Therefore, maybe care should be taken when hardcoding the :inherited-members: flag in the template as it seems to overwrite the autodoc_inherit_docstrings = False setting. Just something we should consider when implementing the feature. I think this is related to the comment of @tk0miya.

The version in this issue

When I omit the custom-class-template.rst the problems go away. Now, however, classes and functions are not documented.

@JamesALeedham
Copy link
Author

Hi @rickstaa , thanks for getting back to me. I admit I only tested my solution on a few live projects, and didn't set out to test it exhaustively on a wide set of possible scenarios, so not surprised you've found cases where it doesn't work! Thanks for trying it out...

I'll be guided by what you experts think is best, of course. For my part, when getting started with Sphinx I found it hard to get something that 'quickly' & 'nearly' worked so that I could see I was on the right tracks (and from the responses I've had on StackOverflow and other places I am not alone!).

The goal with my solution (or something similar) is to get a majority of people up and running with something tangible out-of-the-box a bit quicker, and then let people explore Sphinx's myriad settings and options to tailor their experience at their own leisure. I hope it is a step in the right direction there, though naturally I realise it won't entirely work for everyone...

@rickstaa
Copy link

rickstaa commented Mar 6, 2021

@JamesALeedham, I think your solution is good as it works in most use cases. I use it in most of my projects. My previous comment was mainly to provide the sphinx developers like @guyer and @tk0miya with the uses cases in which it does not work. I'm not familiar enough with the sphinx and sphinx.ext.autosummary codebase to develop a solution that also works in the aforementioned use cases.

@guyer
Copy link

guyer commented Mar 7, 2021

@rickstaa I'm not a sphinx developer!

@rickstaa
Copy link

rickstaa commented Mar 7, 2021

Ha @guyer sorry for making that assumption.

@tk0miya tk0miya modified the milestones: 4.0.0, 4.1.0 Apr 11, 2021
@dan0nchik
Copy link

Hey guys! Any progress on this feature?

@tk0miya tk0miya modified the milestones: 4.1.0, 4.2.0 Jul 10, 2021
@vineetsharma883
Copy link

Hey there, waiting for this very useful feature. Can someone share when it would be released in Sphinx?

@vineetsharma883
Copy link

vineetsharma883 commented Jul 28, 2021

I am working with it where I have a following folder structure:-

.
├── README.md
├── __init__.py
├── docs
│   ├── Makefile
│   ├── make.bat
│   └── source
│       ├── _autosummary
│       │   ├── ...
│       ├── _templates
│       │   ├── custom-class-template.rst
│       │   └── custom-module-template.rst
│       ├── conf.py
│       └── index.rst
├── extract
│   ├── README.md
│   ├── __init__.py
│   ├── folder_1
│   │   ├── a.py
│   │   ├── __init__.py
│   │   ├── b.py
│   │   ├── c.py
│   ├── folders_2
│   │   ├── __init__.py
│   │   ├── d.py
│   │   └── e.py
│   ├── folder_3
│   │   ├── __init__.py
│   │   ├── f.py
└── transform
    ├── __init__.py
    ├── g.py
    └── h.py

The script for templates is completely same as given on stackoverflow. Following is my code for index.rst and config.py:-
index.rst

Welcome to sample documentation!
======================================
Docs - Sample repository

.. autosummary::
   :toctree: _autosummary
   :template: custom-module-template.rst
   :recursive:

   extract
   transform

config.py

import os
import sys
sys.path.insert(0, os.path.abspath('../..'))

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    'sphinx.ext.coverage',
    'sphinx.ext.napoleon',
    'sphinx.ext.viewcode'
]

templates_path = ['_templates']
exclude_patterns = ['_build', '_templates']

html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
autosummary_generate = True

However, with this code I am unable to access the documentation in separate page for classes and functions in a.py, b.py, c.py, d.py, e.py, f.py, g.py, h.py until I have following code in index.rst:-

Welcome to titan documentation!
======================================
Docs - Titan repository

.. autosummary::
   :toctree: _autosummary
   :template: custom-module-template.rst
   :recursive:

   extract.folder_1.a
   extract.folder_1.b
   extract.folder_1.c
   transform.g
   transform.h
   ....
   ....
   ....

i.e. specifying each file individually.

@buhrmann
Copy link

Hi, I'm trying to use the recursive option with the modified template to create stubs for functions, attributes etc. But, this also includes attributes, functions etc. in the navigation toctree. Is there a way to recursively generate all stubs (with corresponding links in the summary tables), but limit the depth of the navigation (or limit it to entries only for packages and modules)?

@jpfeuffer
Copy link

@buhrmann Did you find a solution? I am having the same problem.

rexut added a commit to tiacsys/verylittlewire that referenced this issue Nov 21, 2022
... and also attributes, exaptions or functions and attributes
on module level. When a class is added to an ".. autosummary"
directive, the docstring for the class itself is automatically
generated for the reference docs, but any methods or attributes
are not.

With a set of private autosummary templates and following the
comments in sphinx-doc/sphinx#7912
now all elements will be respected by autosummary and all Python
dostrings will convert into RST.

Signed-off-by: Stephan Linz <linz@li-pro.net>
rexut added a commit to tiacsys/verylittlewire that referenced this issue Nov 21, 2022
... and also attributes, exaptions or functions and attributes
on module level. When a class is added to an ".. autosummary"
directive, the docstring for the class itself is automatically
generated for the reference docs, but any methods or attributes
are not.

With a set of private autosummary templates and following the
comments in sphinx-doc/sphinx#7912
now all elements will be respected by autosummary and all Python
dostrings will convert into RST.

Signed-off-by: Stephan Linz <linz@li-pro.net>
rexut added a commit to tiacsys/verylittlewire that referenced this issue Nov 25, 2022
... and also attributes, exaptions or functions and attributes
on module level. When a class is added to an ".. autosummary"
directive, the docstring for the class itself is automatically
generated for the reference docs, but any methods or attributes
are not.

With a set of private autosummary templates and following the
comments in sphinx-doc/sphinx#7912
now all elements will be respected by autosummary and all Python
dostrings will convert into RST.

Signed-off-by: Stephan Linz <linz@li-pro.net>
rexut added a commit to tiacsys/verylittlewire that referenced this issue Nov 25, 2022
... and also attributes, exaptions or functions and attributes
on module level. When a class is added to an ".. autosummary"
directive, the docstring for the class itself is automatically
generated for the reference docs, but any methods or attributes
are not.

With a set of private autosummary templates and following the
comments in sphinx-doc/sphinx#7912
now all elements will be respected by autosummary and all Python
dostrings will convert into RST.

Signed-off-by: Stephan Linz <linz@li-pro.net>
@luis-chaves-visa
Copy link

Thank you so much @JamesALeedham, being new to autosummary I completely expected what you suggest to be the expected behaviour, this was driving me mad!! 🍔

@fepegar
Copy link

fepegar commented Jan 19, 2023

Thanks for sharing, @mhostetter. Your docs look amazing!

rchaput added a commit to ethicsai/ethical-smart-grid that referenced this issue Mar 31, 2023
* Automatically generate rst files using the `autosummary` extension.
* The generated rst internally use the `autodoc` extension to automatically generate the desired documentation.
* Added autosummary templates to force an "extensive" documentation (e.g., modules, classes, members: methods, attributes, etc.) to be generated by autodoc, instead of simply a table with the first line of the docstrings. (See sphinx-doc/sphinx#7912)
* Added the `api.rst` and updated the `index.rst` files to include the auto-generated documentation in the Table of Contents.
* Removed the `generate-autodoc` make target, as we do not need it anymore.
* Adapted the gitignore.
@AA-Turner AA-Turner modified the milestones: 6.x, 7.x Apr 29, 2023
ZedThree added a commit to PlasmaFAIR/sphinx that referenced this issue Jul 14, 2023
ZedThree added a commit to PlasmaFAIR/sphinx that referenced this issue Jul 26, 2023
@NikosAlexandris
Copy link

I feel the need to share with my fellow Sphinx users an amazing new theme that's solved this issue for me -- Sphinx Immaterial. It has a feature python-apigen that is a modified version of autosummary. It will recursively document an entire package/module, or several.

Instead of producing an autosummary table, it produces a list of signature summaries which are hyperlinked to the individual object documentation pages. Here is an example API reference from my open-source project using Sphinx Immaterial.

In addition to recursive autosummary/autodoc, it monkey patches many bug fixes into Sphinx and adds many new features. The development is very active. I would recommend you all look into it. If you have issues, open an issue or discussion on https://github.com/jbms/sphinx-immaterial and we'll help you use it. 👍

Love the theming in https://galois.readthedocs.io/en/stable/api/!

@siddharth-krishna
Copy link

Another alternative is to use sphinxcontrib-apidoc. I prefer this to sphinx-immaterial because it does not require one to group classes/functions, and automatically generates a hierarchical documentation for all files/modules in a package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extensions:autosummary type:enhancement enhance or introduce a new feature
Projects
None yet
Development

No branches or pull requests