Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autosummary to include instance attributes #9146

Merged
merged 4 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions sphinx/ext/autosummary/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,8 +662,10 @@ def import_ivar_by_name(name: str, prefixes: List[str] = [None]) -> Tuple[str, A
name, attr = name.rsplit(".", 1)
real_name, obj, parent, modname = import_by_name(name, prefixes)
qualname = real_name.replace(modname + ".", "")
analyzer = ModuleAnalyzer.for_module(modname)
if (qualname, attr) in analyzer.find_attr_docs():
analyzer = ModuleAnalyzer.for_module(getattr(obj, '__module__', modname))
analyzer.analyze()
# check for presence in `annotations` to include dataclass attributes
if (qualname, attr) in analyzer.attr_docs or (qualname, attr) in analyzer.annotations:
return real_name + "." + attr, INSTANCEATTR, obj, modname
except (ImportError, ValueError, PycodeError):
pass
Expand Down
28 changes: 23 additions & 5 deletions sphinx/ext/autosummary/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,33 @@ def skip_member(obj: Any, name: str, objtype: str) -> bool:
name, exc, type='autosummary')
return False

def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
imported: bool = True) -> Tuple[List[str], List[str]]:
items: List[str] = []
public: List[str] = []
def get_class_members(obj: Any) -> Dict[str, Any]:
members = sphinx.ext.autodoc.get_class_members(obj, [qualname], safe_getattr)
return {name: member.object for name, member in members.items()}

def get_module_members(obj: Any) -> Dict[str, Any]:
members = {}
for name in dir(obj):
try:
value = safe_getattr(obj, name)
members[name] = safe_getattr(obj, name)
except AttributeError:
continue
return members

def get_all_members(obj: Any) -> Dict[str, Any]:
if doc.objtype == "module":
return get_module_members(obj)
elif doc.objtype == "class":
return get_class_members(obj)
return {}

def get_members(obj: Any, types: Set[str], include_public: List[str] = [],
imported: bool = True) -> Tuple[List[str], List[str]]:
items: List[str] = []
public: List[str] = []

all_members = get_all_members(obj)
tk0miya marked this conversation as resolved.
Show resolved Hide resolved
for name, value in all_members.items():
documenter = get_documenter(app, value, obj)
if documenter.objtype in types:
# skip imported members if expected
Expand Down
7 changes: 7 additions & 0 deletions tests/roots/test-autosummary/dummy_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

module_attr
C.class_attr
C.instance_attr
C.prop_attr1
C.prop_attr2
C.C2
Expand Down Expand Up @@ -51,6 +52,12 @@ class C:
#: value is integer.
class_attr = 42

def __init__(self):
#: This is an instance attribute
#:
#: value is a string
self.instance_attr = "42"

def _prop_attr_get(self):
"""
This is a function docstring
Expand Down
2 changes: 2 additions & 0 deletions tests/test_ext_autosummary.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def handler(app, what, name, obj, options, lines):
'emptyLine': "This is the real summary",
'module_attr': 'This is a module attribute',
'C.class_attr': 'This is a class attribute',
'C.instance_attr': 'This is an instance attribute',
'C.prop_attr1': 'This is a function docstring',
'C.prop_attr2': 'This is a attribute docstring',
'C.C2': 'This is a nested inner class docstring',
Expand Down Expand Up @@ -329,6 +330,7 @@ def test_autosummary_generate(app, status, warning):
' ~Foo.CONSTANT3\n'
' ~Foo.CONSTANT4\n'
' ~Foo.baz\n'
' ~Foo.value\n'
' \n' in Foo)

FooBar = (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.Bar.rst').read_text()
Expand Down