3

After much struggle with awful defaults in Sphinx, I finally found a way to display inherited methods in subclass documentation. Unfortunately, this option is global...

autodoc_default_options = {
    ...
    'inherited-members': True,
}

Is there any way to annotate any given class to prevent inherited methods and fields from showing in that documentation?

If there is no way to base it on inheritance, is there any way to simply list all the methods I don't want to be documented for a given class in its docstring?

I'm OK... well, I'd cry a little, but I'd live if I had to list the methods that need to be documented rather than blacklising the ones I don't want.

I know I can put :meta private: on a method definition to circumvent its inclusion in documentation (sort of, not really, but let's pretend it works), but in the case of inherited methods there's nowhere I can attach the docstring to.

Note that any "solution" that involves writing .. automodule:: section by hand is not a solution -- those must be generated.

wvxvw
  • 8,089
  • 10
  • 32
  • 61
  • "those must be be generated" - are you referring to sphinx-apidoc? – mzjn Aug 04 '21 at 18:18
  • @mzjn yes. I do. – wvxvw Aug 04 '21 at 19:13
  • sphinx-apidoc only outputs `automodule` directives. If you want an exception for the documentation of a specific class, that can be done with `autoclass`. Something like this: https://stackoverflow.com/q/33704275/407651. – mzjn Aug 04 '21 at 19:16
  • @mzjn that's not what I'm looking for... I want that to happen in the docstrings attached to the source code. I cannot touch the code generated by sphinx-apidoc. If I'm going to write that, what's the point of using apidoc at all? It's really a worthless tool with too much headache, but having gone through this headache already, I'm not really willing to give up on it yet entirely... – wvxvw Aug 04 '21 at 19:56
  • For now I don't have any other suggestions. Note that unless your project is very unstable, it is not really necessary to run sphinx-apidoc over and over again. Run it once, make your adjustments, and add the files to version control. See https://stackoverflow.com/a/28481785/407651. – mzjn Aug 04 '21 at 20:04
  • @mzjn last thing I need is to hand-edit autogenerated code... If I knew what kind of garbage sphinx-apidoc is before I started, by now, I would have a replacement ready for it... unfortunately, I didn't, and now that's what I have. – wvxvw Aug 04 '21 at 20:07

1 Answers1

0

Well, I figured how to solve half of the problem. Brace yourself for a lot of duct tape...

So, here's an example of how you can disable inherited fields in everything that extends directly or indirectly Exception class:

def is_error(obj):
    return issubclass(obj, Exception)


conditionally_ignored = {
    '__reduce__': is_error,
    '__init__': is_error,
    'with_traceback': is_error,
    'args': is_error,
}

def skip_member_handler(app, objtype, membername, member, skip, options):
    ignore_checker = conditionally_ignored.get(membername)
    if ignore_checker:
        frame = sys._getframe()
        while frame.f_code.co_name != 'filter_members':
            frame = frame.f_back

        suspect = frame.f_locals['self'].object
        return not ignore_checker(suspect)
    return skip


def setup(app):
    app.connect('autodoc-skip-member', skip_member_handler)

Put the above in your config.py. This implies that you are using autodoc to generate documentation.

In the end, I didn't go for controlling this behavior from the docstring of the class being documented. This is just too much work, and there are too many bugs in autodoc, Sphinx builders, the generated output and so on. Just not worth it.

But, the general idea would be to similarly add an event handler for when the source is read, extract information from docstrings, replace docstrings by patched docstrings w/o the necessary information, keep the extracted information somewhere until the skip handler is called, and then implement skipping. But, like I said, there are simply too many things broken along this line.

Another approach would be to emit XML, patch it with XSLT and feed it back to Docutils, but at the time of writing XML generator is broken (it adds namespaced attributes to XML, while it doesn't declare namespaces...) Old classic.

Yet another approach would've been handling an event, when, say the document is generated and references are resolved. Unfortunately, at that point, you will be missing information such as types of things you are working with, the original docstrings etc. You'll be essentially patching HTML, but with very convoluted structure.

wvxvw
  • 8,089
  • 10
  • 32
  • 61