Skip to content

Commit 10a7a6c

Browse files
authored
Move property type annotation logic to importer (#13948)
1 parent 90b4008 commit 10a7a6c

File tree

3 files changed

+44
-51
lines changed

3 files changed

+44
-51
lines changed

sphinx/ext/autodoc/_documenters.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,56 +1750,6 @@ def can_document_member(
17501750
else:
17511751
return False
17521752

1753-
def format_args(self, **kwargs: Any) -> str:
1754-
func = self._get_property_getter()
1755-
if func is None:
1756-
return ''
1757-
1758-
# update the annotations of the property getter
1759-
self._events.emit('autodoc-before-process-signature', func, False)
1760-
1761-
self.props._obj_property_type_annotation = self._property_type_hint()
1762-
1763-
# correctly format the arguments for a property
1764-
return super().format_args(**kwargs)
1765-
1766-
def _property_type_hint(self) -> str | None:
1767-
# TODO: Move this to _importer. Requires moving when type comments
1768-
# are processed.
1769-
mode = _get_render_mode(self.config.autodoc_typehints_format)
1770-
config = self.config
1771-
1772-
func = self._get_property_getter()
1773-
if func is None:
1774-
return None
1775-
1776-
try:
1777-
signature = inspect.signature(
1778-
func, type_aliases=config.autodoc_type_aliases
1779-
)
1780-
if signature.return_annotation is not Parameter.empty:
1781-
short_literals = config.python_display_short_literal_types
1782-
return stringify_annotation(
1783-
signature.return_annotation, mode, short_literals=short_literals
1784-
)
1785-
except TypeError as exc:
1786-
logger.warning(
1787-
__('Failed to get a function signature for %s: %s'),
1788-
self.props.full_name,
1789-
exc,
1790-
)
1791-
pass
1792-
except ValueError:
1793-
pass
1794-
return None
1795-
1796-
def _get_property_getter(self) -> Callable[..., Any] | None:
1797-
if safe_getattr(self.props._obj, 'fget', None): # property
1798-
return self.props._obj.fget
1799-
if safe_getattr(self.props._obj, 'func', None): # cached_property
1800-
return self.props._obj.func
1801-
return None
1802-
18031753

18041754
class TypeAliasDocumenter(Documenter):
18051755
"""Specialized Documenter subclass for type aliases."""

sphinx/ext/autodoc/_property_types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class _FunctionDefProperties(_ItemProperties):
145145

146146
_obj___name__: str | None
147147
_obj___qualname__: str | None
148-
_obj_property_type_annotation: str | None = 'default'
148+
_obj_property_type_annotation: str | None = None
149149

150150
@property
151151
def is_abstractmethod(self) -> bool:

sphinx/ext/autodoc/importer.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from importlib.abc import FileLoader
1414
from importlib.machinery import EXTENSION_SUFFIXES
1515
from importlib.util import decode_source, find_spec, module_from_spec, spec_from_loader
16+
from inspect import Parameter
1617
from pathlib import Path
1718
from types import ModuleType, SimpleNamespace
1819
from typing import TYPE_CHECKING, NewType, TypeVar
@@ -34,6 +35,7 @@
3435
UNINITIALIZED_ATTR,
3536
)
3637
from sphinx.ext.autodoc.mock import ismock, mock, undecorate
38+
from sphinx.ext.autodoc.type_comment import update_annotations_using_type_comments
3739
from sphinx.locale import __
3840
from sphinx.pycode import ModuleAnalyzer
3941
from sphinx.util import inspect, logging
@@ -655,6 +657,46 @@ def _load_object_by_name(
655657
if inspect.isabstractmethod(obj):
656658
obj_properties.add('abstractmethod')
657659

660+
# get property return type annotation
661+
obj_property_type_annotation = None
662+
if safe_getattr(obj, 'fget', None): # property
663+
func = obj.fget # type: ignore[union-attr]
664+
elif safe_getattr(obj, 'func', None): # cached_property
665+
func = obj.func # type: ignore[union-attr]
666+
else:
667+
func = None
668+
if func is not None:
669+
app = SimpleNamespace(config=config)
670+
# update the annotations of the property getter
671+
update_annotations_using_type_comments(app, func, False) # type: ignore[arg-type]
672+
673+
try:
674+
signature = inspect.signature(
675+
func, type_aliases=config.autodoc_type_aliases
676+
)
677+
except TypeError as exc:
678+
full_name = '.'.join((module_name, *parts))
679+
logger.warning(
680+
__('Failed to get a function signature for %s: %s'),
681+
full_name,
682+
exc,
683+
)
684+
pass
685+
except ValueError:
686+
pass
687+
else:
688+
if config.autodoc_typehints_format == 'short':
689+
mode = 'smart'
690+
else:
691+
mode = 'fully-qualified-except-typing'
692+
if signature.return_annotation is not Parameter.empty:
693+
short_literals = config.python_display_short_literal_types
694+
obj_property_type_annotation = stringify_annotation(
695+
signature.return_annotation,
696+
mode, # type: ignore[arg-type]
697+
short_literals=short_literals,
698+
)
699+
658700
props = _FunctionDefProperties(
659701
obj_type=objtype,
660702
module_name=module_name,
@@ -665,6 +707,7 @@ def _load_object_by_name(
665707
_obj___module__=get_attr(parent or obj, '__module__', None) or module_name,
666708
_obj___name__=getattr(parent or obj, '__name__', None),
667709
_obj___qualname__=getattr(parent or obj, '__qualname__', None),
710+
_obj_property_type_annotation=obj_property_type_annotation,
668711
)
669712
elif objtype == 'data':
670713
# Update __annotations__ to support type_comment and so on

0 commit comments

Comments
 (0)