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.12k stars 145 forks source link

Unable document function that start with underscore #323

Closed OmriGilhar closed 3 years ago

OmriGilhar commented 3 years ago

Expected Behavior

Module simple
=============

Functions
---------

`test() ‑> int`
:   test

`_test2() ‑> int`
:   private test

Actual Behavior

Module simple
=============

Functions
---------

`test() ‑> int`
:   test

Steps to Reproduce

  1. Create a basic python script:
def test() -> int:
    """test"""
    return 1

def _test2() -> int:
    """private test"""
    return 0
  1. use pdoc3 via cli to generate the Markdown document:
    pdoc3 simple.py

Additional info

Is there a flag that I'm missing to generate the underscored function?

kernc commented 3 years ago

It's by design. It's a common convention that underscored members are considered private, implementation details.

You can use __all__ or __pdoc__ to override this behavior.

OmriGilhar commented 3 years ago

It's by design. It's a common convention that underscored members are considered private, implementation details.

You can use __all__ or __pdoc__ to override this behavior.

Thank you @kernc for the quick answer.

ghost commented 3 years ago

So I essentially have to do something like:

__pdoc__[private_function1] = True
__pdoc__[private_function2] = True
...

For all functions that I want to document (as of now)? Isn't it a little tedious and messy if you have a lot of private methods that you want documented?

I'm going to assume that this is a common question, which means it's something Devs do often. Maybe implementing a flag in config.mako to include private methods across the board by default is a good idea?

That being said,

Cheerio.

kernc commented 3 years ago

a little tedious and messy

You could also populate the dict dynamically:

__pdoc__ = {name: True
            for name, obj in globals().items()
            if name.startswith('_') and callable(obj)}  # ...

The distinction between public and private API is just that. One is documented, relied and contracted upon; the other ephemeral, ever-changing, implementation detail, code. If a function/method/class might be of interest to you users, simply make it public. If not, don't overwhelm your users, by concealing it.

ghost commented 3 years ago

I agree, but...

what you mean when you say "users" really changes from project to project. For example the word "users" mean 2 things for us:

For the most part the docs being generated will be used the most by people contributing/maintaining the project and not even by those using it as a back-end. While it's reasonable to hide private methods/class, having a flag to include all of them would really help future devs/contributors/maintainers as they'd be able to generate full-fledged all-encompassing docs without much work.

(P.S.) About private API's

private API's aren't necessarily ephemeral & ever changing:

Private methods are very useful when it comes to managing the interface of both your class and your program. They should be used when dealing with:

  • Sensitive information, such as passwords, personal information, etc.
  • Methods that serve as the inner workings of your class and don’t output or display information.
  • Methods that don’t add to the interface and do not collaborate with other classes.

    - A really good explanation of public, private & protected, Medium.