astropy / sphinx-automodapi

Sphinx extension for generating API documentation
https://sphinx-automodapi.readthedocs.io
BSD 3-Clause "New" or "Revised" License
62 stars 43 forks source link

Add option to exclude imported members #119

Open JWCook opened 3 years ago

JWCook commented 3 years ago

First of all, thanks for this great extension! I've found it very useful, except for one detail:

When using either the automodapi or automodsumm directives, all imported members of a module are included, and there does not appear to be a way to change this behavior. The behavior I would like is to only include local members and exclude imported members.

There is one StackOverflow question on this issue with a response that suggests modifying __all__, which is a sub-optimal solution. The :skip: option could be used, but is sub-optimal for the same reason, that is, it requires a hardcoded list of members.

Conveniently, it appears that utils.find_mod_objs() already has a onlylocals argument which will, as expected, return only local members and exclude imported members. If this call within Automodsumm.run(): https://github.com/astropy/sphinx-automodapi/blob/master/sphinx_automodapi/automodsumm.py#L135 is replaced with localnames, fqns, objs = find_mod_objs(modname, onlylocals=True), this produces the desired output.

What I am currently doing is monkey-patching this out in conf.py:

def patch_automodapi(app):
    """Monkey-patch the automodapi extension to exclude imported members"""
    from sphinx_automodapi import automodsumm
    from sphinx_automodapi.utils import find_mod_objs
    automodsumm.find_mod_objs = lambda *args: find_mod_objs(args[0], onlylocals=True)

def setup(app):
    app.connect("builder-inited", patch_automodapi)

Instead of monkey-patching, it would be great if this could be exposed as one or more options in automodapi. Autosummary has a related setting called autosummary_imported_members, so I would suggest doing one or more of the following:

  1. Respect the autosummary_imported_members setting, since automodapi uses autosummary
  2. Add options automodapi_imported_members and automodsumm_imported_members to adjust this behavior for only the automodapi or automodsumm directives, respectively.
  3. Add a :no-imported-members: option to both the automodapi and automodsumm directives
JWCook commented 3 years ago

P.S., I would be willing to work on this myself, if you would be open to a PR containing these changes.

bradyrx commented 3 years ago

+1 to this! This is the only painpoint I've had with this extension. Would be great to implement.

jsh9 commented 2 years ago

On a newer version of Python, such as 3.9.12, the code snippet above will fail.

This is most likely because of the updated behavior of lambda functions.

The following will work:

from sphinx_automodapi import automodsumm
from sphinx_automodapi.utils import find_mod_objs

def find_mod_objs_patched(*args, **kwargs):
    return find_mod_objs(args[0], onlylocals=True)

def patch_automodapi(app):
    """Monkey-patch the automodapi extension to exclude imported members"""
    automodsumm.find_mod_objs = find_mod_objs_patched

def setup(app):
    app.connect("builder-inited", patch_automodapi)

Btw @JWCook , I think they are open to pull requests; they just don't have enough bandwidth. If you know how to make code changes, would you please open an PR? I don't know enough about Sphinx or this package, so I can't create one myself. Thanks!

JWCook commented 2 years ago

@jsh9 Good to know, thanks. Sure, I should have time to put together a PR sometime within the next couple weeks.

I think the least complicated change would be option 1 (support the existing autosummary_imported_members setting).

JWCook commented 1 year ago

I looked into this a bit more, and realized modifying Automodsumm.run() would only affect behavior at the directive level. In other words, it would require the user to add an option in every place it's used, something like:

.. automodumm::
    :no-imported-members:

Supporting autosummary_imported_members (as a single option in conf.py) will require messing with generate_automodsumm_docs(). I'd still like to add this, but it's a bit more complicated than I expected.