diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2020-11-21 01:01:36 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2020-11-21 01:01:36 +0900 |
commit | 3a4ae2092a6f236e2d71fdedb4b66f594e30d4e7 (patch) | |
tree | afa4f774e0f8660d5ce247f01cace9deaa848d58 /sphinx/util/inspect.py | |
parent | f3a6004f822b05e352372a77f449332ad230d21e (diff) | |
parent | 18b2707b2ac621f23f8ee6a7ca19bf1590be7826 (diff) | |
download | sphinx-git-3a4ae2092a6f236e2d71fdedb4b66f594e30d4e7.tar.gz |
Merge branch '3.x'
Diffstat (limited to 'sphinx/util/inspect.py')
-rw-r--r-- | sphinx/util/inspect.py | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index d1e9c4435..beaed6099 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -20,7 +20,7 @@ import warnings from functools import partial, partialmethod from inspect import Parameter, isclass, ismethod, ismethoddescriptor, ismodule # NOQA from io import StringIO -from typing import Any, Callable, Dict, cast +from typing import Any, Callable, Dict, Optional, Sequence, cast from sphinx.deprecation import RemovedInSphinx50Warning from sphinx.pycode.ast import ast # for py36-37 @@ -107,7 +107,11 @@ def getargspec(func: Callable) -> Any: def unwrap(obj: Any) -> Any: """Get an original object from wrapped object (wrapped functions).""" try: - return inspect.unwrap(obj) + if hasattr(obj, '__sphinx_mock__'): + # Skip unwrapping mock object to avoid RecursionError + return obj + else: + return inspect.unwrap(obj) except ValueError: # might be a mock object return obj @@ -133,6 +137,43 @@ def unwrap_all(obj: Any, *, stop: Callable = None) -> Any: return obj +def getall(obj: Any) -> Optional[Sequence[str]]: + """Get __all__ attribute of the module as dict. + + Return None if given *obj* does not have __all__. + Raises ValueError if given *obj* have invalid __all__. + """ + __all__ = safe_getattr(obj, '__all__', None) + if __all__ is None: + return None + else: + if (isinstance(__all__, (list, tuple)) and all(isinstance(e, str) for e in __all__)): + return __all__ + else: + raise ValueError(__all__) + + +def getslots(obj: Any) -> Optional[Dict]: + """Get __slots__ attribute of the class as dict. + + Return None if gienv *obj* does not have __slots__. + """ + if not inspect.isclass(obj): + raise TypeError + + __slots__ = safe_getattr(obj, '__slots__', None) + if __slots__ is None: + return None + elif isinstance(__slots__, dict): + return __slots__ + elif isinstance(__slots__, str): + return {__slots__: None} + elif isinstance(__slots__, (list, tuple)): + return {e: None for e in __slots__} + else: + raise ValueError + + def isenumclass(x: Any) -> bool: """Check if the object is subclass of enum.""" return inspect.isclass(x) and issubclass(x, enum.Enum) |