mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #10009: autodoc: Crashes if subject raises an error on getdoc()
This commit is contained in:
parent
6ad6594ec7
commit
6c6fed5e55
1
CHANGES
1
CHANGES
@ -46,6 +46,7 @@ Bugs fixed
|
|||||||
with Python 3.10
|
with Python 3.10
|
||||||
* #9968: autodoc: instance variables are not shown if __init__ method has
|
* #9968: autodoc: instance variables are not shown if __init__ method has
|
||||||
position-only-arguments
|
position-only-arguments
|
||||||
|
* #10009: autodoc: Crashes if target object raises an error on getting docstring
|
||||||
* #9947: i18n: topic directive having a bullet list can't be translatable
|
* #9947: i18n: topic directive having a bullet list can't be translatable
|
||||||
* #9878: mathjax: MathJax configuration is placed after loading MathJax itself
|
* #9878: mathjax: MathJax configuration is placed after loading MathJax itself
|
||||||
* #9857: Generated RFC links use outdated base url
|
* #9857: Generated RFC links use outdated base url
|
||||||
|
@ -711,109 +711,111 @@ class Documenter:
|
|||||||
|
|
||||||
# process members and determine which to skip
|
# process members and determine which to skip
|
||||||
for obj in members:
|
for obj in members:
|
||||||
membername, member = obj
|
try:
|
||||||
# if isattr is True, the member is documented as an attribute
|
membername, member = obj
|
||||||
if member is INSTANCEATTR:
|
# if isattr is True, the member is documented as an attribute
|
||||||
isattr = True
|
if member is INSTANCEATTR:
|
||||||
elif (namespace, membername) in attr_docs:
|
isattr = True
|
||||||
isattr = True
|
elif (namespace, membername) in attr_docs:
|
||||||
else:
|
isattr = True
|
||||||
isattr = False
|
else:
|
||||||
|
isattr = False
|
||||||
|
|
||||||
doc = getdoc(member, self.get_attr, self.config.autodoc_inherit_docstrings,
|
doc = getdoc(member, self.get_attr, self.config.autodoc_inherit_docstrings,
|
||||||
self.object, membername)
|
self.object, membername)
|
||||||
if not isinstance(doc, str):
|
if not isinstance(doc, str):
|
||||||
# Ignore non-string __doc__
|
# Ignore non-string __doc__
|
||||||
doc = None
|
|
||||||
|
|
||||||
# if the member __doc__ is the same as self's __doc__, it's just
|
|
||||||
# inherited and therefore not the member's doc
|
|
||||||
cls = self.get_attr(member, '__class__', None)
|
|
||||||
if cls:
|
|
||||||
cls_doc = self.get_attr(cls, '__doc__', None)
|
|
||||||
if cls_doc == doc:
|
|
||||||
doc = None
|
doc = None
|
||||||
|
|
||||||
if isinstance(obj, ObjectMember) and obj.docstring:
|
# if the member __doc__ is the same as self's __doc__, it's just
|
||||||
# hack for ClassDocumenter to inject docstring via ObjectMember
|
# inherited and therefore not the member's doc
|
||||||
doc = obj.docstring
|
cls = self.get_attr(member, '__class__', None)
|
||||||
|
if cls:
|
||||||
|
cls_doc = self.get_attr(cls, '__doc__', None)
|
||||||
|
if cls_doc == doc:
|
||||||
|
doc = None
|
||||||
|
|
||||||
doc, metadata = separate_metadata(doc)
|
if isinstance(obj, ObjectMember) and obj.docstring:
|
||||||
has_doc = bool(doc)
|
# hack for ClassDocumenter to inject docstring via ObjectMember
|
||||||
|
doc = obj.docstring
|
||||||
|
|
||||||
if 'private' in metadata:
|
doc, metadata = separate_metadata(doc)
|
||||||
# consider a member private if docstring has "private" metadata
|
has_doc = bool(doc)
|
||||||
isprivate = True
|
|
||||||
elif 'public' in metadata:
|
if 'private' in metadata:
|
||||||
# consider a member public if docstring has "public" metadata
|
# consider a member private if docstring has "private" metadata
|
||||||
isprivate = False
|
isprivate = True
|
||||||
else:
|
elif 'public' in metadata:
|
||||||
isprivate = membername.startswith('_')
|
# consider a member public if docstring has "public" metadata
|
||||||
|
isprivate = False
|
||||||
|
else:
|
||||||
|
isprivate = membername.startswith('_')
|
||||||
|
|
||||||
keep = False
|
|
||||||
if ismock(member) and (namespace, membername) not in attr_docs:
|
|
||||||
# mocked module or object
|
|
||||||
pass
|
|
||||||
elif self.options.exclude_members and membername in self.options.exclude_members:
|
|
||||||
# remove members given by exclude-members
|
|
||||||
keep = False
|
keep = False
|
||||||
elif want_all and special_member_re.match(membername):
|
if ismock(member) and (namespace, membername) not in attr_docs:
|
||||||
# special __methods__
|
# mocked module or object
|
||||||
if self.options.special_members and membername in self.options.special_members:
|
pass
|
||||||
if membername == '__doc__':
|
elif (self.options.exclude_members and
|
||||||
|
membername in self.options.exclude_members):
|
||||||
|
# remove members given by exclude-members
|
||||||
|
keep = False
|
||||||
|
elif want_all and special_member_re.match(membername):
|
||||||
|
# special __methods__
|
||||||
|
if (self.options.special_members and
|
||||||
|
membername in self.options.special_members):
|
||||||
|
if membername == '__doc__':
|
||||||
|
keep = False
|
||||||
|
elif is_filtered_inherited_member(membername, obj):
|
||||||
|
keep = False
|
||||||
|
else:
|
||||||
|
keep = has_doc or self.options.undoc_members
|
||||||
|
else:
|
||||||
keep = False
|
keep = False
|
||||||
elif is_filtered_inherited_member(membername, obj):
|
elif (namespace, membername) in attr_docs:
|
||||||
|
if want_all and isprivate:
|
||||||
|
if self.options.private_members is None:
|
||||||
|
keep = False
|
||||||
|
else:
|
||||||
|
keep = membername in self.options.private_members
|
||||||
|
else:
|
||||||
|
# keep documented attributes
|
||||||
|
keep = True
|
||||||
|
elif want_all and isprivate:
|
||||||
|
if has_doc or self.options.undoc_members:
|
||||||
|
if self.options.private_members is None:
|
||||||
|
keep = False
|
||||||
|
elif is_filtered_inherited_member(membername, obj):
|
||||||
|
keep = False
|
||||||
|
else:
|
||||||
|
keep = membername in self.options.private_members
|
||||||
|
else:
|
||||||
|
keep = False
|
||||||
|
else:
|
||||||
|
if (self.options.members is ALL and
|
||||||
|
is_filtered_inherited_member(membername, obj)):
|
||||||
keep = False
|
keep = False
|
||||||
else:
|
else:
|
||||||
|
# ignore undocumented members if :undoc-members: is not given
|
||||||
keep = has_doc or self.options.undoc_members
|
keep = has_doc or self.options.undoc_members
|
||||||
else:
|
|
||||||
keep = False
|
|
||||||
elif (namespace, membername) in attr_docs:
|
|
||||||
if want_all and isprivate:
|
|
||||||
if self.options.private_members is None:
|
|
||||||
keep = False
|
|
||||||
else:
|
|
||||||
keep = membername in self.options.private_members
|
|
||||||
else:
|
|
||||||
# keep documented attributes
|
|
||||||
keep = True
|
|
||||||
elif want_all and isprivate:
|
|
||||||
if has_doc or self.options.undoc_members:
|
|
||||||
if self.options.private_members is None:
|
|
||||||
keep = False
|
|
||||||
elif is_filtered_inherited_member(membername, obj):
|
|
||||||
keep = False
|
|
||||||
else:
|
|
||||||
keep = membername in self.options.private_members
|
|
||||||
else:
|
|
||||||
keep = False
|
|
||||||
else:
|
|
||||||
if (self.options.members is ALL and
|
|
||||||
is_filtered_inherited_member(membername, obj)):
|
|
||||||
keep = False
|
|
||||||
else:
|
|
||||||
# ignore undocumented members if :undoc-members: is not given
|
|
||||||
keep = has_doc or self.options.undoc_members
|
|
||||||
|
|
||||||
if isinstance(obj, ObjectMember) and obj.skipped:
|
if isinstance(obj, ObjectMember) and obj.skipped:
|
||||||
# forcedly skipped member (ex. a module attribute not defined in __all__)
|
# forcedly skipped member (ex. a module attribute not defined in __all__)
|
||||||
keep = False
|
keep = False
|
||||||
|
|
||||||
# give the user a chance to decide whether this member
|
# give the user a chance to decide whether this member
|
||||||
# should be skipped
|
# should be skipped
|
||||||
if self.env.app:
|
if self.env.app:
|
||||||
# let extensions preprocess docstrings
|
# let extensions preprocess docstrings
|
||||||
try:
|
|
||||||
skip_user = self.env.app.emit_firstresult(
|
skip_user = self.env.app.emit_firstresult(
|
||||||
'autodoc-skip-member', self.objtype, membername, member,
|
'autodoc-skip-member', self.objtype, membername, member,
|
||||||
not keep, self.options)
|
not keep, self.options)
|
||||||
if skip_user is not None:
|
if skip_user is not None:
|
||||||
keep = not skip_user
|
keep = not skip_user
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning(__('autodoc: failed to determine %r to be documented, '
|
logger.warning(__('autodoc: failed to determine %r to be documented, '
|
||||||
'the following exception was raised:\n%s'),
|
'the following exception was raised:\n%s'),
|
||||||
member, exc, type='autodoc')
|
member, exc, type='autodoc')
|
||||||
keep = False
|
keep = False
|
||||||
|
|
||||||
if keep:
|
if keep:
|
||||||
ret.append((membername, member, isattr))
|
ret.append((membername, member, isattr))
|
||||||
|
Loading…
Reference in New Issue
Block a user