diff --git a/CHANGES b/CHANGES index 8fa9f5707..b95582e2c 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ Deprecated * ``sphinx.ext.autodoc.SlotsAttributeDocumenter`` * ``sphinx.ext.autodoc.TypeVarDocumenter`` * ``sphinx.ext.autodoc.importer._getannotations()`` +* ``sphinx.ext.autodoc.importer._getmro()`` * ``sphinx.pycode.ModuleAnalyzer.parse()`` * ``sphinx.util.osutil.movefile()`` * ``sphinx.util.requests.is_ssl_error()`` diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index c167e509c..30d108035 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -72,6 +72,11 @@ The following is a list of deprecated interfaces. - 4.0 - ``sphinx.util.inspect.getannotations()`` + * - ``sphinx.ext.autodoc.importer._getmro()`` + - 3.4 + - 4.0 + - ``sphinx.util.inspect.getmro()`` + * - ``sphinx.pycode.ModuleAnalyzer.parse()`` - 3.4 - 5.0 diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index cb97e0c72..ec05a8a3d 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -16,7 +16,8 @@ from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Optional, Tup from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.pycode import ModuleAnalyzer from sphinx.util import logging -from sphinx.util.inspect import getannotations, getslots, isclass, isenumclass, safe_getattr +from sphinx.util.inspect import (getannotations, getmro, getslots, isclass, isenumclass, + safe_getattr) if False: # For type annotation @@ -165,12 +166,9 @@ Attribute = NamedTuple('Attribute', [('name', str), def _getmro(obj: Any) -> Tuple["Type", ...]: - """Get __mro__ from given *obj* safely.""" - __mro__ = safe_getattr(obj, '__mro__', None) - if isinstance(__mro__, tuple): - return __mro__ - else: - return tuple() + warnings.warn('sphinx.ext.autodoc.importer._getmro() is deprecated.', + RemovedInSphinx40Warning) + return getmro(obj) def _getannotations(obj: Any) -> Mapping[str, Any]: @@ -224,7 +222,7 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable, continue # annotation only member (ex. attr: int) - for i, cls in enumerate(_getmro(subject)): + for i, cls in enumerate(getmro(subject)): try: for name in getannotations(cls): name = unmangle(cls, name) diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index df469a5ae..a26c818c0 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -36,6 +36,10 @@ else: MethodDescriptorType = type(str.join) WrapperDescriptorType = type(dict.__dict__['fromkeys']) +if False: + # For type annotation + from typing import Type # NOQA + logger = logging.getLogger(__name__) memory_address_re = re.compile(r' at 0x[0-9a-f]{8,16}(?=>)', re.IGNORECASE) @@ -166,6 +170,18 @@ def getannotations(obj: Any) -> Mapping[str, Any]: return {} +def getmro(obj: Any) -> Tuple["Type", ...]: + """Get __mro__ from given *obj* safely. + + Raises AttributeError if given *obj* raises an error on accessing __mro__. + """ + __mro__ = safe_getattr(obj, '__mro__', None) + if isinstance(__mro__, tuple): + return __mro__ + else: + return tuple() + + def getslots(obj: Any) -> Optional[Dict]: """Get __slots__ attribute of the class as dict.