Skip to content

Commit

Permalink
Merge pull request sphinx-doc#8799 from tk0miya/refactor_util_get
Browse files Browse the repository at this point in the history
refactor: AttributeError handling for sphinx.util.inspect.get* is not needed
  • Loading branch information
tk0miya committed Feb 1, 2021
2 parents d3101dd + 42e491a commit 7ca279e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 74 deletions.
60 changes: 24 additions & 36 deletions sphinx/ext/autodoc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1020,10 +1020,6 @@ def import_object(self, raiseerror: bool = False) -> bool:
try:
if not self.options.ignore_module_all:
self.__all__ = inspect.getall(self.object)
except AttributeError as exc:
# __all__ raises an error.
logger.warning(__('%s.__all__ raises an error. Ignored: %r'),
(self.fullname, exc), type='autodoc')
except ValueError as exc:
# invalid __all__ found.
logger.warning(__('__all__ should be a list of strings, not %r '
Expand Down Expand Up @@ -1064,14 +1060,11 @@ def get_module_members(self) -> Dict[str, ObjectMember]:
continue

# annotation only member (ex. attr: int)
try:
for name in inspect.getannotations(self.object):
if name not in members:
docstring = attr_docs.get(('', name), [])
members[name] = ObjectMember(name, INSTANCEATTR,
docstring="\n".join(docstring))
except AttributeError:
pass
for name in inspect.getannotations(self.object):
if name not in members:
docstring = attr_docs.get(('', name), [])
members[name] = ObjectMember(name, INSTANCEATTR,
docstring="\n".join(docstring))

return members

Expand Down Expand Up @@ -1911,16 +1904,16 @@ def can_document_member(cls, member: Any, membername: str, isattr: bool, parent:

def update_annotations(self, parent: Any) -> None:
"""Update __annotations__ to support type_comment and so on."""
try:
annotations = dict(inspect.getannotations(parent))
parent.__annotations__ = annotations
annotations = dict(inspect.getannotations(parent))
parent.__annotations__ = annotations

try:
analyzer = ModuleAnalyzer.for_module(self.modname)
analyzer.analyze()
for (classname, attrname), annotation in analyzer.annotations.items():
if classname == '' and attrname not in annotations:
annotations[attrname] = annotation
except AttributeError:
except PycodeError:
pass

def import_object(self, raiseerror: bool = False) -> bool:
Expand Down Expand Up @@ -2233,7 +2226,7 @@ def isslotsattribute(self) -> bool:
return True
else:
return False
except (AttributeError, ValueError, TypeError):
except (ValueError, TypeError):
return False

def import_object(self, raiseerror: bool = False) -> bool:
Expand All @@ -2259,7 +2252,7 @@ def get_doc(self, encoding: str = None, ignore: int = None) -> Optional[List[Lis
return [docstring]
else:
return []
except (AttributeError, ValueError) as exc:
except ValueError as exc:
logger.warning(__('Invalid __slots__ found on %s. Ignored.'),
(self.parent.__qualname__, exc), type='autodoc')
return []
Expand Down Expand Up @@ -2450,8 +2443,6 @@ def update_annotations(self, parent: Any) -> None:
annotations[attrname] = annotation
except (AttributeError, PycodeError):
pass
except AttributeError:
pass
except TypeError:
# Failed to set __annotations__ (built-in, extensions, etc.)
pass
Expand Down Expand Up @@ -2505,22 +2496,19 @@ def add_directive_header(self, sig: str) -> None:
pass

def get_attribute_comment(self, parent: Any, attrname: str) -> Optional[List[str]]:
try:
for cls in inspect.getmro(parent):
try:
module = safe_getattr(cls, '__module__')
qualname = safe_getattr(cls, '__qualname__')

analyzer = ModuleAnalyzer.for_module(module)
analyzer.analyze()
if qualname and self.objpath:
key = (qualname, attrname)
if key in analyzer.attr_docs:
return list(analyzer.attr_docs[key])
except (AttributeError, PycodeError):
pass
except (AttributeError, PycodeError):
pass
for cls in inspect.getmro(parent):
try:
module = safe_getattr(cls, '__module__')
qualname = safe_getattr(cls, '__qualname__')

analyzer = ModuleAnalyzer.for_module(module)
analyzer.analyze()
if qualname and self.objpath:
key = (qualname, attrname)
if key in analyzer.attr_docs:
return list(analyzer.attr_docs[key])
except (AttributeError, PycodeError):
pass

return None

Expand Down
35 changes: 13 additions & 22 deletions sphinx/ext/autodoc/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,9 @@ def get_module_members(module: Any) -> List[Tuple[str, Any]]:
continue

# annotation only member (ex. attr: int)
try:
for name in getannotations(module):
if name not in members:
members[name] = (name, INSTANCEATTR)
except AttributeError:
pass
for name in getannotations(module):
if name not in members:
members[name] = (name, INSTANCEATTR)

return sorted(list(members.values()))

Expand Down Expand Up @@ -214,7 +211,7 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,

for name in __slots__:
members[name] = Attribute(name, True, SLOTSATTR)
except (AttributeError, TypeError, ValueError):
except (TypeError, ValueError):
pass

# other members
Expand All @@ -230,13 +227,10 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,

# annotation only member (ex. attr: int)
for i, cls in enumerate(getmro(subject)):
try:
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = Attribute(name, i == 0, INSTANCEATTR)
except AttributeError:
pass
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = Attribute(name, i == 0, INSTANCEATTR)

if analyzer:
# append instance attributes (cf. self.attr1) if analyzer knows
Expand Down Expand Up @@ -279,7 +273,7 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
for name, docstring in __slots__.items():
members[name] = ObjectMember(name, SLOTSATTR, class_=subject,
docstring=docstring)
except (AttributeError, TypeError, ValueError):
except (TypeError, ValueError):
pass

# other members
Expand All @@ -301,13 +295,10 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
try:
for cls in getmro(subject):
# annotation only member (ex. attr: int)
try:
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)
except AttributeError:
pass
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)

# append instance attributes (cf. self.attr1) if analyzer knows
try:
Expand Down
19 changes: 3 additions & 16 deletions sphinx/util/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ 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 AttributeError if given *obj* raises an error on accessing __all__.
Raises ValueError if given *obj* have invalid __all__.
"""
__all__ = safe_getattr(obj, '__all__', None)
Expand All @@ -159,10 +158,7 @@ def getall(obj: Any) -> Optional[Sequence[str]]:


def getannotations(obj: Any) -> Mapping[str, Any]:
"""Get __annotations__ from given *obj* safely.
Raises AttributeError if given *obj* raises an error on accessing __attribute__.
"""
"""Get __annotations__ from given *obj* safely."""
__annotations__ = safe_getattr(obj, '__annotations__', None)
if isinstance(__annotations__, Mapping):
return __annotations__
Expand All @@ -171,10 +167,7 @@ def getannotations(obj: Any) -> Mapping[str, Any]:


def getmro(obj: Any) -> Tuple["Type", ...]:
"""Get __mro__ from given *obj* safely.
Raises AttributeError if given *obj* raises an error on accessing __mro__.
"""
"""Get __mro__ from given *obj* safely."""
__mro__ = safe_getattr(obj, '__mro__', None)
if isinstance(__mro__, tuple):
return __mro__
Expand All @@ -186,7 +179,6 @@ def getslots(obj: Any) -> Optional[Dict]:
"""Get __slots__ attribute of the class as dict.
Return None if gienv *obj* does not have __slots__.
Raises AttributeError if given *obj* raises an error on accessing __slots__.
Raises TypeError if given *obj* is not a class.
Raises ValueError if given *obj* have invalid __slots__.
"""
Expand Down Expand Up @@ -481,12 +473,7 @@ def is_builtin_class_method(obj: Any, attr_name: str) -> bool:
but PyPy implements it by pure Python code.
"""
try:
mro = inspect.getmro(obj)
except AttributeError:
# no __mro__, assume the object has no methods as we know them
return False

try:
mro = getmro(obj)
cls = next(c for c in mro if attr_name in safe_getattr(c, '__dict__', {}))
except StopIteration:
return False
Expand Down

0 comments on commit 7ca279e

Please sign in to comment.