| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  | """Parse a Python module and describe its classes and methods.
 | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  | Parse enough of a Python file to recognize imports and class and | 
					
						
							|  |  |  | method definitions, and to find out the superclasses of a class. | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | The interface consists of a single function: | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |         readmodule_ex(module [, path]) | 
					
						
							|  |  |  | where module is the name of a Python module, and path is an optional | 
					
						
							|  |  |  | list of directories where the module is to be searched.  If present, | 
					
						
							|  |  |  | path is prepended to the system search path sys.path.  The return | 
					
						
							|  |  |  | value is a dictionary.  The keys of the dictionary are the names of | 
					
						
							|  |  |  | the classes defined in the module (including classes that are defined | 
					
						
							|  |  |  | via the from XXX import YYY construct).  The values are class | 
					
						
							|  |  |  | instances of the class Class defined here.  One special key/value pair | 
					
						
							|  |  |  | is present for packages: the key '__path__' has a list as its value | 
					
						
							|  |  |  | which contains the package search path. | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | A class is described by the class Class in this module.  Instances | 
					
						
							|  |  |  | of this class have the following instance variables: | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         module -- the module name | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |         name -- the name of the class | 
					
						
							|  |  |  |         super -- a list of super classes (Class instances) | 
					
						
							|  |  |  |         methods -- a dictionary of methods | 
					
						
							|  |  |  |         file -- the file in which the class was defined | 
					
						
							|  |  |  |         lineno -- the line in the file on which the class statement occurred | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | The dictionary of methods uses the method names as keys and the line | 
					
						
							|  |  |  | numbers on which the method was defined as values. | 
					
						
							|  |  |  | If the name of a super class is not recognized, the corresponding | 
					
						
							|  |  |  | entry in the list of super classes is not a class instance but a | 
					
						
							|  |  |  | string giving the name of the super class.  Since import statements | 
					
						
							|  |  |  | are recognized and imported modules are scanned as well, this | 
					
						
							|  |  |  | shouldn't happen often. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  | A function is described by the class Function in this module. | 
					
						
							|  |  |  | Instances of this class have the following instance variables: | 
					
						
							|  |  |  |         module -- the module name | 
					
						
							|  |  |  |         name -- the name of the class | 
					
						
							|  |  |  |         file -- the file in which the class was defined | 
					
						
							|  |  |  |         lineno -- the line in the file on which the class statement occurred | 
					
						
							| 
									
										
										
										
											2000-02-04 15:39:30 +00:00
										 |  |  | """
 | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import imp | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  | import tokenize # Python tokenizer | 
					
						
							| 
									
										
										
										
											2006-05-29 14:39:00 +00:00
										 |  |  | from token import NAME, DEDENT, NEWLINE, OP | 
					
						
							| 
									
										
										
										
											2003-12-01 20:12:15 +00:00
										 |  |  | from operator import itemgetter | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  | __all__ = ["readmodule", "readmodule_ex", "Class", "Function"] | 
					
						
							| 
									
										
										
										
											2001-02-12 02:00:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-06-07 15:25:18 +00:00
										 |  |  | _modules = {}                           # cache of modules we've seen | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # each Python class is represented by an instance of this class | 
					
						
							|  |  |  | class Class: | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     '''Class to represent a Python class.''' | 
					
						
							|  |  |  |     def __init__(self, module, name, super, file, lineno): | 
					
						
							|  |  |  |         self.module = module | 
					
						
							|  |  |  |         self.name = name | 
					
						
							|  |  |  |         if super is None: | 
					
						
							|  |  |  |             super = [] | 
					
						
							|  |  |  |         self.super = super | 
					
						
							|  |  |  |         self.methods = {} | 
					
						
							|  |  |  |         self.file = file | 
					
						
							|  |  |  |         self.lineno = lineno | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _addmethod(self, name, lineno): | 
					
						
							|  |  |  |         self.methods[name] = lineno | 
					
						
							| 
									
										
										
										
											1995-07-28 09:30:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  | class Function: | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     '''Class to represent a top-level Python function''' | 
					
						
							|  |  |  |     def __init__(self, module, name, file, lineno): | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         self.module = module | 
					
						
							|  |  |  |         self.name = name | 
					
						
							|  |  |  |         self.file = file | 
					
						
							|  |  |  |         self.lineno = lineno | 
					
						
							| 
									
										
										
										
											1999-06-10 14:39:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  | def readmodule(module, path=[]): | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     '''Backwards compatible interface.
 | 
					
						
							| 
									
										
										
										
											1999-06-10 14:39:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |     Call readmodule_ex() and then only keep Class objects from the | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     resulting dictionary.'''
 | 
					
						
							| 
									
										
										
										
											1999-06-10 14:39:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |     dict = _readmodule(module, path) | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     res = {} | 
					
						
							|  |  |  |     for key, value in dict.items(): | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         if isinstance(value, Class): | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |             res[key] = value | 
					
						
							|  |  |  |     return res | 
					
						
							| 
									
										
										
										
											1999-06-10 14:39:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  | def readmodule_ex(module, path=[]): | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     '''Read a module file and return a dictionary of classes.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Search for MODULE in PATH and sys.path, read and parse the | 
					
						
							|  |  |  |     module and return a dictionary with one entry for each class | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |     found in the module. | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |     If INPACKAGE is true, it must be the dotted name of the package in | 
					
						
							|  |  |  |     which we are searching for a submodule, and then PATH must be the | 
					
						
							|  |  |  |     package search path; otherwise, we are searching for a top-level | 
					
						
							|  |  |  |     module, and PATH is combined with sys.path. | 
					
						
							|  |  |  |     '''
 | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |     return _readmodule(module, path) | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  | def _readmodule(module, path, inpackage=None): | 
					
						
							|  |  |  |     '''Do the hard work for readmodule[_ex].''' | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |     # Compute the full module name (prepending inpackage if set) | 
					
						
							|  |  |  |     if inpackage: | 
					
						
							|  |  |  |         fullmodule = "%s.%s" % (inpackage, module) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         fullmodule = module | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Check in the cache | 
					
						
							|  |  |  |     if fullmodule in _modules: | 
					
						
							|  |  |  |         return _modules[fullmodule] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Initialize the dict for this module's contents | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     dict = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |     # Check if it is a built-in module; we don't do much for these | 
					
						
							|  |  |  |     if module in sys.builtin_module_names and not inpackage: | 
					
						
							|  |  |  |         _modules[module] = dict | 
					
						
							|  |  |  |         return dict | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Check for a dotted module name | 
					
						
							| 
									
										
										
										
											2001-02-09 09:39:08 +00:00
										 |  |  |     i = module.rfind('.') | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     if i >= 0: | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         package = module[:i] | 
					
						
							|  |  |  |         submodule = module[i+1:] | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |         parent = _readmodule(package, path, inpackage) | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         if inpackage: | 
					
						
							|  |  |  |             package = "%s.%s" % (inpackage, package) | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |         return _readmodule(submodule, parent['__path__'], package) | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |     # Search the path for the module | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     f = None | 
					
						
							|  |  |  |     if inpackage: | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         f, file, (suff, mode, type) = imp.find_module(module, path) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         f, file, (suff, mode, type) = imp.find_module(module, path + sys.path) | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     if type == imp.PKG_DIRECTORY: | 
					
						
							|  |  |  |         dict['__path__'] = [file] | 
					
						
							|  |  |  |         path = [file] + path | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |         f, file, (suff, mode, type) = imp.find_module('__init__', [file]) | 
					
						
							|  |  |  |     _modules[fullmodule] = dict | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     if type != imp.PY_SOURCE: | 
					
						
							|  |  |  |         # not Python source, can't do anything with this module | 
					
						
							|  |  |  |         f.close() | 
					
						
							|  |  |  |         return dict | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |     stack = [] # stack of (class, indent) pairs | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |     g = tokenize.generate_tokens(f.readline) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         for tokentype, token, start, end, line in g: | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |             if tokentype == DEDENT: | 
					
						
							|  |  |  |                 lineno, thisindent = start | 
					
						
							|  |  |  |                 # close nested classes and defs | 
					
						
							|  |  |  |                 while stack and stack[-1][1] >= thisindent: | 
					
						
							|  |  |  |                     del stack[-1] | 
					
						
							|  |  |  |             elif token == 'def': | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                 lineno, thisindent = start | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                 # close previous nested classes and defs | 
					
						
							|  |  |  |                 while stack and stack[-1][1] >= thisindent: | 
					
						
							|  |  |  |                     del stack[-1] | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                 tokentype, meth_name, start, end, line = g.next() | 
					
						
							|  |  |  |                 if tokentype != NAME: | 
					
						
							|  |  |  |                     continue # Syntax error | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                 if stack: | 
					
						
							|  |  |  |                     cur_class = stack[-1][0] | 
					
						
							|  |  |  |                     if isinstance(cur_class, Class): | 
					
						
							|  |  |  |                         # it's a method | 
					
						
							|  |  |  |                         cur_class._addmethod(meth_name, lineno) | 
					
						
							|  |  |  |                     # else it's a nested def | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     # it's a function | 
					
						
							| 
									
										
										
										
											2006-09-30 11:06:47 +00:00
										 |  |  |                     dict[meth_name] = Function(fullmodule, meth_name, file, lineno) | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                 stack.append((None, thisindent)) # Marker for nested fns | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |             elif token == 'class': | 
					
						
							|  |  |  |                 lineno, thisindent = start | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                 # close previous nested classes and defs | 
					
						
							|  |  |  |                 while stack and stack[-1][1] >= thisindent: | 
					
						
							|  |  |  |                     del stack[-1] | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                 tokentype, class_name, start, end, line = g.next() | 
					
						
							|  |  |  |                 if tokentype != NAME: | 
					
						
							|  |  |  |                     continue # Syntax error | 
					
						
							|  |  |  |                 # parse what follows the class name | 
					
						
							|  |  |  |                 tokentype, token, start, end, line = g.next() | 
					
						
							|  |  |  |                 inherit = None | 
					
						
							|  |  |  |                 if token == '(': | 
					
						
							|  |  |  |                     names = [] # List of superclasses | 
					
						
							|  |  |  |                     # there's a list of superclasses | 
					
						
							|  |  |  |                     level = 1 | 
					
						
							|  |  |  |                     super = [] # Tokens making up current superclass | 
					
						
							|  |  |  |                     while True: | 
					
						
							|  |  |  |                         tokentype, token, start, end, line = g.next() | 
					
						
							|  |  |  |                         if token in (')', ',') and level == 1: | 
					
						
							|  |  |  |                             n = "".join(super) | 
					
						
							|  |  |  |                             if n in dict: | 
					
						
							|  |  |  |                                 # we know this super class | 
					
						
							|  |  |  |                                 n = dict[n] | 
					
						
							|  |  |  |                             else: | 
					
						
							|  |  |  |                                 c = n.split('.') | 
					
						
							|  |  |  |                                 if len(c) > 1: | 
					
						
							|  |  |  |                                     # super class is of the form | 
					
						
							|  |  |  |                                     # module.class: look in module for | 
					
						
							|  |  |  |                                     # class | 
					
						
							|  |  |  |                                     m = c[-2] | 
					
						
							|  |  |  |                                     c = c[-1] | 
					
						
							|  |  |  |                                     if m in _modules: | 
					
						
							|  |  |  |                                         d = _modules[m] | 
					
						
							|  |  |  |                                         if c in d: | 
					
						
							|  |  |  |                                             n = d[c] | 
					
						
							|  |  |  |                             names.append(n) | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                             super = [] | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                         if token == '(': | 
					
						
							|  |  |  |                             level += 1 | 
					
						
							|  |  |  |                         elif token == ')': | 
					
						
							|  |  |  |                             level -= 1 | 
					
						
							|  |  |  |                             if level == 0: | 
					
						
							|  |  |  |                                 break | 
					
						
							|  |  |  |                         elif token == ',' and level == 1: | 
					
						
							|  |  |  |                             pass | 
					
						
							| 
									
										
										
										
											2006-05-29 14:39:00 +00:00
										 |  |  |                         # only use NAME and OP (== dot) tokens for type name | 
					
						
							|  |  |  |                         elif tokentype in (NAME, OP) and level == 1: | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                             super.append(token) | 
					
						
							| 
									
										
										
										
											2006-05-29 14:39:00 +00:00
										 |  |  |                         # expressions in the base list are not supported | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                     inherit = names | 
					
						
							| 
									
										
										
										
											2004-08-02 06:10:11 +00:00
										 |  |  |                 cur_class = Class(fullmodule, class_name, inherit, file, lineno) | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                 if not stack: | 
					
						
							|  |  |  |                     dict[class_name] = cur_class | 
					
						
							|  |  |  |                 stack.append((cur_class, thisindent)) | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |             elif token == 'import' and start[1] == 0: | 
					
						
							|  |  |  |                 modules = _getnamelist(g) | 
					
						
							|  |  |  |                 for mod, mod2 in modules: | 
					
						
							| 
									
										
										
										
											2002-09-16 16:36:02 +00:00
										 |  |  |                     try: | 
					
						
							|  |  |  |                         # Recursively read the imported module | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |                         if not inpackage: | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                             _readmodule(mod, path) | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |                         else: | 
					
						
							|  |  |  |                             try: | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                                 _readmodule(mod, path, inpackage) | 
					
						
							| 
									
										
										
										
											2002-12-02 14:54:20 +00:00
										 |  |  |                             except ImportError: | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                                 _readmodule(mod, []) | 
					
						
							| 
									
										
										
										
											2002-09-16 16:36:02 +00:00
										 |  |  |                     except: | 
					
						
							|  |  |  |                         # If we can't find or parse the imported module, | 
					
						
							|  |  |  |                         # too bad -- don't die here. | 
					
						
							|  |  |  |                         pass | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |             elif token == 'from' and start[1] == 0: | 
					
						
							|  |  |  |                 mod, token = _getname(g) | 
					
						
							|  |  |  |                 if not mod or token != "import": | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 names = _getnamelist(g) | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2002-09-16 16:36:02 +00:00
										 |  |  |                     # Recursively read the imported module | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                     d = _readmodule(mod, path, inpackage) | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |                 except: | 
					
						
							| 
									
										
										
										
											2002-09-16 16:36:02 +00:00
										 |  |  |                     # If we can't find or parse the imported module, | 
					
						
							|  |  |  |                     # too bad -- don't die here. | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                     continue | 
					
						
							|  |  |  |                 # add any classes that were defined in the imported module | 
					
						
							|  |  |  |                 # to our name space if they were mentioned in the list | 
					
						
							|  |  |  |                 for n, n2 in names: | 
					
						
							|  |  |  |                     if n in d: | 
					
						
							|  |  |  |                         dict[n2 or n] = d[n] | 
					
						
							|  |  |  |                     elif n == '*': | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                         # don't add names that start with _ | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                         for n in d: | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |                             if n[0] != '_': | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |                                 dict[n] = d[n] | 
					
						
							|  |  |  |     except StopIteration: | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  |     f.close() | 
					
						
							| 
									
										
										
										
											2001-01-15 00:50:52 +00:00
										 |  |  |     return dict | 
					
						
							| 
									
										
										
										
											1999-06-08 12:53:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-23 01:36:01 +00:00
										 |  |  | def _getnamelist(g): | 
					
						
							|  |  |  |     # Helper to get a comma-separated list of dotted names plus 'as' | 
					
						
							|  |  |  |     # clauses.  Return a list of pairs (name, name2) where name2 is | 
					
						
							|  |  |  |     # the 'as' name, or None if there is no 'as' clause. | 
					
						
							|  |  |  |     names = [] | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         name, token = _getname(g) | 
					
						
							|  |  |  |         if not name: | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         if token == 'as': | 
					
						
							|  |  |  |             name2, token = _getname(g) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             name2 = None | 
					
						
							|  |  |  |         names.append((name, name2)) | 
					
						
							|  |  |  |         while token != "," and "\n" not in token: | 
					
						
							|  |  |  |             tokentype, token, start, end, line = g.next() | 
					
						
							|  |  |  |         if token != ",": | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |     return names | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _getname(g): | 
					
						
							|  |  |  |     # Helper to get a dotted name, return a pair (name, token) where | 
					
						
							|  |  |  |     # name is the dotted name, or None if there was no dotted name, | 
					
						
							|  |  |  |     # and token is the next input token. | 
					
						
							|  |  |  |     parts = [] | 
					
						
							|  |  |  |     tokentype, token, start, end, line = g.next() | 
					
						
							|  |  |  |     if tokentype != NAME and token != '*': | 
					
						
							|  |  |  |         return (None, token) | 
					
						
							|  |  |  |     parts.append(token) | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         tokentype, token, start, end, line = g.next() | 
					
						
							|  |  |  |         if token != '.': | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         tokentype, token, start, end, line = g.next() | 
					
						
							|  |  |  |         if tokentype != NAME: | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         parts.append(token) | 
					
						
							|  |  |  |     return (".".join(parts), token) | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def _main(): | 
					
						
							|  |  |  |     # Main program for testing. | 
					
						
							|  |  |  |     import os | 
					
						
							|  |  |  |     mod = sys.argv[1] | 
					
						
							|  |  |  |     if os.path.exists(mod): | 
					
						
							|  |  |  |         path = [os.path.dirname(mod)] | 
					
						
							|  |  |  |         mod = os.path.basename(mod) | 
					
						
							|  |  |  |         if mod.lower().endswith(".py"): | 
					
						
							|  |  |  |             mod = mod[:-3] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         path = [] | 
					
						
							|  |  |  |     dict = readmodule_ex(mod, path) | 
					
						
							|  |  |  |     objs = dict.values() | 
					
						
							|  |  |  |     objs.sort(lambda a, b: cmp(getattr(a, 'lineno', 0), | 
					
						
							|  |  |  |                                getattr(b, 'lineno', 0))) | 
					
						
							|  |  |  |     for obj in objs: | 
					
						
							|  |  |  |         if isinstance(obj, Class): | 
					
						
							|  |  |  |             print "class", obj.name, obj.super, obj.lineno | 
					
						
							| 
									
										
										
										
											2003-12-17 20:43:33 +00:00
										 |  |  |             methods = sorted(obj.methods.iteritems(), key=itemgetter(1)) | 
					
						
							| 
									
										
										
										
											2002-12-03 08:14:35 +00:00
										 |  |  |             for name, lineno in methods: | 
					
						
							|  |  |  |                 if name != "__path__": | 
					
						
							|  |  |  |                     print "  def", name, lineno | 
					
						
							|  |  |  |         elif isinstance(obj, Function): | 
					
						
							|  |  |  |             print "def", obj.name, obj.lineno | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     _main() |