sphinx-doc/sphinx

autoclass does not work for concrete aliases of a generic type

Open

#7,450 创建于 2020年4月9日

在 GitHub 查看
 (1 评论) (0 反应) (0 负责人)Python (1,985 fork)batch import
extensions:autodochelp wantedtype:enhancement

仓库指标

Star
 (5,625 star)
PR 合并指标
 (平均合并 10天 11小时) (30 天内合并 11 个 PR)

描述

Describe the bug

autoclass does not output class documentation for concrete aliases of a generic type; instead, it just outputs "module.Class".

To Reproduce

(Two possible workarounds included below.)

conf.py:

import sys, os
sys.path.insert(0, os.path.abspath('.'))

extensions = ['sphinx.ext.autodoc']

mymodule.py:

from typing import Generic, TypeVar

class SimpleThing:
    
    """A normal class."""

    def __init__(self, attr: int):
        #: help
        self.attr: int = attr

T = TypeVar('T', int, float, complex)
    
class _GenericThing(Generic[T]):
    
    """A generic, preferably private."""
    
    def __init__(self, attr: T):
        #: help
        self.attr: T = attr

ConcreteThing = _GenericThing[float]
"""A concrete thing."""

_PrivateThing = _GenericThing[complex]
"""A private concrete thing."""

DocHackThing = _GenericThing[float]

# __doc__ and #:/""" comments comments don't work with autoclass otherwise.
DocHackThing.__name__ = 'DocHackThing'

# Kills warnings; we still lose the signature in the output.
# If we use GenericThing.__mro__, we get the signature of typing._GenericAlias.
# Setting __signature__ = inspect.signature(GenericThing) doesn't work either.
DocHackThing.__mro__ = object.__mro__

# This works for Sphinx, but help(DocHackThing) remains broken.
DocHackThing.__doc__ = """

Another concrete thing.

.. attribute:: attr
    :type: float
    :value: None

    help

"""

index.rst:

.. module:: mymodule

.. autoclass:: SimpleThing
    :members:

.. autoclass:: _GenericThing
    :members:

autoclass doesn't work for concrete types:

.. autoclass:: ConcreteThing
    :members:

Using autodata gets the point across, but it forces us to expose 
:class:`_GenericThing` for things to make sense to the user:

.. autodata:: ConcreteThing

It would be nice if autoclass for concrete types would look like this:

.. We still have to add the signature by hand.

.. autoclass:: DocHackThing(attr: float)
    :members:

index.txt, as generated by sphinx-build -M text . _build:

class mymodule.SimpleThing(attr: int)

   A normal class.

   attr: int = None

      help

class mymodule._GenericThing(attr: T)

   A generic, preferably private.

   attr: T = None

      help

autoclass doesn't work for concrete types:

mymodule.ConcreteThing

   A concrete thing.

   alias of "mymodule.DocHackThing"

Using autodata gets the point across, but it forces us to expose
"_GenericThing" for things to make sense to the user:

mymodule.ConcreteThing = mymodule._GenericThing[float]

   A concrete thing.

It would be nice if autoclass for concrete types would look like this:

class mymodule.DocHackThing(attr: float)

   Another concrete thing.

   attr: float = None

      help

Expected behavior

The autoclass output for the alias of a concrete type should be similar to that of a type that isn't using generics at all (docs for ConcreteThing should look like those for SimpleThing).

It's arguable this should happen all the time:

If the generic class is part of the public API, autoclass for the generic type and autodata for the concrete alias is probably the correct thing to do.

However, if the generic type is just an implementation detail, it would be nice to be able to pretend the concrete alias is a normal class, and not force the user think about typing stuff.

Your project

Full minimal repro included above.

This is the problem in real life: https://github.com/lemon24/reader/blob/05926a6cb7b62d7186f68502ea905f6bdc067b0b/src/reader/core/types.py#L78-L238

Screenshots

N/A.

Environment info

  • OS: macOS Catalina 10.15.2
  • Python version: 3.7.6
  • Sphinx version: 2.4.4
  • Sphinx extensions: sphinx.ext.autodoc
  • Extra tools: N/A

Additional context

N/A.

贡献者指南