Skip to content

Overly verbose output for namedtuples #257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
anntzer opened this issue Apr 11, 2020 · 4 comments · Fixed by #527
Closed

Overly verbose output for namedtuples #257

anntzer opened this issue Apr 11, 2020 · 4 comments · Fixed by #527

Comments

@anntzer
Copy link
Contributor

anntzer commented Apr 11, 2020

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
bad

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

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.

@pitrou
Copy link
Member

pitrou commented Dec 29, 2021

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.

@fohrloop
Copy link
Contributor

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:

image

would you like to have a PR?

@stefanv
Copy link
Contributor

stefanv commented Feb 14, 2024

That looks like a clear improvement to me; a PR would be welcome!

@fohrloop
Copy link
Contributor

There you are :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants