0001 # -*- coding: iso-8859-1 -*- 0002 """Get useful information from live Python objects. 0003 0004 This module encapsulates the interface provided by the internal special 0005 attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion. 0006 It also provides some help for examining source code and class layout. 0007 0008 Here are some of the useful functions provided by this module: 0009 0010 ismodule(), isclass(), ismethod(), isfunction(), istraceback(), 0011 isframe(), iscode(), isbuiltin(), isroutine() - check object types 0012 getmembers() - get members of an object that satisfy a given condition 0013 0014 getfile(), getsourcefile(), getsource() - find an object's source code 0015 getdoc(), getcomments() - get documentation on an object 0016 getmodule() - determine the module that an object came from 0017 getclasstree() - arrange classes so as to represent their hierarchy 0018 0019 getargspec(), getargvalues() - get info about function arguments 0020 formatargspec(), formatargvalues() - format an argument spec 0021 getouterframes(), getinnerframes() - get info about frames 0022 currentframe() - get the current stack frame 0023 stack(), trace() - get info about frames on the stack or in a traceback 0024 """ 0025 0026 # This module is in the public domain. No warranties. 0027 0028 __author__ = 'Ka-Ping Yee <ping@lfw.org>' 0029 __date__ = '1 Jan 2001' 0030 0031 import sys, os, types, string, re, dis, imp, tokenize, linecache 0032 0033 # ----------------------------------------------------------- type-checking 0034 def ismodule(object): 0035 """Return true if the object is a module. 0036 0037 Module objects provide these attributes: 0038 __doc__ documentation string 0039 __file__ filename (missing for built-in modules)""" 0040 return isinstance(object, types.ModuleType) 0041 0042 def isclass(object): 0043 """Return true if the object is a class. 0044 0045 Class objects provide these attributes: 0046 __doc__ documentation string 0047 __module__ name of module in which this class was defined""" 0048 return isinstance(object, types.ClassType) or hasattr(object, '__bases__') 0049 0050 def ismethod(object): 0051 """Return true if the object is an instance method. 0052 0053 Instance method objects provide these attributes: 0054 __doc__ documentation string 0055 __name__ name with which this method was defined 0056 im_class class object in which this method belongs 0057 im_func function object containing implementation of method 0058 im_self instance to which this method is bound, or None""" 0059 return isinstance(object, types.MethodType) 0060 0061 def ismethoddescriptor(object): 0062 """Return true if the object is a method descriptor. 0063 0064 But not if ismethod() or isclass() or isfunction() are true. 0065 0066 This is new in Python 2.2, and, for example, is true of int.__add__. 0067 An object passing this test has a __get__ attribute but not a __set__ 0068 attribute, but beyond that the set of attributes varies. __name__ is 0069 usually sensible, and __doc__ often is. 0070 0071 Methods implemented via descriptors that also pass one of the other 0072 tests return false from the ismethoddescriptor() test, simply because 0073 the other tests promise more -- you can, e.g., count on having the 0074 im_func attribute (etc) when an object passes ismethod().""" 0075 return (hasattr(object, "__get__") 0076 and not hasattr(object, "__set__") # else it's a data descriptor 0077 and not ismethod(object) # mutual exclusion 0078 and not isfunction(object) 0079 and not isclass(object)) 0080 0081 def isdatadescriptor(object): 0082 """Return true if the object is a data descriptor. 0083 0084 Data descriptors have both a __get__ and a __set__ attribute. Examples are 0085 properties (defined in Python) and getsets and members (defined in C). 0086 Typically, data descriptors will also have __name__ and __doc__ attributes 0087 (properties, getsets, and members have both of these attributes), but this 0088 is not guaranteed.""" 0089 return (hasattr(object, "__set__") and hasattr(object, "__get__")) 0090 0091 def isfunction(object): 0092 """Return true if the object is a user-defined function. 0093 0094 Function objects provide these attributes: 0095 __doc__ documentation string 0096 __name__ name with which this function was defined 0097 func_code code object containing compiled function bytecode 0098 func_defaults tuple of any default values for arguments 0099 func_doc (same as __doc__) 0100 func_globals global namespace in which this function was defined 0101 func_name (same as __name__)""" 0102 return isinstance(object, types.FunctionType) 0103 0104 def istraceback(object): 0105 """Return true if the object is a traceback. 0106 0107 Traceback objects provide these attributes: 0108 tb_frame frame object at this level 0109 tb_lasti index of last attempted instruction in bytecode 0110 tb_lineno current line number in Python source code 0111 tb_next next inner traceback object (called by this level)""" 0112 return isinstance(object, types.TracebackType) 0113 0114 def isframe(object): 0115 """Return true if the object is a frame object. 0116 0117 Frame objects provide these attributes: 0118 f_back next outer frame object (this frame's caller) 0119 f_builtins built-in namespace seen by this frame 0120 f_code code object being executed in this frame 0121 f_exc_traceback traceback if raised in this frame, or None 0122 f_exc_type exception type if raised in this frame, or None 0123 f_exc_value exception value if raised in this frame, or None 0124 f_globals global namespace seen by this frame 0125 f_lasti index of last attempted instruction in bytecode 0126 f_lineno current line number in Python source code 0127 f_locals local namespace seen by this frame 0128 f_restricted 0 or 1 if frame is in restricted execution mode 0129 f_trace tracing function for this frame, or None""" 0130 return isinstance(object, types.FrameType) 0131 0132 def iscode(object): 0133 """Return true if the object is a code object. 0134 0135 Code objects provide these attributes: 0136 co_argcount number of arguments (not including * or ** args) 0137 co_code string of raw compiled bytecode 0138 co_consts tuple of constants used in the bytecode 0139 co_filename name of file in which this code object was created 0140 co_firstlineno number of first line in Python source code 0141 co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg 0142 co_lnotab encoded mapping of line numbers to bytecode indices 0143 co_name name with which this code object was defined 0144 co_names tuple of names of local variables 0145 co_nlocals number of local variables 0146 co_stacksize virtual machine stack space required 0147 co_varnames tuple of names of arguments and local variables""" 0148 return isinstance(object, types.CodeType) 0149 0150 def isbuiltin(object): 0151 """Return true if the object is a built-in function or method. 0152 0153 Built-in functions and methods provide these attributes: 0154 __doc__ documentation string 0155 __name__ original name of this function or method 0156 __self__ instance to which a method is bound, or None""" 0157 return isinstance(object, types.BuiltinFunctionType) 0158 0159 def isroutine(object): 0160 """Return true if the object is any kind of function or method.""" 0161 return (isbuiltin(object) 0162 or isfunction(object) 0163 or ismethod(object) 0164 or ismethoddescriptor(object)) 0165 0166 def getmembers(object, predicate=None): 0167 """Return all members of an object as (name, value) pairs sorted by name. 0168 Optionally, only return members that satisfy a given predicate.""" 0169 results = [] 0170 for key in dir(object): 0171 value = getattr(object, key) 0172 if not predicate or predicate(value): 0173 results.append((key, value)) 0174 results.sort() 0175 return results 0176 0177 def classify_class_attrs(cls): 0178 """Return list of attribute-descriptor tuples. 0179 0180 For each name in dir(cls), the return list contains a 4-tuple 0181 with these elements: 0182 0183 0. The name (a string). 0184 0185 1. The kind of attribute this is, one of these strings: 0186 'class method' created via classmethod() 0187 'static method' created via staticmethod() 0188 'property' created via property() 0189 'method' any other flavor of method 0190 'data' not a method 0191 0192 2. The class which defined this attribute (a class). 0193 0194 3. The object as obtained directly from the defining class's 0195 __dict__, not via getattr. This is especially important for 0196 data attributes: C.data is just a data object, but 0197 C.__dict__['data'] may be a data descriptor with additional 0198 info, like a __doc__ string. 0199 """ 0200 0201 mro = getmro(cls) 0202 names = dir(cls) 0203 result = [] 0204 for name in names: 0205 # Get the object associated with the name. 0206 # Getting an obj from the __dict__ sometimes reveals more than 0207 # using getattr. Static and class methods are dramatic examples. 0208 if name in cls.__dict__: 0209 obj = cls.__dict__[name] 0210 else: 0211 obj = getattr(cls, name) 0212 0213 # Figure out where it was defined. 0214 homecls = getattr(obj, "__objclass__", None) 0215 if homecls is None: 0216 # search the dicts. 0217 for base in mro: 0218 if name in base.__dict__: 0219 homecls = base 0220 break 0221 0222 # Get the object again, in order to get it from the defining 0223 # __dict__ instead of via getattr (if possible). 0224 if homecls is not None and name in homecls.__dict__: 0225 obj = homecls.__dict__[name] 0226 0227 # Also get the object via getattr. 0228 obj_via_getattr = getattr(cls, name) 0229 0230 # Classify the object. 0231 if isinstance(obj, staticmethod): 0232 kind = "static method" 0233 elif isinstance(obj, classmethod): 0234 kind = "class method" 0235 elif isinstance(obj, property): 0236 kind = "property" 0237 elif (ismethod(obj_via_getattr) or 0238 ismethoddescriptor(obj_via_getattr)): 0239 kind = "method" 0240 else: 0241 kind = "data" 0242 0243 result.append((name, kind, homecls, obj)) 0244 0245 return result 0246 0247 # ----------------------------------------------------------- class helpers 0248 def _searchbases(cls, accum): 0249 # Simulate the "classic class" search order. 0250 if cls in accum: 0251 return 0252 accum.append(cls) 0253 for base in cls.__bases__: 0254 _searchbases(base, accum) 0255 0256 def getmro(cls): 0257 "Return tuple of base classes (including cls) in method resolution order." 0258 if hasattr(cls, "__mro__"): 0259 return cls.__mro__ 0260 else: 0261 result = [] 0262 _searchbases(cls, result) 0263 return tuple(result) 0264 0265 # -------------------------------------------------- source code extraction 0266 def indentsize(line): 0267 """Return the indent size, in spaces, at the start of a line of text.""" 0268 expline = string.expandtabs(line) 0269 return len(expline) - len(string.lstrip(expline)) 0270 0271 def getdoc(object): 0272 """Get the documentation string for an object. 0273 0274 All tabs are expanded to spaces. To clean up docstrings that are 0275 indented to line up with blocks of code, any whitespace than can be 0276 uniformly removed from the second line onwards is removed.""" 0277 try: 0278 doc = object.__doc__ 0279 except AttributeError: 0280 return None 0281 if not isinstance(doc, types.StringTypes): 0282 return None 0283 try: 0284 lines = string.split(string.expandtabs(doc), '\n') 0285 except UnicodeError: 0286 return None 0287 else: 0288 # Find minimum indentation of any non-blank lines after first line. 0289 margin = sys.maxint 0290 for line in lines[1:]: 0291 content = len(string.lstrip(line)) 0292 if content: 0293 indent = len(line) - content 0294 margin = min(margin, indent) 0295 # Remove indentation. 0296 if lines: 0297 lines[0] = lines[0].lstrip() 0298 if margin < sys.maxint: 0299 for i in range(1, len(lines)): lines[i] = lines[i][margin:] 0300 # Remove any trailing or leading blank lines. 0301 while lines and not lines[-1]: 0302 lines.pop() 0303 while lines and not lines[0]: 0304 lines.pop(0) 0305 return string.join(lines, '\n') 0306 0307 def getfile(object): 0308 """Work out which source or compiled file an object was defined in.""" 0309 if ismodule(object): 0310 if hasattr(object, '__file__'): 0311 return object.__file__ 0312 raise TypeError('arg is a built-in module') 0313 if isclass(object): 0314 object = sys.modules.get(object.__module__) 0315 if hasattr(object, '__file__'): 0316 return object.__file__ 0317 raise TypeError('arg is a built-in class') 0318 if ismethod(object): 0319 object = object.im_func 0320 if isfunction(object): 0321 object = object.func_code 0322 if istraceback(object): 0323 object = object.tb_frame 0324 if isframe(object): 0325 object = object.f_code 0326 if iscode(object): 0327 return object.co_filename 0328 raise TypeError('arg is not a module, class, method, ' 0329 'function, traceback, frame, or code object') 0330 0331 def getmoduleinfo(path): 0332 """Get the module name, suffix, mode, and module type for a given file.""" 0333 filename = os.path.basename(path) 0334 suffixes = map(lambda (suffix, mode, mtype): 0335 (-len(suffix), suffix, mode, mtype), imp.get_suffixes()) 0336 suffixes.sort() # try longest suffixes first, in case they overlap 0337 for neglen, suffix, mode, mtype in suffixes: 0338 if filename[neglen:] == suffix: 0339 return filename[:neglen], suffix, mode, mtype 0340 0341 def getmodulename(path): 0342 """Return the module name for a given file, or None.""" 0343 info = getmoduleinfo(path) 0344 if info: return info[0] 0345 0346 def getsourcefile(object): 0347 """Return the Python source file an object was defined in, if it exists.""" 0348 filename = getfile(object) 0349 if string.lower(filename[-4:]) in ['.pyc', '.pyo']: 0350 filename = filename[:-4] + '.py' 0351 for suffix, mode, kind in imp.get_suffixes(): 0352 if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix: 0353 # Looks like a binary file. We want to only return a text file. 0354 return None 0355 if os.path.exists(filename): 0356 return filename 0357 0358 def getabsfile(object): 0359 """Return an absolute path to the source or compiled file for an object. 0360 0361 The idea is for each object to have a unique origin, so this routine 0362 normalizes the result as much as possible.""" 0363 return os.path.normcase( 0364 os.path.abspath(getsourcefile(object) or getfile(object))) 0365 0366 modulesbyfile = {} 0367 0368 def getmodule(object): 0369 """Return the module an object was defined in, or None if not found.""" 0370 if ismodule(object): 0371 return object 0372 if hasattr(object, '__module__'): 0373 return sys.modules.get(object.__module__) 0374 try: 0375 file = getabsfile(object) 0376 except TypeError: 0377 return None 0378 if file in modulesbyfile: 0379 return sys.modules.get(modulesbyfile[file]) 0380 for module in sys.modules.values(): 0381 if hasattr(module, '__file__'): 0382 modulesbyfile[ 0383 os.path.realpath( 0384 getabsfile(module))] = module.__name__ 0385 if file in modulesbyfile: 0386 return sys.modules.get(modulesbyfile[file]) 0387 main = sys.modules['__main__'] 0388 if not hasattr(object, '__name__'): 0389 return None 0390 if hasattr(main, object.__name__): 0391 mainobject = getattr(main, object.__name__) 0392 if mainobject is object: 0393 return main 0394 builtin = sys.modules['__builtin__'] 0395 if hasattr(builtin, object.__name__): 0396 builtinobject = getattr(builtin, object.__name__) 0397 if builtinobject is object: 0398 return builtin 0399 0400 def findsource(object): 0401 """Return the entire source file and starting line number for an object. 0402 0403 The argument may be a module, class, method, function, traceback, frame, 0404 or code object. The source code is returned as a list of all the lines 0405 in the file and the line number indexes a line in that list. An IOError 0406 is raised if the source code cannot be retrieved.""" 0407 file = getsourcefile(object) or getfile(object) 0408 lines = linecache.getlines(file) 0409 if not lines: 0410 raise IOError('could not get source code') 0411 0412 if ismodule(object): 0413 return lines, 0 0414 0415 if isclass(object): 0416 name = object.__name__ 0417 pat = re.compile(r'^\s*class\s*' + name + r'\b') 0418 for i in range(len(lines)): 0419 if pat.match(lines[i]): return lines, i 0420 else: 0421 raise IOError('could not find class definition') 0422 0423 if ismethod(object): 0424 object = object.im_func 0425 if isfunction(object): 0426 object = object.func_code 0427 if istraceback(object): 0428 object = object.tb_frame 0429 if isframe(object): 0430 object = object.f_code 0431 if iscode(object): 0432 if not hasattr(object, 'co_firstlineno'): 0433 raise IOError('could not find function definition') 0434 lnum = object.co_firstlineno - 1 0435 pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))|^(\s*@)') 0436 while lnum > 0: 0437 if pat.match(lines[lnum]): break 0438 lnum = lnum - 1 0439 return lines, lnum 0440 raise IOError('could not find code object') 0441 0442 def getcomments(object): 0443 """Get lines of comments immediately preceding an object's source code. 0444 0445 Returns None when source can't be found. 0446 """ 0447 try: 0448 lines, lnum = findsource(object) 0449 except (IOError, TypeError): 0450 return None 0451 0452 if ismodule(object): 0453 # Look for a comment block at the top of the file. 0454 start = 0 0455 if lines and lines[0][:2] == '#!': start = 1 0456 while start < len(lines) and string.strip(lines[start]) in ['', '#']: 0457 start = start + 1 0458 if start < len(lines) and lines[start][:1] == '#': 0459 comments = [] 0460 end = start 0461 while end < len(lines) and lines[end][:1] == '#': 0462 comments.append(string.expandtabs(lines[end])) 0463 end = end + 1 0464 return string.join(comments, '') 0465 0466 # Look for a preceding block of comments at the same indentation. 0467 elif lnum > 0: 0468 indent = indentsize(lines[lnum]) 0469 end = lnum - 1 0470 if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \ 0471 indentsize(lines[end]) == indent: 0472 comments = [string.lstrip(string.expandtabs(lines[end]))] 0473 if end > 0: 0474 end = end - 1 0475 comment = string.lstrip(string.expandtabs(lines[end])) 0476 while comment[:1] == '#' and indentsize(lines[end]) == indent: 0477 comments[:0] = [comment] 0478 end = end - 1 0479 if end < 0: break 0480 comment = string.lstrip(string.expandtabs(lines[end])) 0481 while comments and string.strip(comments[0]) == '#': 0482 comments[:1] = [] 0483 while comments and string.strip(comments[-1]) == '#': 0484 comments[-1:] = [] 0485 return string.join(comments, '') 0486 0487 class ListReader: 0488 """Provide a readline() method to return lines from a list of strings.""" 0489 def __init__(self, lines): 0490 self.lines = lines 0491 self.index = 0 0492 0493 def readline(self): 0494 i = self.index 0495 if i < len(self.lines): 0496 self.index = i + 1 0497 return self.lines[i] 0498 else: return '' 0499 0500 class EndOfBlock(Exception): pass 0501 0502 class BlockFinder: 0503 """Provide a tokeneater() method to detect the end of a code block.""" 0504 def __init__(self): 0505 self.indent = 0 0506 self.started = 0 0507 self.last = 0 0508 0509 def tokeneater(self, type, token, (srow, scol), (erow, ecol), line): 0510 if not self.started: 0511 if '@' in line: pass 0512 elif type == tokenize.NAME: self.started = 1 0513 elif type == tokenize.NEWLINE: 0514 self.last = srow 0515 elif type == tokenize.INDENT: 0516 self.indent = self.indent + 1 0517 elif type == tokenize.DEDENT: 0518 self.indent = self.indent - 1 0519 if self.indent == 0: 0520 raise EndOfBlock, self.last 0521 elif type == tokenize.NAME and scol == 0: 0522 raise EndOfBlock, self.last 0523 0524 def getblock(lines): 0525 """Extract the block of code at the top of the given list of lines.""" 0526 try: 0527 tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater) 0528 except EndOfBlock, eob: 0529 return lines[:eob.args[0]] 0530 # Fooling the indent/dedent logic implies a one-line definition 0531 return lines[:1] 0532 0533 def getsourcelines(object): 0534 """Return a list of source lines and starting line number for an object. 0535 0536 The argument may be a module, class, method, function, traceback, frame, 0537 or code object. The source code is returned as a list of the lines 0538 corresponding to the object and the line number indicates where in the 0539 original source file the first line of code was found. An IOError is 0540 raised if the source code cannot be retrieved.""" 0541 lines, lnum = findsource(object) 0542 0543 if ismodule(object): return lines, 0 0544 else: return getblock(lines[lnum:]), lnum + 1 0545 0546 def getsource(object): 0547 """Return the text of the source code for an object. 0548 0549 The argument may be a module, class, method, function, traceback, frame, 0550 or code object. The source code is returned as a single string. An 0551 IOError is raised if the source code cannot be retrieved.""" 0552 lines, lnum = getsourcelines(object) 0553 return string.join(lines, '') 0554 0555 # --------------------------------------------------- class tree extraction 0556 def walktree(classes, children, parent): 0557 """Recursive helper function for getclasstree().""" 0558 results = [] 0559 classes.sort(key=lambda c: (c.__module__, c.__name__)) 0560 for c in classes: 0561 results.append((c, c.__bases__)) 0562 if c in children: 0563 results.append(walktree(children[c], children, c)) 0564 return results 0565 0566 def getclasstree(classes, unique=0): 0567 """Arrange the given list of classes into a hierarchy of nested lists. 0568 0569 Where a nested list appears, it contains classes derived from the class 0570 whose entry immediately precedes the list. Each entry is a 2-tuple 0571 containing a class and a tuple of its base classes. If the 'unique' 0572 argument is true, exactly one entry appears in the returned structure 0573 for each class in the given list. Otherwise, classes using multiple 0574 inheritance and their descendants will appear multiple times.""" 0575 children = {} 0576 roots = [] 0577 for c in classes: 0578 if c.__bases__: 0579 for parent in c.__bases__: 0580 if not parent in children: 0581 children[parent] = [] 0582 children[parent].append(c) 0583 if unique and parent in classes: break 0584 elif c not in roots: 0585 roots.append(c) 0586 for parent in children: 0587 if parent not in classes: 0588 roots.append(parent) 0589 return walktree(roots, children, None) 0590 0591 # ------------------------------------------------ argument list extraction 0592 # These constants are from Python's compile.h. 0593 CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8 0594 0595 def getargs(co): 0596 """Get information about the arguments accepted by a code object. 0597 0598 Three things are returned: (args, varargs, varkw), where 'args' is 0599 a list of argument names (possibly containing nested lists), and 0600 'varargs' and 'varkw' are the names of the * and ** arguments or None.""" 0601 0602 if not iscode(co): 0603 raise TypeError('arg is not a code object') 0604 0605 code = co.co_code 0606 nargs = co.co_argcount 0607 names = co.co_varnames 0608 args = list(names[:nargs]) 0609 step = 0 0610 0611 # The following acrobatics are for anonymous (tuple) arguments. 0612 for i in range(nargs): 0613 if args[i][:1] in ['', '.']: 0614 stack, remain, count = [], [], [] 0615 while step < len(code): 0616 op = ord(code[step]) 0617 step = step + 1 0618 if op >= dis.HAVE_ARGUMENT: 0619 opname = dis.opname[op] 0620 value = ord(code[step]) + ord(code[step+1])*256 0621 step = step + 2 0622 if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']: 0623 remain.append(value) 0624 count.append(value) 0625 elif opname == 'STORE_FAST': 0626 stack.append(names[value]) 0627 0628 # Special case for sublists of length 1: def foo((bar)) 0629 # doesn't generate the UNPACK_TUPLE bytecode, so if 0630 # `remain` is empty here, we have such a sublist. 0631 if not remain: 0632 stack[0] = [stack[0]] 0633 break 0634 else: 0635 remain[-1] = remain[-1] - 1 0636 while remain[-1] == 0: 0637 remain.pop() 0638 size = count.pop() 0639 stack[-size:] = [stack[-size:]] 0640 if not remain: break 0641 remain[-1] = remain[-1] - 1 0642 if not remain: break 0643 args[i] = stack[0] 0644 0645 varargs = None 0646 if co.co_flags & CO_VARARGS: 0647 varargs = co.co_varnames[nargs] 0648 nargs = nargs + 1 0649 varkw = None 0650 if co.co_flags & CO_VARKEYWORDS: 0651 varkw = co.co_varnames[nargs] 0652 return args, varargs, varkw 0653 0654 def getargspec(func): 0655 """Get the names and default values of a function's arguments. 0656 0657 A tuple of four things is returned: (args, varargs, varkw, defaults). 0658 'args' is a list of the argument names (it may contain nested lists). 0659 'varargs' and 'varkw' are the names of the * and ** arguments or None. 0660 'defaults' is an n-tuple of the default values of the last n arguments. 0661 """ 0662 0663 if ismethod(func): 0664 func = func.im_func 0665 if not isfunction(func): 0666 raise TypeError('arg is not a Python function') 0667 args, varargs, varkw = getargs(func.func_code) 0668 return args, varargs, varkw, func.func_defaults 0669 0670 def getargvalues(frame): 0671 """Get information about arguments passed into a particular frame. 0672 0673 A tuple of four things is returned: (args, varargs, varkw, locals). 0674 'args' is a list of the argument names (it may contain nested lists). 0675 'varargs' and 'varkw' are the names of the * and ** arguments or None. 0676 'locals' is the locals dictionary of the given frame.""" 0677 args, varargs, varkw = getargs(frame.f_code) 0678 return args, varargs, varkw, frame.f_locals 0679 0680 def joinseq(seq): 0681 if len(seq) == 1: 0682 return '(' + seq[0] + ',)' 0683 else: 0684 return '(' + string.join(seq, ', ') + ')' 0685 0686 def strseq(object, convert, join=joinseq): 0687 """Recursively walk a sequence, stringifying each element.""" 0688 if type(object) in [types.ListType, types.TupleType]: 0689 return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object)) 0690 else: 0691 return convert(object) 0692 0693 def formatargspec(args, varargs=None, varkw=None, defaults=None, 0694 formatarg=str, 0695 formatvarargs=lambda name: '*' + name, 0696 formatvarkw=lambda name: '**' + name, 0697 formatvalue=lambda value: '=' + repr(value), 0698 join=joinseq): 0699 """Format an argument spec from the 4 values returned by getargspec. 0700 0701 The first four arguments are (args, varargs, varkw, defaults). The 0702 other four arguments are the corresponding optional formatting functions 0703 that are called to turn names and values into strings. The ninth 0704 argument is an optional function to format the sequence of arguments.""" 0705 specs = [] 0706 if defaults: 0707 firstdefault = len(args) - len(defaults) 0708 for i in range(len(args)): 0709 spec = strseq(args[i], formatarg, join) 0710 if defaults and i >= firstdefault: 0711 spec = spec + formatvalue(defaults[i - firstdefault]) 0712 specs.append(spec) 0713 if varargs is not None: 0714 specs.append(formatvarargs(varargs)) 0715 if varkw is not None: 0716 specs.append(formatvarkw(varkw)) 0717 return '(' + string.join(specs, ', ') + ')' 0718 0719 def formatargvalues(args, varargs, varkw, locals, 0720 formatarg=str, 0721 formatvarargs=lambda name: '*' + name, 0722 formatvarkw=lambda name: '**' + name, 0723 formatvalue=lambda value: '=' + repr(value), 0724 join=joinseq): 0725 """Format an argument spec from the 4 values returned by getargvalues. 0726 0727 The first four arguments are (args, varargs, varkw, locals). The 0728 next four arguments are the corresponding optional formatting functions 0729 that are called to turn names and values into strings. The ninth 0730 argument is an optional function to format the sequence of arguments.""" 0731 def convert(name, locals=locals, 0732 formatarg=formatarg, formatvalue=formatvalue): 0733 return formatarg(name) + formatvalue(locals[name]) 0734 specs = [] 0735 for i in range(len(args)): 0736 specs.append(strseq(args[i], convert, join)) 0737 if varargs: 0738 specs.append(formatvarargs(varargs) + formatvalue(locals[varargs])) 0739 if varkw: 0740 specs.append(formatvarkw(varkw) + formatvalue(locals[varkw])) 0741 return '(' + string.join(specs, ', ') + ')' 0742 0743 # -------------------------------------------------- stack frame extraction 0744 def getframeinfo(frame, context=1): 0745 """Get information about a frame or traceback object. 0746 0747 A tuple of five things is returned: the filename, the line number of 0748 the current line, the function name, a list of lines of context from 0749 the source code, and the index of the current line within that list. 0750 The optional second argument specifies the number of lines of context 0751 to return, which are centered around the current line.""" 0752 if istraceback(frame): 0753 lineno = frame.tb_lineno 0754 frame = frame.tb_frame 0755 else: 0756 lineno = frame.f_lineno 0757 if not isframe(frame): 0758 raise TypeError('arg is not a frame or traceback object') 0759 0760 filename = getsourcefile(frame) or getfile(frame) 0761 if context > 0: 0762 start = lineno - 1 - context//2 0763 try: 0764 lines, lnum = findsource(frame) 0765 except IOError: 0766 lines = index = None 0767 else: 0768 start = max(start, 1) 0769 start = max(0, min(start, len(lines) - context)) 0770 lines = lines[start:start+context] 0771 index = lineno - 1 - start 0772 else: 0773 lines = index = None 0774 0775 return (filename, lineno, frame.f_code.co_name, lines, index) 0776 0777 def getlineno(frame): 0778 """Get the line number from a frame object, allowing for optimization.""" 0779 # FrameType.f_lineno is now a descriptor that grovels co_lnotab 0780 return frame.f_lineno 0781 0782 def getouterframes(frame, context=1): 0783 """Get a list of records for a frame and all higher (calling) frames. 0784 0785 Each record contains a frame object, filename, line number, function 0786 name, a list of lines of context, and index within the context.""" 0787 framelist = [] 0788 while frame: 0789 framelist.append((frame,) + getframeinfo(frame, context)) 0790 frame = frame.f_back 0791 return framelist 0792 0793 def getinnerframes(tb, context=1): 0794 """Get a list of records for a traceback's frame and all lower frames. 0795 0796 Each record contains a frame object, filename, line number, function 0797 name, a list of lines of context, and index within the context.""" 0798 framelist = [] 0799 while tb: 0800 framelist.append((tb.tb_frame,) + getframeinfo(tb, context)) 0801 tb = tb.tb_next 0802 return framelist 0803 0804 currentframe = sys._getframe 0805 0806 def stack(context=1): 0807 """Return a list of records for the stack above the caller's frame.""" 0808 return getouterframes(sys._getframe(1), context) 0809 0810 def trace(context=1): 0811 """Return a list of records for the stack below the current exception.""" 0812 return getinnerframes(sys.exc_info()[2], context) 0813
Generated by PyXR 0.9.4