2

I'm trying to document namedtuple. When I build the docs I get a warning WARNING: duplicate object description and same empty functions after documented ones. For example: enter image description here

How to delete those aliases? I've already tried this solution, writing few functions to conf.py to create empty properties.

Also, I think it worth to mention that after building I get a note to use :noindex: but I don't understand where should I use it? In my docstring, rst file or somewhere else?

Code example:


File = namedtuple("File", ["path", "size", "extension",
                           "adate", "mdate", "links",
                           "user_owner", "group_owner",
                           "inode", "device", "permissions",
                           "depth"])
"""File attributes.

.. py:attribute:: path

    **-** path to the found file

     .. note::
        depending on command-line arguments can be absolute or relative
...
Artem
  • 563
  • 3
  • 17
  • We need to see your reStructuredText markup for the namedtuple alias issue. For the `:noindex:` issue, here's one of my comments in our issue tracker that explains [options to resolve it](https://github.com/Pylons/deform/pull/397#pullrequestreview-401514094). – Steve Piercy May 03 '20 at 09:53
  • @StevePiercy, you mean that .rst file with ```..automodule::``` to file where this namedtuple defined? Cause I have a few of them: source/rst/DiscUsage_Console.rst. source/rst/DiscUsage_Console.main.rst. source/rst/DiscUsage_Console.DUCore.rst. source/rst/DiscUsage_Console.DUCore.DUArgParser.rst. source/rst/DiscUsage_Console.DUCore.DUFileCrawler.rst. source/rst/DiscUsage_Console.DUCore.DUSpinner.rst. source/rst/DiscUsage_Console.DUUtilities.rst. source/rst/DiscUsage_Console.DUUtilities.DUFormatTools.rst. – Artem May 03 '20 at 10:31
  • All those filenames ar not important. Please show us how to reproduce the problem (see [mcve]). – mzjn May 03 '20 at 12:21
  • @Artem no, just the rst markup that exhibits the behavior you describe when it gets rendered to HTML. – Steve Piercy May 03 '20 at 20:47

3 Answers3

6

I ran into a, I think, much better solution than the accepted answer, just wanted to share it:

Just write this in your conf.py:

# -- Post process ------------------------------------------------------------
import collections
def remove_namedtuple_attrib_docstring(app, what, name, obj, skip, options):
    if type(obj) is collections._tuplegetter:
        return True
    return skip


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

This remove all parameters auto documented with this "Alias for field .." from all NamedTuple classes.

Explanation

This uses the autodoc event autodoc-skip-member which triggers an handler each time it comes across any type of member

  • app.connect('autodoc-skip-member', remove_namedtuple_attrib_docstring) attaches the handler remove_namedtuple_attrib_docstring to the event
  • The handler returns true if the member is a tuplegetter and return the default skipping values otherwise
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
NicolasDg
  • 117
  • 1
  • 6
1

I ran into the same problem documenting namedtuples. Here is my solution.

Do not use the :members: option in your autodoc directives.

Example .rst file:

.. documentation for module with namedtuple

Module with namedtuple
======================

.. automodule:: packagename.modulename

.. autoclass:: packagename.modulename.namedtuplename

Also, to get Sphinx to pick up my namedtuple docstring I had to use its __doc__ attribute. So using your example:

File = namedtuple("File", ["path", ..., "depth"])
File.__doc__ = """File attributes.

.. :attribute:: path
...
"""

Explanation

  • the automodule:: directive picks up the module's docstring
  • the autoclass:: directive picks up the namedtuple's docstring.

The preferred (and usual) approach with autodoc is to use the :members: option and recursively document everything in the module. But when the module contains a namedtuple, using the :members: option (with either directive) generates aliases in the documentation.

With automodule::, the :members: option causes Sphinx to recursively document the members: first the members of the module (the namedtuple's class), then the members of the members (the attributes of that class). This picks up duplicate attributes for the class created by the namedtuple, resulting in the alias problem.

With autoclass:, the :members: option again picks up duplicate class attributes, resulting in the alias problem.

Because _fields

The underlying mechanism for the duplicates is that the class attributes documented in the docstring are already documented as the namedtuple's field names (see the docs). This behavior is built in to namedtuples; I'm not sure how to override it.

To see this underlying mechanism, open a REPL and list the _fields of your namedtuple:

>>> File._fields

To see where the duplicate documentation problem is causing the alias messages, get help on the namedtuple:

>>> help(File)

If you keep scrolling through the documentation, you should eventually see something like this:

 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  adate
 |      Alias for field number 3
 |
 |  depth
 |      Alias for field number 11

Note

It is also important that the namedtuple uses the same name as its type, just as you did:

File = namedtuple("File", ["path", ..., "depth"])

This is convention anyway, but since it is not required it is worth noting that using different names will cause the alias problem for the class instead of the class attributes.

Mike Gazes
  • 154
  • 1
  • 6
1

sphinx-toolbox provides a solution to this, for more info, see here.

To use it, you will need to install sphinx-toolbox, for pip user:

pip install sphinx-toolbox

Then insert the extension to conf.py.

extensions = [
    ...
    'sphinx_toolbox.more_autodoc.autonamedtuple',
    ]

and no more configurations :)

hychou
  • 572
  • 5
  • 15