mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #7383: autodoc: Support typehints for properties
py:property directive now outputs py:property directive to describe its type annotation.
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -62,6 +62,7 @@ Features added
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
* #8924: autodoc: Support ``bound`` argument for TypeVar
|
* #8924: autodoc: Support ``bound`` argument for TypeVar
|
||||||
|
* #7383: autodoc: Support typehints for properties
|
||||||
* #7549: autosummary: Enable :confval:`autosummary_generate` by default
|
* #7549: autosummary: Enable :confval:`autosummary_generate` by default
|
||||||
* #4826: py domain: Add ``:canonical:`` option to python directives to describe
|
* #4826: py domain: Add ``:canonical:`` option to python directives to describe
|
||||||
the location where the object is defined
|
the location where the object is defined
|
||||||
|
@@ -2526,7 +2526,6 @@ class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): #
|
|||||||
Specialized Documenter subclass for properties.
|
Specialized Documenter subclass for properties.
|
||||||
"""
|
"""
|
||||||
objtype = 'property'
|
objtype = 'property'
|
||||||
directivetype = 'method'
|
|
||||||
member_order = 60
|
member_order = 60
|
||||||
|
|
||||||
# before AttributeDocumenter
|
# before AttributeDocumenter
|
||||||
@@ -2549,7 +2548,20 @@ class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): #
|
|||||||
sourcename = self.get_sourcename()
|
sourcename = self.get_sourcename()
|
||||||
if inspect.isabstractmethod(self.object):
|
if inspect.isabstractmethod(self.object):
|
||||||
self.add_line(' :abstractmethod:', sourcename)
|
self.add_line(' :abstractmethod:', sourcename)
|
||||||
self.add_line(' :property:', sourcename)
|
|
||||||
|
if safe_getattr(self.object, 'fget', None):
|
||||||
|
try:
|
||||||
|
signature = inspect.signature(self.object.fget,
|
||||||
|
type_aliases=self.config.autodoc_type_aliases)
|
||||||
|
if signature.return_annotation is not Parameter.empty:
|
||||||
|
objrepr = stringify_typehint(signature.return_annotation)
|
||||||
|
self.add_line(' :type: ' + objrepr, sourcename)
|
||||||
|
except TypeError as exc:
|
||||||
|
logger.warning(__("Failed to get a function signature for %s: %s"),
|
||||||
|
self.fullname, exc)
|
||||||
|
return None
|
||||||
|
except ValueError:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
class NewTypeAttributeDocumenter(AttributeDocumenter):
|
class NewTypeAttributeDocumenter(AttributeDocumenter):
|
||||||
|
6
tests/roots/test-ext-autodoc/target/properties.py
Normal file
6
tests/roots/test-ext-autodoc/target/properties.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class Foo:
|
||||||
|
"""docstring"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def prop(self) -> int:
|
||||||
|
"""docstring"""
|
@@ -1033,9 +1033,8 @@ def test_autodoc_descriptor(app):
|
|||||||
' Descriptor instance docstring.',
|
' Descriptor instance docstring.',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: Class.prop',
|
' .. py:property:: Class.prop',
|
||||||
' :module: target.descriptor',
|
' :module: target.descriptor',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
' Property.',
|
' Property.',
|
||||||
''
|
''
|
||||||
@@ -1055,9 +1054,8 @@ def test_autodoc_cached_property(app):
|
|||||||
' :module: target.cached_property',
|
' :module: target.cached_property',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: Foo.prop',
|
' .. py:property:: Foo.prop',
|
||||||
' :module: target.cached_property',
|
' :module: target.cached_property',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1516,10 +1514,9 @@ def test_abstractmethods(app):
|
|||||||
' :module: target.abstractmethods',
|
' :module: target.abstractmethods',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: Base.prop',
|
' .. py:property:: Base.prop',
|
||||||
' :module: target.abstractmethods',
|
' :module: target.abstractmethods',
|
||||||
' :abstractmethod:',
|
' :abstractmethod:',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: Base.staticmeth()',
|
' .. py:method:: Base.staticmeth()',
|
||||||
|
@@ -199,6 +199,27 @@ def test_decorators(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_properties(app):
|
||||||
|
options = {"members": None}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.properties.Foo', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: Foo()',
|
||||||
|
' :module: target.properties',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:property:: Foo.prop',
|
||||||
|
' :module: target.properties',
|
||||||
|
' :type: int',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_slots_attribute(app):
|
def test_slots_attribute(app):
|
||||||
options = {"members": None}
|
options = {"members": None}
|
||||||
|
28
tests/test_ext_autodoc_autoproperty.py
Normal file
28
tests/test_ext_autodoc_autoproperty.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
"""
|
||||||
|
test_ext_autodoc_autoproperty
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Test the autodoc extension. This tests mainly the Documenters; the auto
|
||||||
|
directives are tested in a test source file translated by test_build.
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from .test_ext_autodoc import do_autodoc
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_properties(app):
|
||||||
|
actual = do_autodoc(app, 'property', 'target.properties.Foo.prop')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:property:: Foo.prop',
|
||||||
|
' :module: target.properties',
|
||||||
|
' :type: int',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
]
|
@@ -261,16 +261,14 @@ def test_autodoc_docstring_signature(app):
|
|||||||
' indented line',
|
' indented line',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: DocstringSig.prop1',
|
' .. py:property:: DocstringSig.prop1',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: DocstringSig.prop2',
|
' .. py:property:: DocstringSig.prop2',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
' Second line of docstring',
|
' Second line of docstring',
|
||||||
@@ -305,17 +303,15 @@ def test_autodoc_docstring_signature(app):
|
|||||||
' indented line',
|
' indented line',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: DocstringSig.prop1',
|
' .. py:property:: DocstringSig.prop1',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
' DocstringSig.prop1(self)',
|
' DocstringSig.prop1(self)',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: DocstringSig.prop2',
|
' .. py:property:: DocstringSig.prop2',
|
||||||
' :module: target',
|
' :module: target',
|
||||||
' :property:',
|
|
||||||
'',
|
'',
|
||||||
' First line of docstring',
|
' First line of docstring',
|
||||||
' Second line of docstring',
|
' Second line of docstring',
|
||||||
|
Reference in New Issue
Block a user