summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2020-11-28 13:47:23 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2020-11-29 12:24:10 +0900
commitbb63f030346829d05997efc3ec4713b3c937f3d5 (patch)
tree5b217b29ad93cd94021909909d7dd29229003956
parentc15c61ed64b3c9e0232fe07a366c98aa229e6286 (diff)
downloadsphinx-git-bb63f030346829d05997efc3ec4713b3c937f3d5.tar.gz
Fix #8503: autoattribute could not create document for a GenericAlias
-rw-r--r--CHANGES3
-rw-r--r--doc/extdev/deprecated.rst5
-rw-r--r--sphinx/ext/autodoc/__init__.py55
-rw-r--r--sphinx/ext/autodoc/deprecated.py15
-rw-r--r--sphinx/ext/autosummary/generate.py5
-rw-r--r--tests/roots/test-ext-autodoc/target/genericalias.py5
-rw-r--r--tests/test_ext_autodoc.py22
-rw-r--r--tests/test_ext_autodoc_autoattribute.py26
-rw-r--r--tests/test_ext_autodoc_autodata.py26
9 files changed, 128 insertions, 34 deletions
diff --git a/CHANGES b/CHANGES
index 1ea53bfc5..769b29ab0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,7 @@ Deprecated
* The ``follow_wrapped`` argument of ``sphinx.util.inspect.signature()``
* ``sphinx.ext.autodoc.Documenter.get_object_members()``
* ``sphinx.ext.autodoc.DataDeclarationDocumenter``
+* ``sphinx.ext.autodoc.GenericAliasDocumenter``
* ``sphinx.ext.autodoc.InstanceAttributeDocumenter``
* ``sphinx.ext.autodoc.SlotsAttributeDocumenter``
* ``sphinx.ext.autodoc.TypeVarDocumenter``
@@ -60,6 +61,8 @@ Bugs fixed
based uninitalized variables
* #8480: autodoc: autoattribute could not create document for __slots__
attributes
+* #8503: autodoc: autoattribute could not create document for a GenericAlias as
+ class attributes correctly
* #8452: autodoc: autodoc_type_aliases doesn't work when autodoc_typehints is
set to "description"
* #8460: autodoc: autodata and autoattribute directives do not display type
diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst
index bbd9d283e..068bf899b 100644
--- a/doc/extdev/deprecated.rst
+++ b/doc/extdev/deprecated.rst
@@ -41,6 +41,11 @@ The following is a list of deprecated interfaces.
- 5.0
- ``sphinx.ext.autodoc.DataDocumenter``
+ * - ``sphinx.ext.autodoc.GenericAliasDocumenter``
+ - 3.4
+ - 5.0
+ - ``sphinx.ext.autodoc.DataDocumenter``
+
* - ``sphinx.ext.autodoc.InstanceAttributeDocumenter``
- 3.4
- 5.0
diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py
index f77852c13..ea2818800 100644
--- a/sphinx/ext/autodoc/__init__.py
+++ b/sphinx/ext/autodoc/__init__.py
@@ -1701,6 +1701,25 @@ class DataDocumenterMixinBase:
pass
+class GenericAliasMixin(DataDocumenterMixinBase):
+ """
+ Mixin for DataDocumenter and AttributeDocumenter to provide the feature for
+ supporting GenericAliases.
+ """
+
+ def should_suppress_directive_header(self) -> bool:
+ return (inspect.isgenericalias(self.object) or
+ super().should_suppress_directive_header())
+
+ def update_content(self, more_content: StringList) -> None:
+ if inspect.isgenericalias(self.object):
+ alias = stringify_typehint(self.object)
+ more_content.append(_('alias of %s') % alias, '')
+ more_content.append('', '')
+
+ super().update_content(more_content)
+
+
class NewTypeMixin(DataDocumenterMixinBase):
"""
Mixin for DataDocumenter and AttributeDocumenter to provide the feature for
@@ -1801,8 +1820,8 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase):
super().add_content(more_content, no_docstring=no_docstring) # type: ignore
-class DataDocumenter(NewTypeMixin, TypeVarMixin, UninitializedGlobalVariableMixin,
- ModuleLevelDocumenter):
+class DataDocumenter(GenericAliasMixin, NewTypeMixin, TypeVarMixin,
+ UninitializedGlobalVariableMixin, ModuleLevelDocumenter):
"""
Specialized Documenter subclass for data items.
"""
@@ -1863,32 +1882,6 @@ class DataDocumenter(NewTypeMixin, TypeVarMixin, UninitializedGlobalVariableMixi
super().add_content(more_content, no_docstring=no_docstring)
-class GenericAliasDocumenter(DataDocumenter):
- """
- Specialized Documenter subclass for GenericAliases.
- """
-
- objtype = 'genericalias'
- directivetype = 'data'
- priority = DataDocumenter.priority + 1
-
- @classmethod
- def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
- ) -> bool:
- return inspect.isgenericalias(member)
-
- def add_directive_header(self, sig: str) -> None:
- self.options = Options(self.options)
- self.options['annotation'] = SUPPRESS
- super().add_directive_header(sig)
-
- def add_content(self, more_content: Optional[StringList], no_docstring: bool = False
- ) -> None:
- name = stringify_typehint(self.object)
- content = StringList([_('alias of %s') % name], source='')
- super().add_content(content)
-
-
class NewTypeDataDocumenter(DataDocumenter):
"""
Specialized Documenter subclass for NewTypes.
@@ -2102,8 +2095,8 @@ class SlotsMixin(DataDocumenterMixinBase):
return super().get_doc(encoding, ignore) # type: ignore
-class AttributeDocumenter(NewTypeMixin, SlotsMixin, TypeVarMixin, # type: ignore
- DocstringStripSignatureMixin, ClassLevelDocumenter):
+class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type: ignore
+ TypeVarMixin, DocstringStripSignatureMixin, ClassLevelDocumenter):
"""
Specialized Documenter subclass for attributes.
"""
@@ -2324,6 +2317,7 @@ def migrate_autodoc_member_order(app: Sphinx, config: Config) -> None:
# for compatibility
from sphinx.ext.autodoc.deprecated import DataDeclarationDocumenter # NOQA
+from sphinx.ext.autodoc.deprecated import GenericAliasDocumenter # NOQA
from sphinx.ext.autodoc.deprecated import InstanceAttributeDocumenter # NOQA
from sphinx.ext.autodoc.deprecated import SingledispatchFunctionDocumenter # NOQA
from sphinx.ext.autodoc.deprecated import SingledispatchMethodDocumenter # NOQA
@@ -2336,7 +2330,6 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(ClassDocumenter)
app.add_autodocumenter(ExceptionDocumenter)
app.add_autodocumenter(DataDocumenter)
- app.add_autodocumenter(GenericAliasDocumenter)
app.add_autodocumenter(NewTypeDataDocumenter)
app.add_autodocumenter(FunctionDocumenter)
app.add_autodocumenter(DecoratorDocumenter)
diff --git a/sphinx/ext/autodoc/deprecated.py b/sphinx/ext/autodoc/deprecated.py
index c6ca13105..5541a7a91 100644
--- a/sphinx/ext/autodoc/deprecated.py
+++ b/sphinx/ext/autodoc/deprecated.py
@@ -109,3 +109,18 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
warnings.warn("%s is deprecated." % self.__class__.__name__,
RemovedInSphinx50Warning, stacklevel=2)
super().__init__(*args, **kwargs)
+
+
+class GenericAliasDocumenter(DataDocumenter):
+ """
+ Specialized Documenter subclass for GenericAliases.
+ """
+
+ objtype = 'genericalias'
+ directivetype = 'data'
+ priority = DataDocumenter.priority + 1 # type: ignore
+
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
+ warnings.warn("%s is deprecated." % self.__class__.__name__,
+ RemovedInSphinx50Warning, stacklevel=2)
+ super().__init__(*args, **kwargs)
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index 2dc936591..10f8ca913 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -87,15 +87,14 @@ AutosummaryEntry = NamedTuple('AutosummaryEntry', [('name', str),
def setup_documenters(app: Any) -> None:
from sphinx.ext.autodoc import (AttributeDocumenter, ClassDocumenter, DataDocumenter,
DecoratorDocumenter, ExceptionDocumenter,
- FunctionDocumenter, GenericAliasDocumenter,
- MethodDocumenter, ModuleDocumenter,
+ FunctionDocumenter, MethodDocumenter, ModuleDocumenter,
NewTypeAttributeDocumenter, NewTypeDataDocumenter,
PropertyDocumenter, SingledispatchFunctionDocumenter)
documenters = [
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter,
NewTypeDataDocumenter, AttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
- GenericAliasDocumenter, SingledispatchFunctionDocumenter,
+ SingledispatchFunctionDocumenter,
] # type: List[Type[Documenter]]
for documenter in documenters:
app.registry.add_documenter(documenter.objtype, documenter)
diff --git a/tests/roots/test-ext-autodoc/target/genericalias.py b/tests/roots/test-ext-autodoc/target/genericalias.py
index d37bcb7fa..9909efca1 100644
--- a/tests/roots/test-ext-autodoc/target/genericalias.py
+++ b/tests/roots/test-ext-autodoc/target/genericalias.py
@@ -4,3 +4,8 @@ from typing import Callable, List
T = List[int]
C = Callable[[int], None] # a generic alias not having a doccomment
+
+
+class Class:
+ #: A list of int
+ T = List[int]
diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py
index 000ddc0c5..02ffae549 100644
--- a/tests/test_ext_autodoc.py
+++ b/tests/test_ext_autodoc.py
@@ -1701,6 +1701,15 @@ def test_autodoc_GenericAlias(app):
'.. py:module:: target.genericalias',
'',
'',
+ '.. py:class:: Class()',
+ ' :module: target.genericalias',
+ '',
+ '',
+ ' .. py:attribute:: Class.T',
+ ' :module: target.genericalias',
+ '',
+ ' alias of :class:`List`\\ [:class:`int`]',
+ '',
'.. py:attribute:: T',
' :module: target.genericalias',
'',
@@ -1712,12 +1721,25 @@ def test_autodoc_GenericAlias(app):
'.. py:module:: target.genericalias',
'',
'',
+ '.. py:class:: Class()',
+ ' :module: target.genericalias',
+ '',
+ '',
+ ' .. py:attribute:: Class.T',
+ ' :module: target.genericalias',
+ '',
+ ' A list of int',
+ '',
+ ' alias of List[int]',
+ '',
+ '',
'.. py:data:: T',
' :module: target.genericalias',
'',
' A list of int',
'',
' alias of List[int]',
+ '',
]
diff --git a/tests/test_ext_autodoc_autoattribute.py b/tests/test_ext_autodoc_autoattribute.py
index a0d5e5b6f..e44395ee3 100644
--- a/tests/test_ext_autodoc_autoattribute.py
+++ b/tests/test_ext_autodoc_autoattribute.py
@@ -108,6 +108,32 @@ def test_autoattribute_slots_variable_str(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autoattribute_GenericAlias(app):
+ actual = do_autodoc(app, 'attribute', 'target.genericalias.Class.T')
+ if sys.version_info < (3, 7):
+ assert list(actual) == [
+ '',
+ '.. py:attribute:: Class.T',
+ ' :module: target.genericalias',
+ ' :value: typing.List[int]',
+ '',
+ ' A list of int',
+ '',
+ ]
+ else:
+ assert list(actual) == [
+ '',
+ '.. py:attribute:: Class.T',
+ ' :module: target.genericalias',
+ '',
+ ' A list of int',
+ '',
+ ' alias of List[int]',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autoattribute_NewType(app):
actual = do_autodoc(app, 'attribute', 'target.typevar.Class.T6')
assert list(actual) == [
diff --git a/tests/test_ext_autodoc_autodata.py b/tests/test_ext_autodoc_autodata.py
index dbf6103cb..d3f63f432 100644
--- a/tests/test_ext_autodoc_autodata.py
+++ b/tests/test_ext_autodoc_autodata.py
@@ -76,6 +76,32 @@ def test_autodata_type_comment(app):
@pytest.mark.sphinx('html', testroot='ext-autodoc')
+def test_autodata_GenericAlias(app):
+ actual = do_autodoc(app, 'data', 'target.genericalias.T')
+ if sys.version_info < (3, 7):
+ assert list(actual) == [
+ '',
+ '.. py:data:: T',
+ ' :module: target.genericalias',
+ ' :value: typing.List[int]',
+ '',
+ ' A list of int',
+ '',
+ ]
+ else:
+ assert list(actual) == [
+ '',
+ '.. py:data:: T',
+ ' :module: target.genericalias',
+ '',
+ ' A list of int',
+ '',
+ ' alias of List[int]',
+ '',
+ ]
+
+
+@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodata_NewType(app):
actual = do_autodoc(app, 'data', 'target.typevar.T6')
assert list(actual) == [