mirror of https://github.com/python/cpython
164 lines
3.8 KiB
Python
164 lines
3.8 KiB
Python
|
"""Simple code to extract class & function docstrings from a module.
|
||
|
|
||
|
|
||
|
"""
|
||
|
|
||
|
import symbol
|
||
|
import token
|
||
|
import types
|
||
|
|
||
|
|
||
|
def get_docs(fileName):
|
||
|
"""Retrieve information from the parse tree of a source file.
|
||
|
|
||
|
fileName
|
||
|
Name of the file to read Python source code from.
|
||
|
"""
|
||
|
source = open(fileName).read()
|
||
|
import os
|
||
|
basename = os.path.basename(os.path.splitext(fileName)[0])
|
||
|
import parser
|
||
|
ast = parser.suite(source)
|
||
|
tup = parser.ast2tuple(ast)
|
||
|
return ModuleInfo(tup, basename)
|
||
|
|
||
|
|
||
|
class DefnInfo:
|
||
|
_docstring = ''
|
||
|
_name = ''
|
||
|
|
||
|
def __init__(self, tree):
|
||
|
self._name = tree[2][1]
|
||
|
|
||
|
def get_docstring(self):
|
||
|
return self._docstring
|
||
|
|
||
|
def get_name(self):
|
||
|
return self._name
|
||
|
|
||
|
class SuiteInfoBase(DefnInfo):
|
||
|
def __init__(self):
|
||
|
self._class_info = {}
|
||
|
self._function_info = {}
|
||
|
|
||
|
def get_class_names(self):
|
||
|
return self._class_info.keys()
|
||
|
|
||
|
def get_class_info(self, name):
|
||
|
return self._class_info[name]
|
||
|
|
||
|
def _extract_info(self, tree):
|
||
|
if len(tree) >= 4:
|
||
|
found, vars = match(DOCSTRING_STMT_PATTERN, tree[3])
|
||
|
if found:
|
||
|
self._docstring = eval(vars['docstring'])
|
||
|
for node in tree[1:]:
|
||
|
if (node[0] == symbol.stmt
|
||
|
and node[1][0] == symbol.compound_stmt):
|
||
|
if node[1][1][0] == symbol.funcdef:
|
||
|
name = node[1][1][2][1]
|
||
|
self._function_info[name] = \
|
||
|
FunctionInfo(node[1][1])
|
||
|
elif node[1][1][0] == symbol.classdef:
|
||
|
name = node[1][1][2][1]
|
||
|
self._class_info[name] = ClassInfo(node[1][1])
|
||
|
|
||
|
|
||
|
class SuiteInfo(SuiteInfoBase):
|
||
|
def __init__(self, tree):
|
||
|
SuiteInfoBase.__init__(self)
|
||
|
self._extract_info(tree)
|
||
|
|
||
|
def get_function_names(self):
|
||
|
return self._function_info.keys()
|
||
|
|
||
|
def get_function_info(self, name):
|
||
|
return self._function_info[name]
|
||
|
|
||
|
|
||
|
class FunctionInfo(SuiteInfo):
|
||
|
def __init__(self, tree):
|
||
|
DefnInfo.__init__(self, tree)
|
||
|
suite = tree[-1]
|
||
|
if len(suite) >= 4:
|
||
|
found, vars = match(DOCSTRING_STMT_PATTERN, suite[3])
|
||
|
if found:
|
||
|
self._docstring = eval(vars['docstring'])
|
||
|
SuiteInfoBase.__init__(self)
|
||
|
self._extract_info(suite)
|
||
|
|
||
|
|
||
|
class ClassInfo(SuiteInfoBase):
|
||
|
def __init__(self, tree):
|
||
|
SuiteInfoBase.__init__(self)
|
||
|
DefnInfo.__init__(self, tree)
|
||
|
self._extract_info(tree[-1])
|
||
|
|
||
|
def get_method_names(self):
|
||
|
return self._function_info.keys()
|
||
|
|
||
|
def get_method_info(self, name):
|
||
|
return self._function_info[name]
|
||
|
|
||
|
|
||
|
class ModuleInfo(SuiteInfo):
|
||
|
def __init__(self, tree, name="<string>"):
|
||
|
self._name = name
|
||
|
SuiteInfo.__init__(self, tree)
|
||
|
found, vars = match(DOCSTRING_STMT_PATTERN, tree[1])
|
||
|
if found:
|
||
|
self._docstring = vars["docstring"]
|
||
|
|
||
|
|
||
|
from types import ListType, TupleType
|
||
|
|
||
|
def match(pattern, data, vars=None):
|
||
|
"""
|
||
|
"""
|
||
|
if vars is None:
|
||
|
vars = {}
|
||
|
if type(pattern) is ListType: # 'variables' are ['varname']
|
||
|
vars[pattern[0]] = data
|
||
|
return 1, vars
|
||
|
if type(pattern) is not TupleType:
|
||
|
return (pattern == data), vars
|
||
|
if len(data) != len(pattern):
|
||
|
return 0, vars
|
||
|
for pattern, data in map(None, pattern, data):
|
||
|
same, vars = match(pattern, data, vars)
|
||
|
if not same:
|
||
|
break
|
||
|
return same, vars
|
||
|
|
||
|
|
||
|
# This pattern will match a 'stmt' node which *might* represent a docstring;
|
||
|
# docstrings require that the statement which provides the docstring be the
|
||
|
# first statement in the class or function, which this pattern does not check.
|
||
|
#
|
||
|
DOCSTRING_STMT_PATTERN = (
|
||
|
symbol.stmt,
|
||
|
(symbol.simple_stmt,
|
||
|
(symbol.small_stmt,
|
||
|
(symbol.expr_stmt,
|
||
|
(symbol.testlist,
|
||
|
(symbol.test,
|
||
|
(symbol.and_test,
|
||
|
(symbol.not_test,
|
||
|
(symbol.comparison,
|
||
|
(symbol.expr,
|
||
|
(symbol.xor_expr,
|
||
|
(symbol.and_expr,
|
||
|
(symbol.shift_expr,
|
||
|
(symbol.arith_expr,
|
||
|
(symbol.term,
|
||
|
(symbol.factor,
|
||
|
(symbol.power,
|
||
|
(symbol.atom,
|
||
|
(token.STRING, ['docstring'])
|
||
|
)))))))))))))))),
|
||
|
(token.NEWLINE, '')
|
||
|
))
|
||
|
|
||
|
#
|
||
|
# end of file
|