blob: ac0ee44ccd35cf3ffaa62a8e76a3ecfa29bf4463 [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 Yee7a257652001-03-02 01:19:39 +000030import sys, os, types, string, 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"""
47 return type(object) is types.ClassType
48
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"""
126 return type(object) in [types.BuiltinFunctionType,
127 types.BuiltinMethodType]
128
129def isroutine(object):
130 """Return true if the object is any kind of function or method."""
131 return type(object) in [types.FunctionType, types.LambdaType,
132 types.MethodType, types.BuiltinFunctionType,
133 types.BuiltinMethodType]
134
135def getmembers(object, predicate=None):
136 """Return all members of an object as (name, value) pairs sorted by name.
137 Optionally, only return members that satisfy a given predicate."""
138 results = []
139 for key in dir(object):
140 value = getattr(object, key)
141 if not predicate or predicate(value):
142 results.append((key, value))
143 results.sort()
144 return results
145
146# -------------------------------------------------- source code extraction
147def indentsize(line):
148 """Return the indent size, in spaces, at the start of a line of text."""
149 expline = string.expandtabs(line)
150 return len(expline) - len(string.lstrip(expline))
151
152def getdoc(object):
153 """Get the documentation string for an object.
154
155 All tabs are expanded to spaces. To clean up docstrings that are
156 indented to line up with blocks of code, any whitespace than can be
157 uniformly removed from the second line onwards is removed."""
158 if hasattr(object, '__doc__') and object.__doc__:
159 lines = string.split(string.expandtabs(object.__doc__), '\n')
160 margin = None
161 for line in lines[1:]:
162 content = len(string.lstrip(line))
163 if not content: continue
164 indent = len(line) - content
165 if margin is None: margin = indent
166 else: margin = min(margin, indent)
167 if margin is not None:
168 for i in range(1, len(lines)): lines[i] = lines[i][margin:]
169 return string.join(lines, '\n')
170
171def getfile(object):
172 """Try to guess which (text or binary) file an object was defined in."""
173 if ismodule(object):
174 if hasattr(object, '__file__'):
175 return object.__file__
176 raise TypeError, 'arg is a built-in module'
177 if isclass(object):
178 object = sys.modules[object.__module__]
179 if hasattr(object, '__file__'):
180 return object.__file__
181 raise TypeError, 'arg is a built-in class'
182 if ismethod(object):
183 object = object.im_func
184 if isfunction(object):
185 object = object.func_code
186 if istraceback(object):
187 object = object.tb_frame
188 if isframe(object):
189 object = object.f_code
190 if iscode(object):
191 return object.co_filename
192 raise TypeError, 'arg is not a module, class, method, ' \
193 'function, traceback, frame, or code object'
194
195modulesbyfile = {}
196
197def getmodule(object):
198 """Try to guess which module an object was defined in."""
199 if isclass(object):
Ka-Ping Yee8b58b842001-03-01 13:56:16 +0000200 return sys.modules.get(object.__module__)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000201 try:
Ka-Ping Yee7a257652001-03-02 01:19:39 +0000202 file = os.path.abspath(getsourcefile(object))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000203 except TypeError:
204 return None
205 if modulesbyfile.has_key(file):
206 return sys.modules[modulesbyfile[file]]
207 for module in sys.modules.values():
208 if hasattr(module, '__file__'):
Ka-Ping Yee7a257652001-03-02 01:19:39 +0000209 modulesbyfile[
210 os.path.abspath(getsourcefile(module))] = module.__name__
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000211 if modulesbyfile.has_key(file):
212 return sys.modules[modulesbyfile[file]]
213 main = sys.modules['__main__']
214 try:
215 mainobject = getattr(main, object.__name__)
216 if mainobject is object: return main
217 except AttributeError: pass
218 builtin = sys.modules['__builtin__']
219 try:
220 builtinobject = getattr(builtin, object.__name__)
221 if builtinobject is object: return builtin
222 except AttributeError: pass
223
224def getsourcefile(object):
225 """Try to guess which Python source file an object was defined in."""
226 filename = getfile(object)
227 if filename[-4:] == '.pyc':
228 filename = filename[:-4] + '.py'
229 return filename
230
231def findsource(object):
232 """Return the entire source file and starting line number for an object.
233
234 The argument may be a module, class, method, function, traceback, frame,
235 or code object. The source code is returned as a list of all the lines
236 in the file and the line number indexes a line in that list. An IOError
237 is raised if the source code cannot be retrieved."""
238 try:
239 file = open(getsourcefile(object))
240 lines = file.readlines()
241 file.close()
242 except (TypeError, IOError):
243 raise IOError, 'could not get source code'
244
245 if ismodule(object):
246 return lines, 0
247
248 if isclass(object):
249 name = object.__name__
250 matches = (['class', name], ['class', name + ':'])
251 for i in range(len(lines)):
252 if string.split(lines[i])[:2] in matches:
253 return lines, i
254 else: raise IOError, 'could not find class definition'
255
256 if ismethod(object):
257 object = object.im_func
258 if isfunction(object):
259 object = object.func_code
260 if istraceback(object):
261 object = object.tb_frame
262 if isframe(object):
263 object = object.f_code
264 if iscode(object):
265 try:
266 lnum = object.co_firstlineno - 1
267 except AttributeError:
268 raise IOError, 'could not find function definition'
269 else:
270 while lnum > 0:
271 if string.split(lines[lnum])[:1] == ['def']: break
272 lnum = lnum - 1
273 return lines, lnum
274
275def getcomments(object):
276 """Get lines of comments immediately preceding an object's source code."""
277 try: lines, lnum = findsource(object)
278 except: return None
279
280 if ismodule(object):
281 # Look for a comment block at the top of the file.
282 start = 0
283 if lines[0][:2] == '#!': start = 1
284 while start < len(lines) and string.strip(lines[start]) in ['', '#']:
285 start = start + 1
286 if lines[start][:1] == '#':
287 comments = []
288 end = start
289 while end < len(lines) and lines[end][:1] == '#':
290 comments.append(string.expandtabs(lines[end]))
291 end = end + 1
292 return string.join(comments, '')
293
294 # Look for a preceding block of comments at the same indentation.
295 elif lnum > 0:
296 indent = indentsize(lines[lnum])
297 end = lnum - 1
298 if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
299 indentsize(lines[end]) == indent:
300 comments = [string.lstrip(string.expandtabs(lines[end]))]
301 if end > 0:
302 end = end - 1
303 comment = string.lstrip(string.expandtabs(lines[end]))
304 while comment[:1] == '#' and indentsize(lines[end]) == indent:
305 comments[:0] = [comment]
306 end = end - 1
307 if end < 0: break
308 comment = string.lstrip(string.expandtabs(lines[end]))
309 while comments and string.strip(comments[0]) == '#':
310 comments[:1] = []
311 while comments and string.strip(comments[-1]) == '#':
312 comments[-1:] = []
313 return string.join(comments, '')
314
315class ListReader:
316 """Provide a readline() method to return lines from a list of strings."""
317 def __init__(self, lines):
318 self.lines = lines
319 self.index = 0
320
321 def readline(self):
322 i = self.index
323 if i < len(self.lines):
324 self.index = i + 1
325 return self.lines[i]
326 else: return ''
327
328class EndOfBlock(Exception): pass
329
330class BlockFinder:
331 """Provide a tokeneater() method to detect the end of a code block."""
332 def __init__(self):
333 self.indent = 0
334 self.started = 0
335 self.last = 0
336
337 def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
338 if not self.started:
339 if type == tokenize.NAME: self.started = 1
340 elif type == tokenize.NEWLINE:
341 self.last = srow
342 elif type == tokenize.INDENT:
343 self.indent = self.indent + 1
344 elif type == tokenize.DEDENT:
345 self.indent = self.indent - 1
346 if self.indent == 0: raise EndOfBlock, self.last
347
348def getblock(lines):
349 """Extract the block of code at the top of the given list of lines."""
350 try:
351 tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater)
352 except EndOfBlock, eob:
353 return lines[:eob.args[0]]
354
355def getsourcelines(object):
356 """Return a list of source lines and starting line number for an object.
357
358 The argument may be a module, class, method, function, traceback, frame,
359 or code object. The source code is returned as a list of the lines
360 corresponding to the object and the line number indicates where in the
361 original source file the first line of code was found. An IOError is
362 raised if the source code cannot be retrieved."""
363 lines, lnum = findsource(object)
364
365 if ismodule(object): return lines, 0
366 else: return getblock(lines[lnum:]), lnum + 1
367
368def getsource(object):
369 """Return the text of the source code for an object.
370
371 The argument may be a module, class, method, function, traceback, frame,
372 or code object. The source code is returned as a single string. An
373 IOError is raised if the source code cannot be retrieved."""
374 lines, lnum = getsourcelines(object)
375 return string.join(lines, '')
376
377# --------------------------------------------------- class tree extraction
378def walktree(classes, children, parent):
379 """Recursive helper function for getclasstree()."""
380 results = []
381 classes.sort(lambda a, b: cmp(a.__name__, b.__name__))
382 for c in classes:
383 results.append((c, c.__bases__))
384 if children.has_key(c):
385 results.append(walktree(children[c], children, c))
386 return results
387
388def getclasstree(classes, unique=0):
389 """Arrange the given list of classes into a hierarchy of nested lists.
390
391 Where a nested list appears, it contains classes derived from the class
392 whose entry immediately precedes the list. Each entry is a 2-tuple
393 containing a class and a tuple of its base classes. If the 'unique'
394 argument is true, exactly one entry appears in the returned structure
395 for each class in the given list. Otherwise, classes using multiple
396 inheritance and their descendants will appear multiple times."""
397 children = {}
398 roots = []
399 for c in classes:
400 if c.__bases__:
401 for parent in c.__bases__:
402 if not children.has_key(parent):
403 children[parent] = []
404 children[parent].append(c)
405 if unique and parent in classes: break
406 elif c not in roots:
407 roots.append(c)
408 for parent in children.keys():
409 if parent not in classes:
410 roots.append(parent)
411 return walktree(roots, children, None)
412
413# ------------------------------------------------ argument list extraction
414# These constants are from Python's compile.h.
415CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
416
417def getargs(co):
418 """Get information about the arguments accepted by a code object.
419
420 Three things are returned: (args, varargs, varkw), where 'args' is
421 a list of argument names (possibly containing nested lists), and
422 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
423 if not iscode(co): raise TypeError, 'arg is not a code object'
424
425 code = co.co_code
426 nargs = co.co_argcount
427 names = co.co_varnames
428 args = list(names[:nargs])
429 step = 0
430
431 # The following acrobatics are for anonymous (tuple) arguments.
432 for i in range(nargs):
433 if args[i][:1] in ['', '.']:
434 stack, remain, count = [], [], []
435 while step < len(code):
436 op = ord(code[step])
437 step = step + 1
438 if op >= dis.HAVE_ARGUMENT:
439 opname = dis.opname[op]
440 value = ord(code[step]) + ord(code[step+1])*256
441 step = step + 2
442 if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']:
443 remain.append(value)
444 count.append(value)
445 elif opname == 'STORE_FAST':
446 stack.append(names[value])
447 remain[-1] = remain[-1] - 1
448 while remain[-1] == 0:
449 remain.pop()
450 size = count.pop()
451 stack[-size:] = [stack[-size:]]
452 if not remain: break
453 remain[-1] = remain[-1] - 1
454 if not remain: break
455 args[i] = stack[0]
456
457 varargs = None
458 if co.co_flags & CO_VARARGS:
459 varargs = co.co_varnames[nargs]
460 nargs = nargs + 1
461 varkw = None
462 if co.co_flags & CO_VARKEYWORDS:
463 varkw = co.co_varnames[nargs]
464 return args, varargs, varkw
465
466def getargspec(func):
467 """Get the names and default values of a function's arguments.
468
469 A tuple of four things is returned: (args, varargs, varkw, defaults).
470 'args' is a list of the argument names (it may contain nested lists).
471 'varargs' and 'varkw' are the names of the * and ** arguments or None.
472 'defaults' is an n-tuple of the default values of the last n arguments."""
473 if not isfunction(func): raise TypeError, 'arg is not a Python function'
474 args, varargs, varkw = getargs(func.func_code)
475 return args, varargs, varkw, func.func_defaults
476
477def getargvalues(frame):
478 """Get information about arguments passed into a particular frame.
479
480 A tuple of four things is returned: (args, varargs, varkw, locals).
481 'args' is a list of the argument names (it may contain nested lists).
482 'varargs' and 'varkw' are the names of the * and ** arguments or None.
483 'locals' is the locals dictionary of the given frame."""
484 args, varargs, varkw = getargs(frame.f_code)
485 return args, varargs, varkw, frame.f_locals
486
487def joinseq(seq):
488 if len(seq) == 1:
489 return '(' + seq[0] + ',)'
490 else:
491 return '(' + string.join(seq, ', ') + ')'
492
493def strseq(object, convert, join=joinseq):
494 """Recursively walk a sequence, stringifying each element."""
495 if type(object) in [types.ListType, types.TupleType]:
496 return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
497 else:
498 return convert(object)
499
500def formatargspec(args, varargs=None, varkw=None, defaults=None,
501 formatarg=str,
502 formatvarargs=lambda name: '*' + name,
503 formatvarkw=lambda name: '**' + name,
504 formatvalue=lambda value: '=' + repr(value),
505 join=joinseq):
506 """Format an argument spec from the 4 values returned by getargspec.
507
508 The first four arguments are (args, varargs, varkw, defaults). The
509 other four arguments are the corresponding optional formatting functions
510 that are called to turn names and values into strings. The ninth
511 argument is an optional function to format the sequence of arguments."""
512 specs = []
513 if defaults:
514 firstdefault = len(args) - len(defaults)
515 for i in range(len(args)):
516 spec = strseq(args[i], formatarg, join)
517 if defaults and i >= firstdefault:
518 spec = spec + formatvalue(defaults[i - firstdefault])
519 specs.append(spec)
520 if varargs:
521 specs.append(formatvarargs(varargs))
522 if varkw:
523 specs.append(formatvarkw(varkw))
524 return '(' + string.join(specs, ', ') + ')'
525
526def formatargvalues(args, varargs, varkw, locals,
527 formatarg=str,
528 formatvarargs=lambda name: '*' + name,
529 formatvarkw=lambda name: '**' + name,
530 formatvalue=lambda value: '=' + repr(value),
531 join=joinseq):
532 """Format an argument spec from the 4 values returned by getargvalues.
533
534 The first four arguments are (args, varargs, varkw, locals). The
535 next four arguments are the corresponding optional formatting functions
536 that are called to turn names and values into strings. The ninth
537 argument is an optional function to format the sequence of arguments."""
538 def convert(name, locals=locals,
539 formatarg=formatarg, formatvalue=formatvalue):
540 return formatarg(name) + formatvalue(locals[name])
541 specs = []
542 for i in range(len(args)):
543 specs.append(strseq(args[i], convert, join))
544 if varargs:
545 specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
546 if varkw:
547 specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
548 return '(' + string.join(specs, ', ') + ')'
549
550# -------------------------------------------------- stack frame extraction
551def getframeinfo(frame, context=1):
552 """Get information about a frame or traceback object.
553
554 A tuple of five things is returned: the filename, the line number of
555 the current line, the function name, a list of lines of context from
556 the source code, and the index of the current line within that list.
557 The optional second argument specifies the number of lines of context
558 to return, which are centered around the current line."""
559 if istraceback(frame):
560 frame = frame.tb_frame
561 if not isframe(frame):
562 raise TypeError, 'arg is not a frame or traceback object'
563
564 filename = getsourcefile(frame)
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000565 lineno = getlineno(frame)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000566 if context > 0:
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000567 start = lineno - 1 - context/2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000568 try:
569 lines, lnum = findsource(frame)
570 start = max(start, 1)
571 start = min(start, len(lines) - context)
572 lines = lines[start:start+context]
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000573 index = lineno - 1 - start
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000574 except:
575 lines = index = None
576 else:
577 lines = index = None
578
Ka-Ping Yee59ade082001-03-01 03:55:35 +0000579 return (filename, lineno, frame.f_code.co_name, lines, index)
580
581def getlineno(frame):
582 """Get the line number from a frame object, allowing for optimization."""
583 # Written by Marc-André Lemburg; revised by Jim Hugunin and Fredrik Lundh.
584 lineno = frame.f_lineno
585 code = frame.f_code
586 if hasattr(code, 'co_lnotab'):
587 table = code.co_lnotab
588 lineno = code.co_firstlineno
589 addr = 0
590 for i in range(0, len(table), 2):
591 addr = addr + ord(table[i])
592 if addr > frame.f_lasti: break
593 lineno = lineno + ord(table[i+1])
594 return lineno
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000595
596def getouterframes(frame, context=1):
597 """Get a list of records for a frame and all higher (calling) frames.
598
599 Each record contains a frame object, filename, line number, function
600 name, a list of lines of context, and index within the context."""
601 framelist = []
602 while frame:
603 framelist.append((frame,) + getframeinfo(frame, context))
604 frame = frame.f_back
605 return framelist
606
607def getinnerframes(tb, context=1):
608 """Get a list of records for a traceback's frame and all lower frames.
609
610 Each record contains a frame object, filename, line number, function
611 name, a list of lines of context, and index within the context."""
612 tb = tb.tb_next
613 framelist = []
614 while tb:
615 framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
616 tb = tb.tb_next
617 return framelist
618
619def currentframe():
620 """Return the frame object for the caller's stack frame."""
621 try:
622 raise 'catch me'
623 except:
624 return sys.exc_traceback.tb_frame.f_back
625
626if hasattr(sys, '_getframe'): currentframe = sys._getframe
627
628def stack(context=1):
629 """Return a list of records for the stack above the caller's frame."""
630 return getouterframes(currentframe().f_back, context)
631
632def trace(context=1):
Tim Peters85ba6732001-02-28 08:26:44 +0000633 """Return a list of records for the stack below the current exception."""
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000634 return getinnerframes(sys.exc_traceback, context)
Ka-Ping Yee8b58b842001-03-01 13:56:16 +0000635
636