Skip to content
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

autoclass does not work for concrete aliases of a generic type #7450

Open
lemon24 opened this issue Apr 9, 2020 · 1 comment
Open

autoclass does not work for concrete aliases of a generic type #7450

lemon24 opened this issue Apr 9, 2020 · 1 comment
Labels

Comments

@lemon24
Copy link

lemon24 commented Apr 9, 2020

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.

@lemon24 lemon24 changed the title autoclass does not work for concrete aliases of a generic class autoclass does not work for concrete aliases of a generic type Apr 9, 2020
@tk0miya tk0miya added this to the 3.1.0 milestone Apr 11, 2020
@tk0miya tk0miya added help wanted type:enhancement enhance or introduce a new feature and removed type:bug labels Apr 11, 2020
@tk0miya
Copy link
Member

tk0miya commented Apr 11, 2020

Indeed. To support parametrized generic types, we have to discuss how to represent them on output.

As a just idea, it might be better to show it like type hints.

mymodule.ConcreteThing: _GenericThing[float]

Or, show it like a parent class (confusing?):

mymodule.ConcreteThing(_GenericThing[float])

In addition, we also have to consider the representation of generic-subclasses (ex. _GenericThing).

@tk0miya tk0miya modified the milestones: 3.1.0, 3.2.0 May 23, 2020
@tk0miya tk0miya modified the milestones: 3.2.0, 3.3.0 Aug 2, 2020
@tk0miya tk0miya modified the milestones: 3.3.0, 3.4.0 Nov 1, 2020
@tk0miya tk0miya modified the milestones: 3.4.0, 3.5.0 Dec 19, 2020
@tk0miya tk0miya modified the milestones: 3.5.0, 4.0.0 Feb 14, 2021
@tk0miya tk0miya modified the milestones: 4.0.0, 4.1.0 Apr 11, 2021
@tk0miya tk0miya modified the milestones: 4.1.0, 4.2.0 Jul 10, 2021
@tk0miya tk0miya modified the milestones: 4.2.0, 4.3.0 Sep 12, 2021
@tk0miya tk0miya modified the milestones: 4.3.0, 4.4.0 Nov 8, 2021
@tk0miya tk0miya modified the milestones: 4.4.0, 5.0.0 Dec 23, 2021
@tk0miya tk0miya removed this from the 5.0.0 milestone May 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants