1
"""Get useful information from live Python objects.
3
This module encapsulates the interface provided by the internal special
4
attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
5
It also provides some help for examining source code and class layout.
7
Here are some of the useful functions provided by this module:
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
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
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
25
# This module is in the public domain. No warranties.
27
__version__ = 'Ka-Ping Yee <ping@lfw.org>, 1 Jan 2001'
29
import sys, types, string, dis, imp, tokenize
31
# ----------------------------------------------------------- type-checking
33
"""Return true if the object is a module.
35
Module objects provide these attributes:
36
__doc__ documentation string
37
__file__ filename (missing for built-in modules)"""
38
return type(object) is types.ModuleType
41
"""Return true if the object is a class.
43
Class objects provide these attributes:
44
__doc__ documentation string
45
__module__ name of module in which this class was defined"""
46
return type(object) is types.ClassType
49
"""Return true if the object is an instance method.
51
Instance method objects provide these attributes:
52
__doc__ documentation string
53
__name__ name with which this method was defined
54
im_class class object in which this method belongs
55
im_func function object containing implementation of method
56
im_self instance to which this method is bound, or None"""
57
return type(object) is types.MethodType
59
def isfunction(object):
60
"""Return true if the object is a user-defined function.
62
Function objects provide these attributes:
63
__doc__ documentation string
64
__name__ name with which this function was defined
65
func_code code object containing compiled function bytecode
66
func_defaults tuple of any default values for arguments
67
func_doc (same as __doc__)
68
func_globals global namespace in which this function was defined
69
func_name (same as __name__)"""
70
return type(object) in [types.FunctionType, types.LambdaType]
72
def istraceback(object):
73
"""Return true if the object is a traceback.
75
Traceback objects provide these attributes:
76
tb_frame frame object at this level
77
tb_lasti index of last attempted instruction in bytecode
78
tb_lineno current line number in Python source code
79
tb_next next inner traceback object (called by this level)"""
80
return type(object) is types.TracebackType
83
"""Return true if the object is a frame object.
85
Frame objects provide these attributes:
86
f_back next outer frame object (this frame's caller)
87
f_builtins built-in namespace seen by this frame
88
f_code code object being executed in this frame
89
f_exc_traceback traceback if raised in this frame, or None
90
f_exc_type exception type if raised in this frame, or None
91
f_exc_value exception value if raised in this frame, or None
92
f_globals global namespace seen by this frame
93
f_lasti index of last attempted instruction in bytecode
94
f_lineno current line number in Python source code
95
f_locals local namespace seen by this frame
96
f_restricted 0 or 1 if frame is in restricted execution mode
97
f_trace tracing function for this frame, or None"""
98
return type(object) is types.FrameType
101
"""Return true if the object is a code object.
103
Code objects provide these attributes:
104
co_argcount number of arguments (not including * or ** args)
105
co_code string of raw compiled bytecode
106
co_consts tuple of constants used in the bytecode
107
co_filename name of file in which this code object was created
108
co_firstlineno number of first line in Python source code
109
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
110
co_lnotab encoded mapping of line numbers to bytecode indices
111
co_name name with which this code object was defined
112
co_names tuple of names of local variables
113
co_nlocals number of local variables
114
co_stacksize virtual machine stack space required
115
co_varnames tuple of names of arguments and local variables"""
116
return type(object) is types.CodeType
118
def isbuiltin(object):
119
"""Return true if the object is a built-in function or method.
121
Built-in functions and methods provide these attributes:
122
__doc__ documentation string
123
__name__ original name of this function or method
124
__self__ instance to which a method is bound, or None"""
125
return type(object) in [types.BuiltinFunctionType,
126
types.BuiltinMethodType]
128
def isroutine(object):
129
"""Return true if the object is any kind of function or method."""
130
return type(object) in [types.FunctionType, types.LambdaType,
131
types.MethodType, types.BuiltinFunctionType,
132
types.BuiltinMethodType]
134
def getmembers(object, predicate=None):
135
"""Return all members of an object as (name, value) pairs sorted by name.
136
Optionally, only return members that satisfy a given predicate."""
138
for key in dir(object):
139
value = getattr(object, key)
140
if not predicate or predicate(value):
141
results.append((key, value))
145
# -------------------------------------------------- source code extraction
146
def indentsize(line):
147
"""Return the indent size, in spaces, at the start of a line of text."""
148
expline = string.expandtabs(line)
149
return len(expline) - len(string.lstrip(expline))
152
"""Get the documentation string for an object.
154
All tabs are expanded to spaces. To clean up docstrings that are
155
indented to line up with blocks of code, any whitespace than can be
156
uniformly removed from the second line onwards is removed."""
157
if hasattr(object, '__doc__') and object.__doc__:
158
lines = string.split(string.expandtabs(object.__doc__), '\n')
160
for line in lines[1:]:
161
content = len(string.lstrip(line))
162
if not content: continue
163
indent = len(line) - content
164
if margin is None: margin = indent
165
else: margin = min(margin, indent)
166
if margin is not None:
167
for i in range(1, len(lines)): lines[i] = lines[i][margin:]
168
return string.join(lines, '\n')
171
"""Try to guess which (text or binary) file an object was defined in."""
173
if hasattr(object, '__file__'):
174
return object.__file__
175
raise TypeError, 'arg is a built-in module'
177
object = sys.modules[object.__module__]
178
if hasattr(object, '__file__'):
179
return object.__file__
180
raise TypeError, 'arg is a built-in class'
182
object = object.im_func
183
if isfunction(object):
184
object = object.func_code
185
if istraceback(object):
186
object = object.tb_frame
188
object = object.f_code
190
return object.co_filename
191
raise TypeError, 'arg is not a module, class, method, ' \
192
'function, traceback, frame, or code object'
196
def getmodule(object):
197
"""Try to guess which module an object was defined in."""
199
return sys.modules[object.__module__]
201
file = getsourcefile(object)
204
if modulesbyfile.has_key(file):
205
return sys.modules[modulesbyfile[file]]
206
for module in sys.modules.values():
207
if hasattr(module, '__file__'):
208
modulesbyfile[getsourcefile(module)] = module.__name__
209
if modulesbyfile.has_key(file):
210
return sys.modules[modulesbyfile[file]]
211
main = sys.modules['__main__']
213
mainobject = getattr(main, object.__name__)
214
if mainobject is object: return main
215
except AttributeError: pass
216
builtin = sys.modules['__builtin__']
218
builtinobject = getattr(builtin, object.__name__)
219
if builtinobject is object: return builtin
220
except AttributeError: pass
222
def getsourcefile(object):
223
"""Try to guess which Python source file an object was defined in."""
224
filename = getfile(object)
225
if filename[-4:] == '.pyc':
226
filename = filename[:-4] + '.py'
229
def findsource(object):
230
"""Return the entire source file and starting line number for an object.
232
The argument may be a module, class, method, function, traceback, frame,
233
or code object. The source code is returned as a list of all the lines
234
in the file and the line number indexes a line in that list. An IOError
235
is raised if the source code cannot be retrieved."""
237
file = open(getsourcefile(object))
238
lines = file.readlines()
240
except (TypeError, IOError):
241
raise IOError, 'could not get source code'
247
name = object.__name__
248
matches = (['class', name], ['class', name + ':'])
249
for i in range(len(lines)):
250
if string.split(lines[i])[:2] in matches:
252
else: raise IOError, 'could not find class definition'
255
object = object.im_func
256
if isfunction(object):
257
object = object.func_code
258
if istraceback(object):
259
object = object.tb_frame
261
object = object.f_code
264
lnum = object.co_firstlineno - 1
265
except AttributeError:
266
raise IOError, 'could not find function definition'
269
if string.split(lines[lnum])[:1] == ['def']: break
273
def getcomments(object):
274
"""Get lines of comments immediately preceding an object's source code."""
275
try: lines, lnum = findsource(object)
279
# Look for a comment block at the top of the file.
281
if lines[0][:2] == '#!': start = 1
282
while start < len(lines) and string.strip(lines[start]) in ['', '#']:
284
if lines[start][:1] == '#':
287
while end < len(lines) and lines[end][:1] == '#':
288
comments.append(string.expandtabs(lines[end]))
290
return string.join(comments, '')
292
# Look for a preceding block of comments at the same indentation.
294
indent = indentsize(lines[lnum])
296
if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
297
indentsize(lines[end]) == indent:
298
comments = [string.lstrip(string.expandtabs(lines[end]))]
301
comment = string.lstrip(string.expandtabs(lines[end]))
302
while comment[:1] == '#' and indentsize(lines[end]) == indent:
303
comments[:0] = [comment]
306
comment = string.lstrip(string.expandtabs(lines[end]))
307
while comments and string.strip(comments[0]) == '#':
309
while comments and string.strip(comments[-1]) == '#':
311
return string.join(comments, '')
314
"""Provide a readline() method to return lines from a list of strings."""
315
def __init__(self, lines):
321
if i < len(self.lines):
326
class EndOfBlock(Exception): pass
329
"""Provide a tokeneater() method to detect the end of a code block."""
335
def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
337
if type == tokenize.NAME: self.started = 1
338
elif type == tokenize.NEWLINE:
340
elif type == tokenize.INDENT:
341
self.indent = self.indent + 1
342
elif type == tokenize.DEDENT:
343
self.indent = self.indent - 1
344
if self.indent == 0: raise EndOfBlock, self.last
347
"""Extract the block of code at the top of the given list of lines."""
349
tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater)
350
except EndOfBlock, eob:
351
return lines[:eob.args[0]]
353
def getsourcelines(object):
354
"""Return a list of source lines and starting line number for an object.
356
The argument may be a module, class, method, function, traceback, frame,
357
or code object. The source code is returned as a list of the lines
358
corresponding to the object and the line number indicates where in the
359
original source file the first line of code was found. An IOError is
360
raised if the source code cannot be retrieved."""
361
lines, lnum = findsource(object)
363
if ismodule(object): return lines, 0
364
else: return getblock(lines[lnum:]), lnum + 1
366
def getsource(object):
367
"""Return the text of the source code for an object.
369
The argument may be a module, class, method, function, traceback, frame,
370
or code object. The source code is returned as a single string. An
371
IOError is raised if the source code cannot be retrieved."""
372
lines, lnum = getsourcelines(object)
373
return string.join(lines, '')
375
# --------------------------------------------------- class tree extraction
376
def walktree(classes, children, parent):
377
"""Recursive helper function for getclasstree()."""
379
classes.sort(lambda a, b: cmp(a.__name__, b.__name__))
381
results.append((c, c.__bases__))
382
if children.has_key(c):
383
results.append(walktree(children[c], children, c))
386
def getclasstree(classes, unique=0):
387
"""Arrange the given list of classes into a hierarchy of nested lists.
389
Where a nested list appears, it contains classes derived from the class
390
whose entry immediately precedes the list. Each entry is a 2-tuple
391
containing a class and a tuple of its base classes. If the 'unique'
392
argument is true, exactly one entry appears in the returned structure
393
for each class in the given list. Otherwise, classes using multiple
394
inheritance and their descendants will appear multiple times."""
399
for parent in c.__bases__:
400
if not children.has_key(parent):
401
children[parent] = []
402
children[parent].append(c)
403
if unique and parent in classes: break
406
for parent in children.keys():
407
if parent not in classes:
409
return walktree(roots, children, None)
411
# ------------------------------------------------ argument list extraction
412
# These constants are from Python's compile.h.
413
CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
416
"""Get information about the arguments accepted by a code object.
418
Three things are returned: (args, varargs, varkw), where 'args' is
419
a list of argument names (possibly containing nested lists), and
420
'varargs' and 'varkw' are the names of the * and ** arguments or None."""
421
if not iscode(co): raise TypeError, 'arg is not a code object'
424
nargs = co.co_argcount
425
names = co.co_varnames
426
args = list(names[:nargs])
429
# The following acrobatics are for anonymous (tuple) arguments.
430
for i in range(nargs):
431
if args[i][:1] in ['', '.']:
432
stack, remain, count = [], [], []
433
while step < len(code):
436
if op >= dis.HAVE_ARGUMENT:
437
opname = dis.opname[op]
438
value = ord(code[step]) + ord(code[step+1])*256
440
if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']:
443
elif opname == 'STORE_FAST':
444
stack.append(names[value])
445
remain[-1] = remain[-1] - 1
446
while remain[-1] == 0:
449
stack[-size:] = [stack[-size:]]
451
remain[-1] = remain[-1] - 1
456
if co.co_flags & CO_VARARGS:
457
varargs = co.co_varnames[nargs]
460
if co.co_flags & CO_VARKEYWORDS:
461
varkw = co.co_varnames[nargs]
462
return args, varargs, varkw
464
def getargspec(func):
465
"""Get the names and default values of a function's arguments.
467
A tuple of four things is returned: (args, varargs, varkw, defaults).
468
'args' is a list of the argument names (it may contain nested lists).
469
'varargs' and 'varkw' are the names of the * and ** arguments or None.
470
'defaults' is an n-tuple of the default values of the last n arguments."""
471
if not isfunction(func): raise TypeError, 'arg is not a Python function'
472
args, varargs, varkw = getargs(func.func_code)
473
return args, varargs, varkw, func.func_defaults
475
def getargvalues(frame):
476
"""Get information about arguments passed into a particular frame.
478
A tuple of four things is returned: (args, varargs, varkw, locals).
479
'args' is a list of the argument names (it may contain nested lists).
480
'varargs' and 'varkw' are the names of the * and ** arguments or None.
481
'locals' is the locals dictionary of the given frame."""
482
args, varargs, varkw = getargs(frame.f_code)
483
return args, varargs, varkw, frame.f_locals
487
return '(' + seq[0] + ',)'
489
return '(' + string.join(seq, ', ') + ')'
491
def strseq(object, convert, join=joinseq):
492
"""Recursively walk a sequence, stringifying each element."""
493
if type(object) in [types.ListType, types.TupleType]:
494
return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
496
return convert(object)
498
def formatargspec(args, varargs=None, varkw=None, defaults=None,
500
formatvarargs=lambda name: '*' + name,
501
formatvarkw=lambda name: '**' + name,
502
formatvalue=lambda value: '=' + repr(value),
504
"""Format an argument spec from the 4 values returned by getargspec.
506
The first four arguments are (args, varargs, varkw, defaults). The
507
other four arguments are the corresponding optional formatting functions
508
that are called to turn names and values into strings. The ninth
509
argument is an optional function to format the sequence of arguments."""
512
firstdefault = len(args) - len(defaults)
513
for i in range(len(args)):
514
spec = strseq(args[i], formatarg, join)
515
if defaults and i >= firstdefault:
516
spec = spec + formatvalue(defaults[i - firstdefault])
519
specs.append(formatvarargs(varargs))
521
specs.append(formatvarkw(varkw))
522
return '(' + string.join(specs, ', ') + ')'
524
def formatargvalues(args, varargs, varkw, locals,
526
formatvarargs=lambda name: '*' + name,
527
formatvarkw=lambda name: '**' + name,
528
formatvalue=lambda value: '=' + repr(value),
530
"""Format an argument spec from the 4 values returned by getargvalues.
532
The first four arguments are (args, varargs, varkw, locals). The
533
next four arguments are the corresponding optional formatting functions
534
that are called to turn names and values into strings. The ninth
535
argument is an optional function to format the sequence of arguments."""
536
def convert(name, locals=locals,
537
formatarg=formatarg, formatvalue=formatvalue):
538
return formatarg(name) + formatvalue(locals[name])
540
for i in range(len(args)):
541
specs.append(strseq(args[i], convert, join))
543
specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
545
specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
546
return '(' + string.join(specs, ', ') + ')'
548
# -------------------------------------------------- stack frame extraction
549
def getframeinfo(frame, context=1):
550
"""Get information about a frame or traceback object.
552
A tuple of five things is returned: the filename, the line number of
553
the current line, the function name, a list of lines of context from
554
the source code, and the index of the current line within that list.
555
The optional second argument specifies the number of lines of context
556
to return, which are centered around the current line."""
557
if istraceback(frame):
558
frame = frame.tb_frame
559
if not isframe(frame):
560
raise TypeError, 'arg is not a frame or traceback object'
562
filename = getsourcefile(frame)
564
start = frame.f_lineno - 1 - context/2
566
lines, lnum = findsource(frame)
567
start = max(start, 1)
568
start = min(start, len(lines) - context)
569
lines = lines[start:start+context]
570
index = frame.f_lineno - 1 - start
576
return (filename, frame.f_lineno, frame.f_code.co_name, lines, index)
578
def getouterframes(frame, context=1):
579
"""Get a list of records for a frame and all higher (calling) frames.
581
Each record contains a frame object, filename, line number, function
582
name, a list of lines of context, and index within the context."""
585
framelist.append((frame,) + getframeinfo(frame, context))
589
def getinnerframes(tb, context=1):
590
"""Get a list of records for a traceback's frame and all lower frames.
592
Each record contains a frame object, filename, line number, function
593
name, a list of lines of context, and index within the context."""
597
framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
602
"""Return the frame object for the caller's stack frame."""
606
return sys.exc_traceback.tb_frame.f_back
608
if hasattr(sys, '_getframe'): currentframe = sys._getframe
610
def stack(context=1):
611
"""Return a list of records for the stack above the caller's frame."""
612
return getouterframes(currentframe().f_back, context)
614
def trace(context=1):
615
"""Return a list of records for the stack below the current exception."""
616
return getinnerframes(sys.exc_traceback, context)