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.