blob: 2aa9ec2857f11af874331817f5b842341e75afcd [file] [log] [blame]
Guido van Rossum16d27e31996-08-21 16:28:53 +00001"""Simple code to extract class & function docstrings from a module.
2
Guido van Rossum8206fb91996-08-26 00:33:29 +00003This code is used as an example in the library reference manual in the
4section on using the parser module. Refer to the manual for a thorough
5discussion of the operation of this code.
Guido van Rossum16d27e31996-08-21 16:28:53 +00006"""
7
Fred Drake995285e1999-11-19 21:57:56 +00008import os
9import parser
Guido van Rossum16d27e31996-08-21 16:28:53 +000010import symbol
11import token
12import types
13
Fred Drake995285e1999-11-19 21:57:56 +000014from types import ListType, TupleType
15
Guido van Rossum16d27e31996-08-21 16:28:53 +000016
17def get_docs(fileName):
18 """Retrieve information from the parse tree of a source file.
19
20 fileName
Guido van Rossum4117e541998-09-14 16:44:15 +000021 Name of the file to read Python source code from.
Guido van Rossum16d27e31996-08-21 16:28:53 +000022 """
23 source = open(fileName).read()
Guido van Rossum16d27e31996-08-21 16:28:53 +000024 basename = os.path.basename(os.path.splitext(fileName)[0])
Guido van Rossum16d27e31996-08-21 16:28:53 +000025 ast = parser.suite(source)
Fred Drake995285e1999-11-19 21:57:56 +000026 return ModuleInfo(ast.totuple(), basename)
Guido van Rossum16d27e31996-08-21 16:28:53 +000027
28
Guido van Rossum8206fb91996-08-26 00:33:29 +000029class SuiteInfoBase:
Guido van Rossum16d27e31996-08-21 16:28:53 +000030 _docstring = ''
31 _name = ''
32
Guido van Rossum8206fb91996-08-26 00:33:29 +000033 def __init__(self, tree = None):
Guido van Rossum4117e541998-09-14 16:44:15 +000034 self._class_info = {}
35 self._function_info = {}
36 if tree:
37 self._extract_info(tree)
Guido van Rossum8206fb91996-08-26 00:33:29 +000038
39 def _extract_info(self, tree):
Guido van Rossum4117e541998-09-14 16:44:15 +000040 # extract docstring
41 if len(tree) == 2:
42 found, vars = match(DOCSTRING_STMT_PATTERN[1], tree[1])
43 else:
44 found, vars = match(DOCSTRING_STMT_PATTERN, tree[3])
45 if found:
46 self._docstring = eval(vars['docstring'])
47 # discover inner definitions
48 for node in tree[1:]:
49 found, vars = match(COMPOUND_STMT_PATTERN, node)
50 if found:
51 cstmt = vars['compound']
52 if cstmt[0] == symbol.funcdef:
53 name = cstmt[2][1]
54 self._function_info[name] = FunctionInfo(cstmt)
55 elif cstmt[0] == symbol.classdef:
56 name = cstmt[2][1]
57 self._class_info[name] = ClassInfo(cstmt)
Guido van Rossum16d27e31996-08-21 16:28:53 +000058
59 def get_docstring(self):
Guido van Rossum4117e541998-09-14 16:44:15 +000060 return self._docstring
Guido van Rossum16d27e31996-08-21 16:28:53 +000061
62 def get_name(self):
Guido van Rossum4117e541998-09-14 16:44:15 +000063 return self._name
Guido van Rossum16d27e31996-08-21 16:28:53 +000064
Guido van Rossum16d27e31996-08-21 16:28:53 +000065 def get_class_names(self):
Guido van Rossum4117e541998-09-14 16:44:15 +000066 return self._class_info.keys()
Guido van Rossum16d27e31996-08-21 16:28:53 +000067
68 def get_class_info(self, name):
Guido van Rossum4117e541998-09-14 16:44:15 +000069 return self._class_info[name]
Guido van Rossum16d27e31996-08-21 16:28:53 +000070
Guido van Rossum8206fb91996-08-26 00:33:29 +000071 def __getitem__(self, name):
Guido van Rossum4117e541998-09-14 16:44:15 +000072 try:
73 return self._class_info[name]
74 except KeyError:
75 return self._function_info[name]
Guido van Rossum16d27e31996-08-21 16:28:53 +000076
77
Guido van Rossum8206fb91996-08-26 00:33:29 +000078class SuiteFuncInfo:
79 # Mixin class providing access to function names and info.
Guido van Rossum16d27e31996-08-21 16:28:53 +000080
81 def get_function_names(self):
Guido van Rossum4117e541998-09-14 16:44:15 +000082 return self._function_info.keys()
Guido van Rossum16d27e31996-08-21 16:28:53 +000083
84 def get_function_info(self, name):
Guido van Rossum4117e541998-09-14 16:44:15 +000085 return self._function_info[name]
Guido van Rossum16d27e31996-08-21 16:28:53 +000086
87
Guido van Rossum8206fb91996-08-26 00:33:29 +000088class FunctionInfo(SuiteInfoBase, SuiteFuncInfo):
89 def __init__(self, tree = None):
Guido van Rossum4117e541998-09-14 16:44:15 +000090 self._name = tree[2][1]
91 SuiteInfoBase.__init__(self, tree and tree[-1] or None)
Guido van Rossum16d27e31996-08-21 16:28:53 +000092
93
94class ClassInfo(SuiteInfoBase):
Guido van Rossum8206fb91996-08-26 00:33:29 +000095 def __init__(self, tree = None):
Guido van Rossum4117e541998-09-14 16:44:15 +000096 self._name = tree[2][1]
97 SuiteInfoBase.__init__(self, tree and tree[-1] or None)
Guido van Rossum16d27e31996-08-21 16:28:53 +000098
99 def get_method_names(self):
Guido van Rossum4117e541998-09-14 16:44:15 +0000100 return self._function_info.keys()
Guido van Rossum16d27e31996-08-21 16:28:53 +0000101
102 def get_method_info(self, name):
Guido van Rossum4117e541998-09-14 16:44:15 +0000103 return self._function_info[name]
Guido van Rossum16d27e31996-08-21 16:28:53 +0000104
105
Guido van Rossum8206fb91996-08-26 00:33:29 +0000106class ModuleInfo(SuiteInfoBase, SuiteFuncInfo):
107 def __init__(self, tree = None, name = "<string>"):
Guido van Rossum4117e541998-09-14 16:44:15 +0000108 self._name = name
109 SuiteInfoBase.__init__(self, tree)
110 if tree:
111 found, vars = match(DOCSTRING_STMT_PATTERN, tree[1])
112 if found:
113 self._docstring = vars["docstring"]
Guido van Rossum16d27e31996-08-21 16:28:53 +0000114
115
Guido van Rossum16d27e31996-08-21 16:28:53 +0000116def match(pattern, data, vars=None):
Guido van Rossum8206fb91996-08-26 00:33:29 +0000117 """Match `data' to `pattern', with variable extraction.
118
119 pattern
Guido van Rossum4117e541998-09-14 16:44:15 +0000120 Pattern to match against, possibly containing variables.
Guido van Rossum8206fb91996-08-26 00:33:29 +0000121
122 data
Guido van Rossum4117e541998-09-14 16:44:15 +0000123 Data to be checked and against which variables are extracted.
Guido van Rossum8206fb91996-08-26 00:33:29 +0000124
125 vars
Guido van Rossum4117e541998-09-14 16:44:15 +0000126 Dictionary of variables which have already been found. If not
127 provided, an empty dictionary is created.
Guido van Rossum8206fb91996-08-26 00:33:29 +0000128
129 The `pattern' value may contain variables of the form ['varname'] which
130 are allowed to match anything. The value that is matched is returned as
131 part of a dictionary which maps 'varname' to the matched value. 'varname'
132 is not required to be a string object, but using strings makes patterns
133 and the code which uses them more readable.
134
135 This function returns two values: a boolean indicating whether a match
136 was found and a dictionary mapping variable names to their associated
137 values.
Guido van Rossum16d27e31996-08-21 16:28:53 +0000138 """
139 if vars is None:
Guido van Rossum4117e541998-09-14 16:44:15 +0000140 vars = {}
141 if type(pattern) is ListType: # 'variables' are ['varname']
142 vars[pattern[0]] = data
143 return 1, vars
Guido van Rossum16d27e31996-08-21 16:28:53 +0000144 if type(pattern) is not TupleType:
Guido van Rossum4117e541998-09-14 16:44:15 +0000145 return (pattern == data), vars
Guido van Rossum16d27e31996-08-21 16:28:53 +0000146 if len(data) != len(pattern):
Guido van Rossum4117e541998-09-14 16:44:15 +0000147 return 0, vars
Guido van Rossum16d27e31996-08-21 16:28:53 +0000148 for pattern, data in map(None, pattern, data):
Guido van Rossum4117e541998-09-14 16:44:15 +0000149 same, vars = match(pattern, data, vars)
150 if not same:
151 break
Guido van Rossum16d27e31996-08-21 16:28:53 +0000152 return same, vars
153
154
Guido van Rossum8206fb91996-08-26 00:33:29 +0000155# This pattern identifies compound statements, allowing them to be readily
156# differentiated from simple statements.
157#
158COMPOUND_STMT_PATTERN = (
159 symbol.stmt,
160 (symbol.compound_stmt, ['compound'])
161 )
162
163
Guido van Rossum16d27e31996-08-21 16:28:53 +0000164# This pattern will match a 'stmt' node which *might* represent a docstring;
165# docstrings require that the statement which provides the docstring be the
166# first statement in the class or function, which this pattern does not check.
167#
168DOCSTRING_STMT_PATTERN = (
169 symbol.stmt,
170 (symbol.simple_stmt,
171 (symbol.small_stmt,
172 (symbol.expr_stmt,
173 (symbol.testlist,
Guido van Rossum4117e541998-09-14 16:44:15 +0000174 (symbol.test,
175 (symbol.and_test,
176 (symbol.not_test,
177 (symbol.comparison,
178 (symbol.expr,
179 (symbol.xor_expr,
180 (symbol.and_expr,
181 (symbol.shift_expr,
182 (symbol.arith_expr,
183 (symbol.term,
184 (symbol.factor,
185 (symbol.power,
186 (symbol.atom,
187 (token.STRING, ['docstring'])
188 )))))))))))))))),
Guido van Rossum16d27e31996-08-21 16:28:53 +0000189 (token.NEWLINE, '')
190 ))