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