Support NewType as a class attribute

This commit is contained in:
Takeshi KOMIYA
2020-11-21 23:56:16 +09:00
parent be42edea76
commit 6973888294
4 changed files with 63 additions and 6 deletions
+29 -6
View File
@@ -2045,7 +2045,7 @@ class SingledispatchMethodDocumenter(MethodDocumenter):
super().__init__(*args, **kwargs)
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter, NewTypeMixin): # type: ignore # NOQA
"""
Specialized Documenter subclass for attributes.
"""
@@ -2141,7 +2141,11 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
def add_directive_header(self, sig: str) -> None:
super().add_directive_header(sig)
sourcename = self.get_sourcename()
if not self.options.annotation:
if self.options.annotation is SUPPRESS or self.should_suppress_directive_header():
pass
elif self.options.annotation:
self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
else:
# obtain type annotation for this attribute
annotations = get_type_hints(self.parent, None, self.config.autodoc_type_aliases)
if self.objpath[-1] in annotations:
@@ -2163,10 +2167,6 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
self.add_line(' :value: ' + objrepr, sourcename)
except ValueError:
pass
elif self.options.annotation is SUPPRESS:
pass
else:
self.add_line(' :annotation: %s' % self.options.annotation, sourcename)
def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:
try:
@@ -2185,6 +2185,10 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
# if it's not a data descriptor, its docstring is very probably the
# wrong thing to display
no_docstring = True
if more_content is None:
more_content = StringList()
self.update_content(more_content)
super().add_content(more_content, no_docstring)
@@ -2318,6 +2322,24 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
return []
class NewTypeAttributeDocumenter(AttributeDocumenter):
"""
Specialized Documenter subclass for NewTypes.
Note: This must be invoked before MethodDocumenter because NewType is a kind of
function object.
"""
objtype = 'newvarattribute'
directivetype = 'attribute'
priority = MethodDocumenter.priority + 1
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return not isinstance(parent, ModuleDocumenter) and inspect.isNewType(member)
def get_documenters(app: Sphinx) -> Dict[str, "Type[Documenter]"]:
"""Returns registered Documenter classes"""
warnings.warn("get_documenters() is deprecated.", RemovedInSphinx50Warning, stacklevel=2)
@@ -2356,6 +2378,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(PropertyDocumenter)
app.add_autodocumenter(InstanceAttributeDocumenter)
app.add_autodocumenter(SlotsAttributeDocumenter)
app.add_autodocumenter(NewTypeAttributeDocumenter)
app.add_config_value('autoclass_content', 'class', True, ENUM('both', 'class', 'init'))
app.add_config_value('autodoc_member_order', 'alphabetical', True,
@@ -16,3 +16,10 @@ T5 = TypeVar("T5", contravariant=True)
#: T6
T6 = NewType("T6", int)
class Class:
# TODO: TypeVar
#: T6
T6 = NewType("T6", int)
+12
View File
@@ -1731,6 +1731,18 @@ def test_autodoc_TypeVar(app):
'.. py:module:: target.typevar',
'',
'',
'.. py:class:: Class()',
' :module: target.typevar',
'',
'',
' .. py:attribute:: Class.T6',
' :module: target.typevar',
'',
' T6',
'',
' alias of :class:`int`',
'',
'',
'.. py:data:: T1',
' :module: target.typevar',
'',
+15
View File
@@ -70,3 +70,18 @@ def test_autoattribute_instance_variable(app):
' attr4',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autoattribute_NewType(app):
actual = do_autodoc(app, 'attribute', 'target.typevar.Class.T6')
assert list(actual) == [
'',
'.. py:attribute:: Class.T6',
' :module: target.typevar',
'',
' T6',
'',
' alias of :class:`int`',
'',
]