pdoc3 / pdoc

:snake: :arrow_right: :scroll: Auto-generate API documentation for Python projects
https://pdoc3.github.io/pdoc/
GNU Affero General Public License v3.0
1.14k stars 146 forks source link

The idea for documenting reimported entities from submodules #340

Open Yura52 opened 3 years ago

Yura52 commented 3 years ago

Hi!

As far as I understand there is no way to tell pdoc to document the function as my_lib.my_function. Although I see from the website that this is an intentional design decision, I would like to share an idea that is:

The idea is to add a single mapping __pdoc_mapping__ in the root __init__.py (my_lib/__init__.py in the example above) with the following content:

__pdoc_mapping__ = {
    # old_name: new_name
    'my_function': 'my_module.my_function'
}

What do you think?

kernc commented 3 years ago

This is certainly a common use case, but distinguishing imported my_lib.my_function (that you want to show) from imported re (that you don't) is near impossible.

Pdoc should honor __all__ when present.

Can you first try if it works if you expose the function in __all__ in the module where you want it, and block it with __pdoc__ value False where you don't?

Yura52 commented 3 years ago

I've just tried what you are suggesting and it works. However, it also makes it necessary to:

  1. put all other documented members of my_lib in __all__
  2. duplicate my intention in the form of __pdoc__['my_function'] = False in my_lib/my_module.py

The suggested __pdoc_mapping__ frees __all__ from this additional documentation-related responsibility (which, in theory, can be inappropriate) and removes the duplication.

distinguishing imported my_lib.my_function (that you want to show) from imported re (that you don't) is near impossible.

__pdoc_mapping__ also solves this problem, since this mapping should contain all imported entities that are supposed to be documented.

Yura52 commented 3 years ago

While __pdoc_mapping__ is a clear self-sufficient concept which is convenient to discuss, I should say that there are other ways to implement the idea. Especially I would like to mention the following approach: dicts can be allowed as values for __pdoc__, while booleans and strings can be treated as some special cases. Then the story becomes the following:

# This dictionary
__pdoc__ = {
    'some_function': False,
    'SomeClass': 'Custom docstring',
    'my_function': {'source': 'my_module.my_function'},
    'something_else': {'source': 'my_module.submodule.whatever', show: False, 'doc': 'Better docstring'},
}

# is equivalent to this dictionary:
__pdoc__ = {
    'some_function': {'show': False},
    'SomeClass': {'doc': 'Custom docstring'},
    'my_function': {'source': 'my_module.my_function'},
    'something_else': {'source': 'my_module.submodule.whatever', show: False, 'doc': 'Better docstring'},
}
iyume commented 3 years ago

mapping is little complex.

I'm thinking about such situation:

__pdoc__ = {
    'MyClass': True
}

MyClass is under the submodule _base and reimported in __init__.

When inspect.getmembers() iter this module, just document the MyClass object; meanwhile, module _base will not be documented.

See: https://github.com/pdoc3/pdoc/blob/f49faf04a8f236474cda70116046d89f3725faee/pdoc/__init__.py#L694

ignore this comment. _is_whitelisted method while ask supermodule for pdoc, which conflicts.

amin-nejad commented 2 years ago

I stumbled upon this issue whilst trying to find a fix for duplicate entries in the documentation when I import my public API in a package's __init__.py file. I've tried __pdoc__ = {"__all__": False} which does not work. Is the only way to do it to iterate over every member in __all__ and mark it as False. I currently have something like the following which works:

from myproject.foo import Foo
from myproject.bar import Bar

__all__ = [
    "Foo",
    "Bar",
]

__pdoc__ = {}
for _obj in __all__:
    __pdoc__[_obj] = False

Is this the only way? I have __init__.py files which import classes in all of my subpackages so this pattern will need to be repeated in a lot of places. It would be great if there was a command line option to just ignore imports in the __init__.py files completely