These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			191 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Simple code to extract class & function docstrings from a module.
 | |
| 
 | |
| 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.
 | |
| """
 | |
| 
 | |
| import os
 | |
| import parser
 | |
| import symbol
 | |
| import token
 | |
| import types
 | |
| 
 | |
| from types import ListType, TupleType
 | |
| 
 | |
| 
 | |
| 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()
 | |
|     basename = os.path.basename(os.path.splitext(fileName)[0])
 | |
|     ast = parser.suite(source)
 | |
|     return ModuleInfo(ast.totuple(), basename)
 | |
| 
 | |
| 
 | |
| class SuiteInfoBase:
 | |
|     _docstring = ''
 | |
|     _name = ''
 | |
| 
 | |
|     def __init__(self, tree = None):
 | |
|         self._class_info = {}
 | |
|         self._function_info = {}
 | |
|         if tree:
 | |
|             self._extract_info(tree)
 | |
| 
 | |
|     def _extract_info(self, tree):
 | |
|         # 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)
 | |
| 
 | |
|     def get_docstring(self):
 | |
|         return self._docstring
 | |
| 
 | |
|     def get_name(self):
 | |
|         return self._name
 | |
| 
 | |
|     def get_class_names(self):
 | |
|         return self._class_info.keys()
 | |
| 
 | |
|     def get_class_info(self, name):
 | |
|         return self._class_info[name]
 | |
| 
 | |
|     def __getitem__(self, name):
 | |
|         try:
 | |
|             return self._class_info[name]
 | |
|         except KeyError:
 | |
|             return self._function_info[name]
 | |
| 
 | |
| 
 | |
| class SuiteFuncInfo:
 | |
|     #  Mixin class providing access to function names and info.
 | |
| 
 | |
|     def get_function_names(self):
 | |
|         return self._function_info.keys()
 | |
| 
 | |
|     def get_function_info(self, name):
 | |
|         return self._function_info[name]
 | |
| 
 | |
| 
 | |
| class FunctionInfo(SuiteInfoBase, SuiteFuncInfo):
 | |
|     def __init__(self, tree = None):
 | |
|         self._name = tree[2][1]
 | |
|         SuiteInfoBase.__init__(self, tree and tree[-1] or None)
 | |
| 
 | |
| 
 | |
| class ClassInfo(SuiteInfoBase):
 | |
|     def __init__(self, tree = None):
 | |
|         self._name = tree[2][1]
 | |
|         SuiteInfoBase.__init__(self, tree and tree[-1] or None)
 | |
| 
 | |
|     def get_method_names(self):
 | |
|         return self._function_info.keys()
 | |
| 
 | |
|     def get_method_info(self, name):
 | |
|         return self._function_info[name]
 | |
| 
 | |
| 
 | |
| class ModuleInfo(SuiteInfoBase, SuiteFuncInfo):
 | |
|     def __init__(self, tree = None, name = "<string>"):
 | |
|         self._name = name
 | |
|         SuiteInfoBase.__init__(self, tree)
 | |
|         if tree:
 | |
|             found, vars = match(DOCSTRING_STMT_PATTERN, tree[1])
 | |
|             if found:
 | |
|                 self._docstring = vars["docstring"]
 | |
| 
 | |
| 
 | |
| def match(pattern, data, vars=None):
 | |
|     """Match `data' to `pattern', with variable extraction.
 | |
| 
 | |
|     pattern
 | |
|         Pattern to match against, possibly containing variables.
 | |
| 
 | |
|     data
 | |
|         Data to be checked and against which variables are extracted.
 | |
| 
 | |
|     vars
 | |
|         Dictionary of variables which have already been found.  If not
 | |
|         provided, an empty dictionary is created.
 | |
| 
 | |
|     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.
 | |
|     """
 | |
|     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 identifies compound statements, allowing them to be readily
 | |
| #  differentiated from simple statements.
 | |
| #
 | |
| COMPOUND_STMT_PATTERN = (
 | |
|     symbol.stmt,
 | |
|     (symbol.compound_stmt, ['compound'])
 | |
|     )
 | |
| 
 | |
| 
 | |
| #  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, '')
 | |
|      ))
 |