Overly verbose output for namedtuples
numpydoc generates rather verbose outputs for namedtuples, especially when combined with autosummary:
$ sphinx-quickstart -q -m --sep -pfoo -afoo --extensions=sphinx.ext.autosummary,numpydoc
then edit source/index.rst to contain
.. autosummary::
foo.Foo
.. automodule:: foo
:members:
and foo.py to contain
from collections import namedtuple
Foo = namedtuple("Foo", "bar baz")
then build with
PYTHONPATH=. make html
This results in

Compare with the result using either not numpydoc at all, or sphinx.ext.napoleon instead:

I guess whether "count" and "index" should be listed as methods can be argued over, but having "bar" and "baz" being listed twice seems clearly too much, and the "Attributes" entry in the autosummary table is not so great either.
Also, if one tries to actually document the fields, e.g.:
_Foo = namedtuple("_Foo", "bar")
class Foo(_Foo):
"""
A Foo.
Attributes
----------
bar : str
The bar contents of Foo.
"""
__slots__ = ()
then both the documented description ("The bar contents of Foo") and the docstring autogenerated by namedtuple ("Alias for field number 0") are output by numpydoc.
I think this is fairly easy to fix. A quick and dirty modification in numpydoc/docscrape.py::ClassDoc does it
Change ClassDoc.properties to
@property
def properties(self):
if self._cls is None:
return []
return [
name
for name, func in inspect.getmembers(self._cls)
if (
not name.startswith("_")
and not self._should_skip_member(name, self._cls) #this added
and (
func is None
or isinstance(func, (property, cached_property))
or inspect.isdatadescriptor(func)
)
and self._is_show_member(name)
)
]
and add ClassDoc._should_skip_member:
@staticmethod
def _should_skip_member(name, klass):
if (issubclass(klass, tuple) and hasattr(klass, '_asdict')
and hasattr(klass, '_fields') and name in klass._fields):
return True
return False
I think this should be the default behavior.
I tested it with a namedtuple having code like this:
class SomeClass(NamedTuple):
"""A docstring.
"""
foo: str = 'text'
"""This is a docstring of foo
"""
and it still preserves the docstring of foo in the output:
would you like to have a PR?
That looks like a clear improvement to me; a PR would be welcome!
There you are :)