|
""" |
|
generate_document.py |
|
|
|
Example program for "How Sphinx generates document from Python code" |
|
|
|
Copyright: @tk0miya |
|
License: BSDL |
|
|
|
#pyconjp2020 |
|
""" |
|
import ast |
|
import inspect |
|
import importlib |
|
import textwrap |
|
|
|
|
|
def get_ivars_from_constructor(cls): |
|
"""Returns the instance variables of given class.""" |
|
# Convert source code to AST |
|
filename = inspect.getsourcefile(cls) |
|
with open(filename) as f: |
|
tree = ast.parse(f.read()) |
|
|
|
members = [] |
|
for _class in tree.body: |
|
# Search specified class from module |
|
if isinstance(_class, ast.ClassDef) and _class.name == cls.__name__: |
|
# Search constructor from class definition |
|
for func in _class.body: |
|
if isinstance(func, ast.FunctionDef) and func.name == "__init__": |
|
# Keep the name of first argument (a.k.a. self) |
|
self = func.args.args[0].arg |
|
|
|
# Search assign statements in constructor |
|
for stmt in func.body: |
|
if (isinstance(stmt, ast.Assign) and |
|
isinstance(stmt.targets[0], ast.Attribute) and |
|
isinstance(stmt.targets[0].value, ast.Name) and |
|
stmt.targets[0].value.id == self): |
|
members.append(stmt.targets[0].attr) |
|
|
|
return members |
|
|
|
|
|
def myhelp(name): |
|
"""Document generator for class.""" |
|
# Import the class |
|
modname, clsname = name.rsplit(".", 1) |
|
module = importlib.import_module(modname) |
|
cls = getattr(module, clsname) |
|
|
|
classname = cls.__module__ + "." + cls.__name__ |
|
doc = inspect.getdoc(cls) |
|
members = [] |
|
|
|
for name in dir(cls): |
|
if name.startswith('__') and name.endswith('__'): |
|
# Filter dunder members (e.g. __init__) |
|
pass |
|
else: |
|
members.append(name) |
|
|
|
# Instance variables |
|
for name in get_ivars_from_constructor(cls): |
|
if name not in members: |
|
members.append(name) |
|
|
|
print("Usage of %s" % classname) |
|
print(textwrap.indent(doc, ' ')) |
|
print("") |
|
print("Members:") |
|
for name in members: |
|
print("- %s" % name) |
|
|
|
|
|
if __name__ == '__main__': |
|
myhelp("example.Foo") |