#11917 - Fix rendering of inherited members for Python 3.9 (#11919)

Co-authored-by: j-carson <j-carson@fastmail.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
j-carson 2024-02-03 01:46:13 -08:00 committed by GitHub
parent 11d522a097
commit cd2bf0a7e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 72 additions and 1 deletions

View File

@ -72,6 +72,8 @@ Bugs fixed
Patch by Colin Marquardt.
* #11598: Do not use query components in URLs for assets in EPUB rendering.
Patch by David Runge.
* #11917: Fix rendering of annotated inherited members for Python 3.9.
Patch by Janet Carson.
* #11925: Blacklist the ``sphinxprettysearchresults`` extension; the functionality
it provides was merged into Sphinx v2.0.0.
Patch by James Addison.

View File

@ -87,7 +87,13 @@ def getall(obj: Any) -> Sequence[str] | None:
def getannotations(obj: Any) -> Mapping[str, Any]:
"""Get __annotations__ from given *obj* safely."""
__annotations__ = safe_getattr(obj, '__annotations__', None)
if sys.version_info >= (3, 10, 0) or not isinstance(obj, type):
__annotations__ = safe_getattr(obj, '__annotations__', None)
else:
# Workaround for bugfix not available until python 3.10 as recommended by docs
# https://docs.python.org/3.10/howto/annotations.html#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older
__dict__ = safe_getattr(obj, '__dict__', {})
__annotations__ = __dict__.get('__annotations__', None)
if isinstance(__annotations__, Mapping):
return __annotations__
else:

View File

@ -0,0 +1,17 @@
"""
Test case for #11387 corner case involving inherited
members with type annotations on python 3.9 and earlier
"""
class HasTypeAnnotatedMember:
inherit_me: int
"""Inherited"""
class NoTypeAnnotation(HasTypeAnnotatedMember):
a = 1
"""Local"""
class NoTypeAnnotation2(HasTypeAnnotatedMember):
a = 1
"""Local"""

View File

@ -515,3 +515,49 @@ def test_autoattribute_TypeVar_module_level(app):
" alias of TypeVar('T1')",
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_inherited_instance_variable_with_annotations(app):
options = {'members': None,
'inherited-members': None}
actual = do_autodoc(app, 'class', 'target.inherited_annotations.NoTypeAnnotation', options)
assert list(actual) == [
'',
'.. py:class:: NoTypeAnnotation()',
' :module: target.inherited_annotations',
'',
'',
' .. py:attribute:: NoTypeAnnotation.a',
' :module: target.inherited_annotations',
' :value: 1',
'',
' Local',
'',
'',
' .. py:attribute:: NoTypeAnnotation.inherit_me',
' :module: target.inherited_annotations',
' :type: int',
'',
' Inherited',
'',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_no_inherited_instance_variable_with_annotations(app):
options = {'members': None}
actual = do_autodoc(app, 'class', 'target.inherited_annotations.NoTypeAnnotation2', options)
assert list(actual) == [
'',
'.. py:class:: NoTypeAnnotation2()',
' :module: target.inherited_annotations',
'',
'',
' .. py:attribute:: NoTypeAnnotation2.a',
' :module: target.inherited_annotations',
' :value: 1',
'',
' Local',
'',
]