blob: f62167ba2e39e2a5b6b056b269c34a22f5ecb574 [file] [log] [blame]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +00001"""Get useful information from live Python objects.
2
3This module encapsulates the interface provided by the internal special
4attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
5It also provides some help for examining source code and class layout.
6
7Here are some of the useful functions provided by this module:
8
9 ismodule(), isclass(), ismethod(), isfunction(), istraceback(),
10 isframe(), iscode(), isbuiltin(), isroutine() - check object types
11 getmembers() - get members of an object that satisfy a given condition
12
13 getfile(), getsourcefile(), getsource() - find an object's source code
14 getdoc(), getcomments() - get documentation on an object
15 getmodule() - determine the module that an object came from
16 getclasstree() - arrange classes so as to represent their hierarchy
17
18 getargspec(), getargvalues() - get info about function arguments
19 formatargspec(), formatargvalues() - format an argument spec
20 getouterframes(), getinnerframes() - get info about frames
21 currentframe() - get the current stack frame
22 stack(), trace() - get info about frames on the stack or in a traceback
23"""
24
25# This module is in the public domain. No warranties.
26
Ka-Ping Yee8b58b842001-03-01 13:56:16 +000027__author__ = 'Ka-Ping Yee <ping@lfw.org>'
28__date__ = '1 Jan 2001'
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000029
Ka-Ping Yeea6e59712001-03-10 09:31:55 +000030import sys, os, types, string, re, dis, imp, tokenize
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000031
32# ----------------------------------------------------------- type-checking
33def ismodule(object):
34 """Return true if the object is a module.
35
36 Module objects provide these attributes:
37 __doc__ documentation string
38 __file__ filename (missing for built-in modules)"""
39 return type(object) is types.ModuleType
40
41def isclass(object):
42 """Return true if the object is a class.
43
44 Class objects provide these attributes:
45 __doc__ documentation string
46 __module__ name of module in which this class was defined"""
Ka-Ping Yeea9c6c8d2001-03-23 15:29:59 +000047 return type(object) is types.ClassType or hasattr(object, '__bases__')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000048
49def ismethod(object):
50 """Return true if the object is an instance method.
51
52 Instance method objects provide these attributes:
53 __doc__ documentation string
54 __name__ name with which this method was defined
55 im_class class object in which this method belongs
56 im_func function object containing implementation of method
57 im_self instance to which this method is bound, or None"""
58 return type(object) is types.MethodType
59
60def isfunction(object):
61 """Return true if the object is a user-defined function.
62
63 Function objects provide these attributes:
64 __doc__ documentation string
65 __name__ name with which this function was defined
66 func_code code object containing compiled function bytecode
67 func_defaults tuple of any default values for arguments
68 func_doc (same as __doc__)
69 func_globals global namespace in which this function was defined
70 func_name (same as __name__)"""
71 return type(object) in [types.FunctionType, types.LambdaType]
72
73def istraceback(object):
74 """Return true if the object is a traceback.
75
76 Traceback objects provide these attributes:
77 tb_frame frame object at this level
78 tb_lasti index of last attempted instruction in bytecode
79 tb_lineno current line number in Python source code
80 tb_next next inner traceback object (called by this level)"""
81 return type(object) is types.TracebackType
82
83def isframe(object):
84 """Return true if the object is a frame object.
85
86 Frame objects provide these attributes:
87 f_back next outer frame object (this frame's caller)
88 f_builtins built-in namespace seen by this frame
89 f_code code object being executed in this frame
90 f_exc_traceback traceback if raised in this frame, or None
91 f_exc_type exception type if raised in this frame, or None
92 f_exc_value exception value if raised in this frame, or None
93 f_globals global namespace seen by this frame
94 f_lasti index of last attempted instruction in bytecode
95 f_lineno current line number in Python source code
96 f_locals local namespace seen by this frame
97 f_restricted 0 or 1 if frame is in restricted execution mode
98 f_trace tracing function for this frame, or None"""
99 return type(object) is types.FrameType
100
101def iscode(object):
102 """Return true if the object is a code object.
103
104 Code objects provide these attributes:
105 co_argcount number of arguments (not including * or ** args)
106 co_code string of raw compiled bytecode
107 co_consts tuple of constants used in the bytecode
108 co_filename name of file in which this code object was created
109 co_firstlineno number of first line in Python source code
110 co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
111 co_lnotab encoded mapping of line numbers to bytecode indices
112 co_name name with which this code object was defined
113 co_names tuple of names of local variables
114 co_nlocals number of local variables
115 co_stacksize virtual machine stack space required
116 co_varnames tuple of names of arguments and local variables"""
117 return type(object) is types.CodeType
118
119def isbuiltin(object):
120 """Return true if the object is a built-in function or method.
121
122 Built-in functions and methods provide these attributes:
123 __doc__ documentation string
124 __name__ original name of this function or method
125 __self__ instance to which a method is bound, or None"""
Ka-Ping Yee202c99b2001-04-13 09:15:08 +0000126 return type(object) is types.BuiltinFunctionType
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000127
128def isroutine(object):
129 """Return true if the object is any kind of function or method."""
130 return type(object) in [types.FunctionType, types.LambdaType,
Ka-Ping Yee202c99b2001-04-13 09:15:08 +0000131 types.MethodType, types.BuiltinFunctionType]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000132
133def getmembers(object, predicate=None):
134 """Return all members of an object as (name, value) pairs sorted by name.
135 Optionally, only return members that satisfy a given predicate."""
136 results = []
137 for key in dir(object):
138 value = getattr(object, key)
139 if not predicate or predicate(value):
140 results.append((key, value))
141 results.sort()
142 return results
143
144# -------------------------------------------------- source code extraction
145def indentsize(line):
146 """Return the indent size, in spaces, at the start of a line of text."""
147 expline = string.expandtabs(line)
148 return len(expline) - len(string.lstrip(expline))
149
150def getdoc(object):
151 """Get the documentation string for an object.
152
153 All tabs are expanded to spaces. To clean up docstrings that are
154 indented to line up with blocks of code, any whitespace than can be
155 uniformly removed from the second line onwards is removed."""
156 if hasattr(object, '__doc__') and object.__doc__:
157 lines = string.split(string.expandtabs(object.__doc__), '\n')
158 margin = None
159 for line in lines[1:]:
160 content = len(string.lstrip(line))
161 if not content: continue
162 indent = len(line) - content
163 if margin is None: margin = indent
164 else: margin = min(margin, indent)
165 if margin is not None:
166 for i in range(1, len(lines)): lines[i] = lines[i][margin:]
167 return string.join(lines, '\n')
168
169def getfile(object):
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000170 """Work out which source or compiled file an object was defined in."""
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000171 if ismodule(object):
172 if hasattr(object, '__file__'):
173 return object.__file__
174 raise TypeError, 'arg is a built-in module'
175 if isclass(object):
176 object = sys.modules[object.__module__]
177 if hasattr(object, '__file__'):
178 return object.__file__
179 raise TypeError, 'arg is a built-in class'
180 if ismethod(object):
181 object = object.im_func
182 if isfunction(object):
183 object = object.func_code
184 if istraceback(object):
185 object = object.tb_frame
186 if isframe(object):
187 object = object.f_code
188 if iscode(object):
189 return object.co_filename
190 raise TypeError, 'arg is not a module, class, method, ' \
191 'function, traceback, frame, or code object'
192
Ka-Ping Yee4d6fc7f2001-04-10 11:43:00 +0000193def getmoduleinfo(path):
194 """Get the module name, suffix, mode, and module type for a given file."""
195 filename = os.path.basename(path)
196 suffixes = map(lambda (suffix, mode, mtype):
197 (-len(suffix), suffix, mode, mtype), imp.get_suffixes())
198 suffixes.sort() # try longest suffixes first, in case they overlap
199 for neglen, suffix, mode, mtype in suffixes:
200 if filename[neglen:] == suffix:
201 return filename[:neglen], suffix, mode, mtype
202
203def getmodulename(path):
204 """Return the module name for a given file, or None."""
205 info = getmoduleinfo(path)
206 if info: return info[0]
207
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000208def getsourcefile(object):
209 """Return the Python source file an object was defined in, if it exists."""
210 filename = getfile(object)
211 if string.lower(filename[-4:]) in ['.pyc', '.pyo']:
212 filename = filename[:-4] + '.py'
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000213 for suffix, mode, kind in imp.get_suffixes():
214 if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix:
215 # Looks like a binary file. We want to only return a text file.
216 return None
217 if os.path.exists(filename):
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000218 return filename
219
220def getabsfile(object):
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000221 """Return an absolute path to the source or compiled file for an object.
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000222
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000223 The idea is for each object to have a unique origin, so this routine
224 normalizes the result as much as possible."""
225 return os.path.normcase(
226 os.path.abspath(getsourcefile(object) or getfile(object)))
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000227
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000228modulesbyfile = {}
229
230def getmodule(object):
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000231 """Return the module an object was defined in, or None if not found."""
Ka-Ping Yee202c99b2001-04-13 09:15:08 +0000232 if ismodule(object):
233 return object
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000234 if isclass(object):
Ka-Ping Yee8b58b842001-03-01 13:56:16 +0000235 return sys.modules.get(object.__module__)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000236 try:
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000237 file = getabsfile(object)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000238 except TypeError:
239 return None
240 if modulesbyfile.has_key(file):
241 return sys.modules[modulesbyfile[file]]
242 for module in sys.modules.values():
243 if hasattr(module, '__file__'):
Ka-Ping Yeec113c242001-03-02 02:08:53 +0000244 modulesbyfile[getabsfile(module)] = module.__name__
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000245 if modulesbyfile.has_key(file):
246 return sys.modules[modulesbyfile[file]]
247 main = sys.modules['__main__']
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000248 if hasattr(main, object.__name__):
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000249 mainobject = getattr(main, object.__name__)
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000250 if mainobject is object:
251 return main
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000252 builtin = sys.modules['__builtin__']
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000253 if hasattr(builtin, object.__name__):
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000254 builtinobject = getattr(builtin, object.__name__)
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000255 if builtinobject is object:
256 return builtin
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000257
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000258def findsource(object):
259 """Return the entire source file and starting line number for an object.
260
261 The argument may be a module, class, method, function, traceback, frame,
262 or code object. The source code is returned as a list of all the lines
263 in the file and the line number indexes a line in that list. An IOError
264 is raised if the source code cannot be retrieved."""
265 try:
266 file = open(getsourcefile(object))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000267 except (TypeError, IOError):
268 raise IOError, 'could not get source code'
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000269 lines = file.readlines()
270 file.close()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000271
272 if ismodule(object):
273 return lines, 0
274
275 if isclass(object):
276 name = object.__name__
Ka-Ping Yeea6e59712001-03-10 09:31:55 +0000277 pat = re.compile(r'^\s*class\s*' + name + r'\b')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000278 for i in range(len(lines)):
Ka-Ping Yeea6e59712001-03-10 09:31:55 +0000279 if pat.match(lines[i]): return lines, i
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000280 else: raise IOError, 'could not find class definition'
281
282 if ismethod(object):
283 object = object.im_func
284 if isfunction(object):
285 object = object.func_code
286 if istraceback(object):
287 object = object.tb_frame
288 if isframe(object):
289 object = object.f_code
290 if iscode(object):
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000291 if not hasattr(object, 'co_firstlineno'):
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000292 raise IOError, 'could not find function definition'
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000293 lnum = object.co_firstlineno - 1
Ka-Ping Yeea6e59712001-03-10 09:31:55 +0000294 pat = re.compile(r'^\s*def\s')
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000295 while lnum > 0:
Ka-Ping Yeea6e59712001-03-10 09:31:55 +0000296 if pat.match(lines[lnum]): break
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000297 lnum = lnum - 1
298 return lines, lnum
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000299
300def getcomments(object):
301 """Get lines of comments immediately preceding an object's source code."""
302 try: lines, lnum = findsource(object)
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000303 except IOError: return None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000304
305 if ismodule(object):
306 # Look for a comment block at the top of the file.
307 start = 0
Ka-Ping Yeeb910efe2001-04-12 13:17:17 +0000308 if lines and lines[0][:2] == '#!': start = 1
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000309 while start < len(lines) and string.strip(lines[start]) in ['', '#']:
310 start = start + 1
Ka-Ping Yeeb910efe2001-04-12 13:17:17 +0000311 if start < len(lines) and lines[start][:1] == '#':
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000312 comments = []
313 end = start
314 while end < len(lines) and lines[end][:1] == '#':
315 comments.append(string.expandtabs(lines[end]))
316 end = end + 1
317 return string.join(comments, '')
318
319 # Look for a preceding block of comments at the same indentation.
320 elif lnum > 0:
321 indent = indentsize(lines[lnum])
322 end = lnum - 1
323 if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
324 indentsize(lines[end]) == indent:
325 comments = [string.lstrip(string.expandtabs(lines[end]))]
326 if end > 0:
327 end = end - 1
328 comment = string.lstrip(string.expandtabs(lines[end]))
329 while comment[:1] == '#' and indentsize(lines[end]) == indent:
330 comments[:0] = [comment]
331 end = end - 1
332 if end < 0: break
333 comment = string.lstrip(string.expandtabs(lines[end]))
334 while comments and string.strip(comments[0]) == '#':
335 comments[:1] = []
336 while comments and string.strip(comments[-1]) == '#':
337 comments[-1:] = []
338 return string.join(comments, '')
339
340class ListReader:
341 """Provide a readline() method to return lines from a list of strings."""
342 def __init__(self, lines):
343 self.lines = lines
344 self.index = 0
345
346 def readline(self):
347 i = self.index
348 if i < len(self.lines):
349 self.index = i + 1
350 return self.lines[i]
351 else: return ''
352
353class EndOfBlock(Exception): pass
354
355class BlockFinder:
356 """Provide a tokeneater() method to detect the end of a code block."""
357 def __init__(self):
358 self.indent = 0
359 self.started = 0
360 self.last = 0
361
362 def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
363 if not self.started:
364 if type == tokenize.NAME: self.started = 1
365 elif type == tokenize.NEWLINE:
366 self.last = srow
367 elif type == tokenize.INDENT:
368 self.indent = self.indent + 1
369 elif type == tokenize.DEDENT:
370 self.indent = self.indent - 1
371 if self.indent == 0: raise EndOfBlock, self.last
372
373def getblock(lines):
374 """Extract the block of code at the top of the given list of lines."""
375 try:
376 tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater)
377 except EndOfBlock, eob:
378 return lines[:eob.args[0]]
379
380def getsourcelines(object):
381 """Return a list of source lines and starting line number for an object.
382
383 The argument may be a module, class, method, function, traceback, frame,
384 or code object. The source code is returned as a list of the lines
385 corresponding to the object and the line number indicates where in the
386 original source file the first line of code was found. An IOError is
387 raised if the source code cannot be retrieved."""
388 lines, lnum = findsource(object)
389
390 if ismodule(object): return lines, 0
391 else: return getblock(lines[lnum:]), lnum + 1
392
393def getsource(object):
394 """Return the text of the source code for an object.
395
396 The argument may be a module, class, method, function, traceback, frame,
397 or code object. The source code is returned as a single string. An
398 IOError is raised if the source code cannot be retrieved."""
399 lines, lnum = getsourcelines(object)
400 return string.join(lines, '')
401
402# --------------------------------------------------- class tree extraction
403def walktree(classes, children, parent):
404 """Recursive helper function for getclasstree()."""
405 results = []
406 classes.sort(lambda a, b: cmp(a.__name__, b.__name__))
407 for c in classes:
408 results.append((c, c.__bases__))
409 if children.has_key(c):
410 results.append(walktree(children[c], children, c))
411 return results
412
413def getclasstree(classes, unique=0):
414 """Arrange the given list of classes into a hierarchy of nested lists.
415
416 Where a nested list appears, it contains classes derived from the class
417 whose entry immediately precedes the list. Each entry is a 2-tuple
418 containing a class and a tuple of its base classes. If the 'unique'
419 argument is true, exactly one entry appears in the returned structure
420 for each class in the given list. Otherwise, classes using multiple
421 inheritance and their descendants will appear multiple times."""
422 children = {}
423 roots = []
424 for c in classes:
425 if c.__bases__:
426 for parent in c.__bases__:
427 if not children.has_key(parent):
428 children[parent] = []
429 children[parent].append(c)
430 if unique and parent in classes: break
431 elif c not in roots:
432 roots.append(c)
433 for parent in children.keys():
434 if parent not in classes:
435 roots.append(parent)
436 return walktree(roots, children, None)
437
438# ------------------------------------------------ argument list extraction
439# These constants are from Python's compile.h.
440CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
441
442def getargs(co):
443 """Get information about the arguments accepted by a code object.
444
445 Three things are returned: (args, varargs, varkw), where 'args' is
446 a list of argument names (possibly containing nested lists), and
447 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
448 if not iscode(co): raise TypeError, 'arg is not a code object'
449
450 code = co.co_code
451 nargs = co.co_argcount
452 names = co.co_varnames
453 args = list(names[:nargs])
454 step = 0
455
456 # The following acrobatics are for anonymous (tuple) arguments.
457 for i in range(nargs):
458 if args[i][:1] in ['', '.']:
459 stack, remain, count = [], [], []
460 while step < len(code):
461 op = ord(code[step])
462 step = step + 1
463 if op >= dis.HAVE_ARGUMENT:
464 opname = dis.opname[op]
465 value = ord(code[step]) + ord(code[step+1])*256
466 step = step + 2
467 if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']:
468 remain.append(value)
469 count.append(value)
470 elif opname == 'STORE_FAST':
471 stack.append(names[value])
472 remain[-1] = remain[-1] - 1
473 while remain[-1] == 0:
474 remain.pop()
475 size = count.pop()
476 stack[-size:] = [stack[-size:]]
477 if not remain: break
478 remain[-1] = remain[-1] - 1
479 if not remain: break
480 args[i] = stack[0]
481
482 varargs = None
483 if co.co_flags & CO_VARARGS:
484 varargs = co.co_varnames[nargs]
485 nargs = nargs + 1
486 varkw = None
487 if co.co_flags & CO_VARKEYWORDS:
488 varkw = co.co_varnames[nargs]
489 return args, varargs, varkw
490
491def getargspec(func):
492 """Get the names and default values of a function's arguments.
493
494 A tuple of four things is returned: (args, varargs, varkw, defaults).
495 'args' is a list of the argument names (it may contain nested lists).
496 'varargs' and 'varkw' are the names of the * and ** arguments or None.
497 'defaults' is an n-tuple of the default values of the last n arguments."""
498 if not isfunction(func): raise TypeError, 'arg is not a Python function'
499 args, varargs, varkw = getargs(func.func_code)
500 return args, varargs, varkw, func.func_defaults
501
502def getargvalues(frame):
503 """Get information about arguments passed into a particular frame.
504
505 A tuple of four things is returned: (args, varargs, varkw, locals).
506 'args' is a list of the argument names (it may contain nested lists).
507 'varargs' and 'varkw' are the names of the * and ** arguments or None.
508 'locals' is the locals dictionary of the given frame."""
509 args, varargs, varkw = getargs(frame.f_code)
510 return args, varargs, varkw, frame.f_locals
511
512def joinseq(seq):
513 if len(seq) == 1:
514 return '(' + seq[0] + ',)'
515 else:
516 return '(' + string.join(seq, ', ') + ')'
517
518def strseq(object, convert, join=joinseq):
519 """Recursively walk a sequence, stringifying each element."""
520 if type(object) in [types.ListType, types.TupleType]:
521 return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
522 else:
523 return convert(object)
524
525def formatargspec(args, varargs=None, varkw=None, defaults=None,
526 formatarg=str,
527 formatvarargs=lambda name: '*' + name,
528 formatvarkw=lambda name: '**' + name,
529 formatvalue=lambda value: '=' + repr(value),
530 join=joinseq):
531 """Format an argument spec from the 4 values returned by getargspec.
532
533 The first four arguments are (args, varargs, varkw, defaults). The
534 other four arguments are the corresponding optional formatting functions
535 that are called to turn names and values into strings. The ninth
536 argument is an optional function to format the sequence of arguments."""
537 specs = []
538 if defaults:
539 firstdefault = len(args) - len(defaults)
540 for i in range(len(args)):
541 spec = strseq(args[i], formatarg, join)
542 if defaults and i >= firstdefault:
543 spec = spec + formatvalue(defaults[i - firstdefault])
544 specs.append(spec)
545 if varargs:
546 specs.append(formatvarargs(varargs))
547 if varkw:
548 specs.append(formatvarkw(varkw))
549 return '(' + string.join(specs, ', ') + ')'
550
551def formatargvalues(args, varargs, varkw, locals,
552 formatarg=str,
553 formatvarargs=lambda name: '*' + name,
554 formatvarkw=lambda name: '**' + name,
555 formatvalue=lambda value: '=' + repr(value),
556 join=joinseq):
557 """Format an argument spec from the 4 values returned by getargvalues.
558
559 The first four arguments are (args, varargs, varkw, locals). The
560 next four arguments are the corresponding optional formatting functions
561 that are called to turn names and values into strings. The ninth
562 argument is an optional function to format the sequence of arguments."""
563 def convert(name, locals=locals,
564 formatarg=formatarg, formatvalue=formatvalue):
565 return formatarg(name) + formatvalue(locals[name])
566 specs = []
567 for i in range(len(args)):
568 specs.append(strseq(args[i], convert, join))
569 if varargs:
570 specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
571 if varkw:
572 specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
573 return '(' + string.join(specs, ', ') + ')'
574
575# -------------------------------------------------- stack frame extraction
576def getframeinfo(frame, context=1):
577 """Get information about a frame or traceback object.
578
579 A tuple of five things is returned: the filename, the line number of
580 the current line, the function name, a list of lines of context from
581 the source code, and the index of the current line within that list.
582 The optional second argument specifies the number of lines of context
583 to return, which are centered around the current line."""
584 if istraceback(frame):
585 frame = frame.tb_frame
586 if not isframe(frame):
587 raise TypeError, 'arg is not a frame or traceback object'
588
589 filename = getsourcefile(frame)
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000590 lineno = getlineno(frame)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000591 if context > 0:
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000592 start = lineno - 1 - context/2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000593 try:
594 lines, lnum = findsource(frame)
Ka-Ping Yee4eb0c002001-03-02 05:50:34 +0000595 except IOError:
596 lines = index = None
597 else:
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000598 start = max(start, 1)
599 start = min(start, len(lines) - context)
600 lines = lines[start:start+context]
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000601 index = lineno - 1 - start
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000602 else:
603 lines = index = None
604
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000605 return (filename, lineno, frame.f_code.co_name, lines, index)
606
607def getlineno(frame):
608 """Get the line number from a frame object, allowing for optimization."""
609 # Written by Marc-André Lemburg; revised by Jim Hugunin and Fredrik Lundh.
610 lineno = frame.f_lineno
611 code = frame.f_code
612 if hasattr(code, 'co_lnotab'):
613 table = code.co_lnotab
614 lineno = code.co_firstlineno
615 addr = 0
616 for i in range(0, len(table), 2):
617 addr = addr + ord(table[i])
618 if addr > frame.f_lasti: break
619 lineno = lineno + ord(table[i+1])
620 return lineno
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000621
622def getouterframes(frame, context=1):
623 """Get a list of records for a frame and all higher (calling) frames.
624
625 Each record contains a frame object, filename, line number, function
626 name, a list of lines of context, and index within the context."""
627 framelist = []
628 while frame:
629 framelist.append((frame,) + getframeinfo(frame, context))
630 frame = frame.f_back
631 return framelist
632
633def getinnerframes(tb, context=1):
634 """Get a list of records for a traceback's frame and all lower frames.
635
636 Each record contains a frame object, filename, line number, function
637 name, a list of lines of context, and index within the context."""
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000638 framelist = []
639 while tb:
640 framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
641 tb = tb.tb_next
642 return framelist
643
644def currentframe():
645 """Return the frame object for the caller's stack frame."""
646 try:
647 raise 'catch me'
648 except:
649 return sys.exc_traceback.tb_frame.f_back
650
651if hasattr(sys, '_getframe'): currentframe = sys._getframe
652
653def stack(context=1):
654 """Return a list of records for the stack above the caller's frame."""
655 return getouterframes(currentframe().f_back, context)
656
657def trace(context=1):
Tim Peters85ba6732001-02-28 08:26:44 +0000658 """Return a list of records for the stack below the current exception."""
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000659 return getinnerframes(sys.exc_traceback, context)