| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | """Simple code to extract class & function docstrings from a module.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | This code is used as an example in the library reference manual in the | 
					
						
							|  |  |  | section on using the parser module.  Refer to the manual for a thorough | 
					
						
							|  |  |  | discussion of the operation of this code. | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-19 21:57:56 +00:00
										 |  |  | import os | 
					
						
							|  |  |  | import parser | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | import symbol | 
					
						
							|  |  |  | import token | 
					
						
							|  |  |  | import types | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-19 21:57:56 +00:00
										 |  |  | from types import ListType, TupleType | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def get_docs(fileName): | 
					
						
							|  |  |  |     """Retrieve information from the parse tree of a source file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fileName | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         Name of the file to read Python source code from. | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     source = open(fileName).read() | 
					
						
							|  |  |  |     basename = os.path.basename(os.path.splitext(fileName)[0]) | 
					
						
							|  |  |  |     ast = parser.suite(source) | 
					
						
							| 
									
										
										
										
											1999-11-19 21:57:56 +00:00
										 |  |  |     return ModuleInfo(ast.totuple(), basename) | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | class SuiteInfoBase: | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     _docstring = '' | 
					
						
							|  |  |  |     _name = '' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  |     def __init__(self, tree = None): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         self._class_info = {} | 
					
						
							|  |  |  |         self._function_info = {} | 
					
						
							|  |  |  |         if tree: | 
					
						
							|  |  |  |             self._extract_info(tree) | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _extract_info(self, tree): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         # extract docstring | 
					
						
							|  |  |  |         if len(tree) == 2: | 
					
						
							|  |  |  |             found, vars = match(DOCSTRING_STMT_PATTERN[1], tree[1]) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             found, vars = match(DOCSTRING_STMT_PATTERN, tree[3]) | 
					
						
							|  |  |  |         if found: | 
					
						
							|  |  |  |             self._docstring = eval(vars['docstring']) | 
					
						
							|  |  |  |         # discover inner definitions | 
					
						
							|  |  |  |         for node in tree[1:]: | 
					
						
							|  |  |  |             found, vars = match(COMPOUND_STMT_PATTERN, node) | 
					
						
							|  |  |  |             if found: | 
					
						
							|  |  |  |                 cstmt = vars['compound'] | 
					
						
							|  |  |  |                 if cstmt[0] == symbol.funcdef: | 
					
						
							|  |  |  |                     name = cstmt[2][1] | 
					
						
							|  |  |  |                     self._function_info[name] = FunctionInfo(cstmt) | 
					
						
							|  |  |  |                 elif cstmt[0] == symbol.classdef: | 
					
						
							|  |  |  |                     name = cstmt[2][1] | 
					
						
							|  |  |  |                     self._class_info[name] = ClassInfo(cstmt) | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_docstring(self): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._docstring | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_name(self): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._name | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_class_names(self): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._class_info.keys() | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_class_info(self, name): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._class_info[name] | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  |     def __getitem__(self, name): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             return self._class_info[name] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             return self._function_info[name] | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SuiteFuncInfo: | 
					
						
							|  |  |  |     #  Mixin class providing access to function names and info. | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_function_names(self): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._function_info.keys() | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_function_info(self, name): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._function_info[name] | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | class FunctionInfo(SuiteInfoBase, SuiteFuncInfo): | 
					
						
							|  |  |  |     def __init__(self, tree = None): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         self._name = tree[2][1] | 
					
						
							|  |  |  |         SuiteInfoBase.__init__(self, tree and tree[-1] or None) | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ClassInfo(SuiteInfoBase): | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  |     def __init__(self, tree = None): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         self._name = tree[2][1] | 
					
						
							|  |  |  |         SuiteInfoBase.__init__(self, tree and tree[-1] or None) | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_method_names(self): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._function_info.keys() | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_method_info(self, name): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return self._function_info[name] | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | class ModuleInfo(SuiteInfoBase, SuiteFuncInfo): | 
					
						
							|  |  |  |     def __init__(self, tree = None, name = "<string>"): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         self._name = name | 
					
						
							|  |  |  |         SuiteInfoBase.__init__(self, tree) | 
					
						
							|  |  |  |         if tree: | 
					
						
							|  |  |  |             found, vars = match(DOCSTRING_STMT_PATTERN, tree[1]) | 
					
						
							|  |  |  |             if found: | 
					
						
							|  |  |  |                 self._docstring = vars["docstring"] | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def match(pattern, data, vars=None): | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  |     """Match `data' to `pattern', with variable extraction.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pattern | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         Pattern to match against, possibly containing variables. | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     data | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         Data to be checked and against which variables are extracted. | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     vars | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         Dictionary of variables which have already been found.  If not | 
					
						
							|  |  |  |         provided, an empty dictionary is created. | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The `pattern' value may contain variables of the form ['varname'] which | 
					
						
							|  |  |  |     are allowed to match anything.  The value that is matched is returned as | 
					
						
							|  |  |  |     part of a dictionary which maps 'varname' to the matched value.  'varname' | 
					
						
							|  |  |  |     is not required to be a string object, but using strings makes patterns | 
					
						
							|  |  |  |     and the code which uses them more readable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This function returns two values: a boolean indicating whether a match | 
					
						
							|  |  |  |     was found and a dictionary mapping variable names to their associated | 
					
						
							|  |  |  |     values. | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     if vars is None: | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         vars = {} | 
					
						
							|  |  |  |     if type(pattern) is ListType:       # 'variables' are ['varname'] | 
					
						
							|  |  |  |         vars[pattern[0]] = data | 
					
						
							|  |  |  |         return 1, vars | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     if type(pattern) is not TupleType: | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return (pattern == data), vars | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     if len(data) != len(pattern): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         return 0, vars | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     for pattern, data in map(None, pattern, data): | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         same, vars = match(pattern, data, vars) | 
					
						
							|  |  |  |         if not same: | 
					
						
							|  |  |  |             break | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |     return same, vars | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 00:33:29 +00:00
										 |  |  | #  This pattern identifies compound statements, allowing them to be readily | 
					
						
							|  |  |  | #  differentiated from simple statements. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | COMPOUND_STMT_PATTERN = ( | 
					
						
							|  |  |  |     symbol.stmt, | 
					
						
							|  |  |  |     (symbol.compound_stmt, ['compound']) | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  | #  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, | 
					
						
							| 
									
										
										
										
											1998-09-14 16:44:15 +00:00
										 |  |  |         (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']) | 
					
						
							|  |  |  |                      )))))))))))))))), | 
					
						
							| 
									
										
										
										
											1996-08-21 16:28:53 +00:00
										 |  |  |      (token.NEWLINE, '') | 
					
						
							|  |  |  |      )) |