py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Lib / inspect.py
blob2d88bc1f6429f37a4df094a2caca142ed48f94cf
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
23 """
25 # This module is in the public domain. No warranties.
27 __author__ = 'Ka-Ping Yee <ping@lfw.org>'
28 __date__ = '1 Jan 2001'
30 import sys, os, types, string, re, dis, imp, tokenize
32 # ----------------------------------------------------------- type-checking
33 def ismodule(object):
34 """Return true if the object is a module.
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
41 def isclass(object):
42 """Return true if the object is a class.
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 or hasattr(object, '__bases__')
49 def ismethod(object):
50 """Return true if the object is an instance method.
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
60 def isfunction(object):
61 """Return true if the object is a user-defined function.
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]
73 def istraceback(object):
74 """Return true if the object is a traceback.
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
83 def isframe(object):
84 """Return true if the object is a frame object.
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
101 def iscode(object):
102 """Return true if the object is a code object.
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
119 def isbuiltin(object):
120 """Return true if the object is a built-in function or method.
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) is types.BuiltinFunctionType
128 def isroutine(object):
129 """Return true if the object is any kind of function or method."""
130 return isbuiltin(object) or isfunction(object) or ismethod(object)
132 def getmembers(object, predicate=None):
133 """Return all members of an object as (name, value) pairs sorted by name.
134 Optionally, only return members that satisfy a given predicate."""
135 results = []
136 for key in dir(object):
137 value = getattr(object, key)
138 if not predicate or predicate(value):
139 results.append((key, value))
140 results.sort()
141 return results
143 # -------------------------------------------------- source code extraction
144 def indentsize(line):
145 """Return the indent size, in spaces, at the start of a line of text."""
146 expline = string.expandtabs(line)
147 return len(expline) - len(string.lstrip(expline))
149 def getdoc(object):
150 """Get the documentation string for an object.
152 All tabs are expanded to spaces. To clean up docstrings that are
153 indented to line up with blocks of code, any whitespace than can be
154 uniformly removed from the second line onwards is removed."""
155 if hasattr(object, '__doc__') and object.__doc__:
156 lines = string.split(string.expandtabs(object.__doc__), '\n')
157 margin = None
158 for line in lines[1:]:
159 content = len(string.lstrip(line))
160 if not content: continue
161 indent = len(line) - content
162 if margin is None: margin = indent
163 else: margin = min(margin, indent)
164 if margin is not None:
165 for i in range(1, len(lines)): lines[i] = lines[i][margin:]
166 return string.join(lines, '\n')
168 def getfile(object):
169 """Work out which source or compiled file an object was defined in."""
170 if ismodule(object):
171 if hasattr(object, '__file__'):
172 return object.__file__
173 raise TypeError, 'arg is a built-in module'
174 if isclass(object):
175 object = sys.modules.get(object.__module__)
176 if hasattr(object, '__file__'):
177 return object.__file__
178 raise TypeError, 'arg is a built-in class'
179 if ismethod(object):
180 object = object.im_func
181 if isfunction(object):
182 object = object.func_code
183 if istraceback(object):
184 object = object.tb_frame
185 if isframe(object):
186 object = object.f_code
187 if iscode(object):
188 return object.co_filename
189 raise TypeError, 'arg is not a module, class, method, ' \
190 'function, traceback, frame, or code object'
192 def getmoduleinfo(path):
193 """Get the module name, suffix, mode, and module type for a given file."""
194 filename = os.path.basename(path)
195 suffixes = map(lambda (suffix, mode, mtype):
196 (-len(suffix), suffix, mode, mtype), imp.get_suffixes())
197 suffixes.sort() # try longest suffixes first, in case they overlap
198 for neglen, suffix, mode, mtype in suffixes:
199 if filename[neglen:] == suffix:
200 return filename[:neglen], suffix, mode, mtype
202 def getmodulename(path):
203 """Return the module name for a given file, or None."""
204 info = getmoduleinfo(path)
205 if info: return info[0]
207 def getsourcefile(object):
208 """Return the Python source file an object was defined in, if it exists."""
209 filename = getfile(object)
210 if string.lower(filename[-4:]) in ['.pyc', '.pyo']:
211 filename = filename[:-4] + '.py'
212 for suffix, mode, kind in imp.get_suffixes():
213 if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix:
214 # Looks like a binary file. We want to only return a text file.
215 return None
216 if os.path.exists(filename):
217 return filename
219 def getabsfile(object):
220 """Return an absolute path to the source or compiled file for an object.
222 The idea is for each object to have a unique origin, so this routine
223 normalizes the result as much as possible."""
224 return os.path.normcase(
225 os.path.abspath(getsourcefile(object) or getfile(object)))
227 modulesbyfile = {}
229 def getmodule(object):
230 """Return the module an object was defined in, or None if not found."""
231 if ismodule(object):
232 return object
233 if isclass(object):
234 return sys.modules.get(object.__module__)
235 try:
236 file = getabsfile(object)
237 except TypeError:
238 return None
239 if modulesbyfile.has_key(file):
240 return sys.modules[modulesbyfile[file]]
241 for module in sys.modules.values():
242 if hasattr(module, '__file__'):
243 modulesbyfile[getabsfile(module)] = module.__name__
244 if modulesbyfile.has_key(file):
245 return sys.modules[modulesbyfile[file]]
246 main = sys.modules['__main__']
247 if hasattr(main, object.__name__):
248 mainobject = getattr(main, object.__name__)
249 if mainobject is object:
250 return main
251 builtin = sys.modules['__builtin__']
252 if hasattr(builtin, object.__name__):
253 builtinobject = getattr(builtin, object.__name__)
254 if builtinobject is object:
255 return builtin
257 def findsource(object):
258 """Return the entire source file and starting line number for an object.
260 The argument may be a module, class, method, function, traceback, frame,
261 or code object. The source code is returned as a list of all the lines
262 in the file and the line number indexes a line in that list. An IOError
263 is raised if the source code cannot be retrieved."""
264 try:
265 file = open(getsourcefile(object))
266 except (TypeError, IOError):
267 raise IOError, 'could not get source code'
268 lines = file.readlines()
269 file.close()
271 if ismodule(object):
272 return lines, 0
274 if isclass(object):
275 name = object.__name__
276 pat = re.compile(r'^\s*class\s*' + name + r'\b')
277 for i in range(len(lines)):
278 if pat.match(lines[i]): return lines, i
279 else: raise IOError, 'could not find class definition'
281 if ismethod(object):
282 object = object.im_func
283 if isfunction(object):
284 object = object.func_code
285 if istraceback(object):
286 object = object.tb_frame
287 if isframe(object):
288 object = object.f_code
289 if iscode(object):
290 if not hasattr(object, 'co_firstlineno'):
291 raise IOError, 'could not find function definition'
292 lnum = object.co_firstlineno - 1
293 pat = re.compile(r'^\s*def\s')
294 while lnum > 0:
295 if pat.match(lines[lnum]): break
296 lnum = lnum - 1
297 return lines, lnum
299 def getcomments(object):
300 """Get lines of comments immediately preceding an object's source code."""
301 try: lines, lnum = findsource(object)
302 except IOError: return None
304 if ismodule(object):
305 # Look for a comment block at the top of the file.
306 start = 0
307 if lines and lines[0][:2] == '#!': start = 1
308 while start < len(lines) and string.strip(lines[start]) in ['', '#']:
309 start = start + 1
310 if start < len(lines) and lines[start][:1] == '#':
311 comments = []
312 end = start
313 while end < len(lines) and lines[end][:1] == '#':
314 comments.append(string.expandtabs(lines[end]))
315 end = end + 1
316 return string.join(comments, '')
318 # Look for a preceding block of comments at the same indentation.
319 elif lnum > 0:
320 indent = indentsize(lines[lnum])
321 end = lnum - 1
322 if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
323 indentsize(lines[end]) == indent:
324 comments = [string.lstrip(string.expandtabs(lines[end]))]
325 if end > 0:
326 end = end - 1
327 comment = string.lstrip(string.expandtabs(lines[end]))
328 while comment[:1] == '#' and indentsize(lines[end]) == indent:
329 comments[:0] = [comment]
330 end = end - 1
331 if end < 0: break
332 comment = string.lstrip(string.expandtabs(lines[end]))
333 while comments and string.strip(comments[0]) == '#':
334 comments[:1] = []
335 while comments and string.strip(comments[-1]) == '#':
336 comments[-1:] = []
337 return string.join(comments, '')
339 class ListReader:
340 """Provide a readline() method to return lines from a list of strings."""
341 def __init__(self, lines):
342 self.lines = lines
343 self.index = 0
345 def readline(self):
346 i = self.index
347 if i < len(self.lines):
348 self.index = i + 1
349 return self.lines[i]
350 else: return ''
352 class EndOfBlock(Exception): pass
354 class BlockFinder:
355 """Provide a tokeneater() method to detect the end of a code block."""
356 def __init__(self):
357 self.indent = 0
358 self.started = 0
359 self.last = 0
361 def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
362 if not self.started:
363 if type == tokenize.NAME: self.started = 1
364 elif type == tokenize.NEWLINE:
365 self.last = srow
366 elif type == tokenize.INDENT:
367 self.indent = self.indent + 1
368 elif type == tokenize.DEDENT:
369 self.indent = self.indent - 1
370 if self.indent == 0: raise EndOfBlock, self.last
372 def getblock(lines):
373 """Extract the block of code at the top of the given list of lines."""
374 try:
375 tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater)
376 except EndOfBlock, eob:
377 return lines[:eob.args[0]]
379 def getsourcelines(object):
380 """Return a list of source lines and starting line number for an object.
382 The argument may be a module, class, method, function, traceback, frame,
383 or code object. The source code is returned as a list of the lines
384 corresponding to the object and the line number indicates where in the
385 original source file the first line of code was found. An IOError is
386 raised if the source code cannot be retrieved."""
387 lines, lnum = findsource(object)
389 if ismodule(object): return lines, 0
390 else: return getblock(lines[lnum:]), lnum + 1
392 def getsource(object):
393 """Return the text of the source code for an object.
395 The argument may be a module, class, method, function, traceback, frame,
396 or code object. The source code is returned as a single string. An
397 IOError is raised if the source code cannot be retrieved."""
398 lines, lnum = getsourcelines(object)
399 return string.join(lines, '')
401 # --------------------------------------------------- class tree extraction
402 def walktree(classes, children, parent):
403 """Recursive helper function for getclasstree()."""
404 results = []
405 classes.sort(lambda a, b: cmp(a.__name__, b.__name__))
406 for c in classes:
407 results.append((c, c.__bases__))
408 if children.has_key(c):
409 results.append(walktree(children[c], children, c))
410 return results
412 def getclasstree(classes, unique=0):
413 """Arrange the given list of classes into a hierarchy of nested lists.
415 Where a nested list appears, it contains classes derived from the class
416 whose entry immediately precedes the list. Each entry is a 2-tuple
417 containing a class and a tuple of its base classes. If the 'unique'
418 argument is true, exactly one entry appears in the returned structure
419 for each class in the given list. Otherwise, classes using multiple
420 inheritance and their descendants will appear multiple times."""
421 children = {}
422 roots = []
423 for c in classes:
424 if c.__bases__:
425 for parent in c.__bases__:
426 if not children.has_key(parent):
427 children[parent] = []
428 children[parent].append(c)
429 if unique and parent in classes: break
430 elif c not in roots:
431 roots.append(c)
432 for parent in children.keys():
433 if parent not in classes:
434 roots.append(parent)
435 return walktree(roots, children, None)
437 # ------------------------------------------------ argument list extraction
438 # These constants are from Python's compile.h.
439 CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
441 def getargs(co):
442 """Get information about the arguments accepted by a code object.
444 Three things are returned: (args, varargs, varkw), where 'args' is
445 a list of argument names (possibly containing nested lists), and
446 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
447 if not iscode(co): raise TypeError, 'arg is not a code object'
449 code = co.co_code
450 nargs = co.co_argcount
451 names = co.co_varnames
452 args = list(names[:nargs])
453 step = 0
455 # The following acrobatics are for anonymous (tuple) arguments.
456 for i in range(nargs):
457 if args[i][:1] in ['', '.']:
458 stack, remain, count = [], [], []
459 while step < len(code):
460 op = ord(code[step])
461 step = step + 1
462 if op >= dis.HAVE_ARGUMENT:
463 opname = dis.opname[op]
464 value = ord(code[step]) + ord(code[step+1])*256
465 step = step + 2
466 if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']:
467 remain.append(value)
468 count.append(value)
469 elif opname == 'STORE_FAST':
470 stack.append(names[value])
471 remain[-1] = remain[-1] - 1
472 while remain[-1] == 0:
473 remain.pop()
474 size = count.pop()
475 stack[-size:] = [stack[-size:]]
476 if not remain: break
477 remain[-1] = remain[-1] - 1
478 if not remain: break
479 args[i] = stack[0]
481 varargs = None
482 if co.co_flags & CO_VARARGS:
483 varargs = co.co_varnames[nargs]
484 nargs = nargs + 1
485 varkw = None
486 if co.co_flags & CO_VARKEYWORDS:
487 varkw = co.co_varnames[nargs]
488 return args, varargs, varkw
490 def getargspec(func):
491 """Get the names and default values of a function's arguments.
493 A tuple of four things is returned: (args, varargs, varkw, defaults).
494 'args' is a list of the argument names (it may contain nested lists).
495 'varargs' and 'varkw' are the names of the * and ** arguments or None.
496 'defaults' is an n-tuple of the default values of the last n arguments."""
497 if not isfunction(func): raise TypeError, 'arg is not a Python function'
498 args, varargs, varkw = getargs(func.func_code)
499 return args, varargs, varkw, func.func_defaults
501 def getargvalues(frame):
502 """Get information about arguments passed into a particular frame.
504 A tuple of four things is returned: (args, varargs, varkw, locals).
505 'args' is a list of the argument names (it may contain nested lists).
506 'varargs' and 'varkw' are the names of the * and ** arguments or None.
507 'locals' is the locals dictionary of the given frame."""
508 args, varargs, varkw = getargs(frame.f_code)
509 return args, varargs, varkw, frame.f_locals
511 def joinseq(seq):
512 if len(seq) == 1:
513 return '(' + seq[0] + ',)'
514 else:
515 return '(' + string.join(seq, ', ') + ')'
517 def strseq(object, convert, join=joinseq):
518 """Recursively walk a sequence, stringifying each element."""
519 if type(object) in [types.ListType, types.TupleType]:
520 return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
521 else:
522 return convert(object)
524 def formatargspec(args, varargs=None, varkw=None, defaults=None,
525 formatarg=str,
526 formatvarargs=lambda name: '*' + name,
527 formatvarkw=lambda name: '**' + name,
528 formatvalue=lambda value: '=' + repr(value),
529 join=joinseq):
530 """Format an argument spec from the 4 values returned by getargspec.
532 The first four arguments are (args, varargs, varkw, defaults). The
533 other 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 specs = []
537 if defaults:
538 firstdefault = len(args) - len(defaults)
539 for i in range(len(args)):
540 spec = strseq(args[i], formatarg, join)
541 if defaults and i >= firstdefault:
542 spec = spec + formatvalue(defaults[i - firstdefault])
543 specs.append(spec)
544 if varargs:
545 specs.append(formatvarargs(varargs))
546 if varkw:
547 specs.append(formatvarkw(varkw))
548 return '(' + string.join(specs, ', ') + ')'
550 def formatargvalues(args, varargs, varkw, locals,
551 formatarg=str,
552 formatvarargs=lambda name: '*' + name,
553 formatvarkw=lambda name: '**' + name,
554 formatvalue=lambda value: '=' + repr(value),
555 join=joinseq):
556 """Format an argument spec from the 4 values returned by getargvalues.
558 The first four arguments are (args, varargs, varkw, locals). The
559 next four arguments are the corresponding optional formatting functions
560 that are called to turn names and values into strings. The ninth
561 argument is an optional function to format the sequence of arguments."""
562 def convert(name, locals=locals,
563 formatarg=formatarg, formatvalue=formatvalue):
564 return formatarg(name) + formatvalue(locals[name])
565 specs = []
566 for i in range(len(args)):
567 specs.append(strseq(args[i], convert, join))
568 if varargs:
569 specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
570 if varkw:
571 specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
572 return '(' + string.join(specs, ', ') + ')'
574 # -------------------------------------------------- stack frame extraction
575 def getframeinfo(frame, context=1):
576 """Get information about a frame or traceback object.
578 A tuple of five things is returned: the filename, the line number of
579 the current line, the function name, a list of lines of context from
580 the source code, and the index of the current line within that list.
581 The optional second argument specifies the number of lines of context
582 to return, which are centered around the current line."""
583 if istraceback(frame):
584 frame = frame.tb_frame
585 if not isframe(frame):
586 raise TypeError, 'arg is not a frame or traceback object'
588 filename = getsourcefile(frame)
589 lineno = getlineno(frame)
590 if context > 0:
591 start = lineno - 1 - context/2
592 try:
593 lines, lnum = findsource(frame)
594 except IOError:
595 lines = index = None
596 else:
597 start = max(start, 1)
598 start = min(start, len(lines) - context)
599 lines = lines[start:start+context]
600 index = lineno - 1 - start
601 else:
602 lines = index = None
604 return (filename, lineno, frame.f_code.co_name, lines, index)
606 def getlineno(frame):
607 """Get the line number from a frame object, allowing for optimization."""
608 # Written by Marc-André Lemburg; revised by Jim Hugunin and Fredrik Lundh.
609 lineno = frame.f_lineno
610 code = frame.f_code
611 if hasattr(code, 'co_lnotab'):
612 table = code.co_lnotab
613 lineno = code.co_firstlineno
614 addr = 0
615 for i in range(0, len(table), 2):
616 addr = addr + ord(table[i])
617 if addr > frame.f_lasti: break
618 lineno = lineno + ord(table[i+1])
619 return lineno
621 def getouterframes(frame, context=1):
622 """Get a list of records for a frame and all higher (calling) frames.
624 Each record contains a frame object, filename, line number, function
625 name, a list of lines of context, and index within the context."""
626 framelist = []
627 while frame:
628 framelist.append((frame,) + getframeinfo(frame, context))
629 frame = frame.f_back
630 return framelist
632 def getinnerframes(tb, context=1):
633 """Get a list of records for a traceback's frame and all lower frames.
635 Each record contains a frame object, filename, line number, function
636 name, a list of lines of context, and index within the context."""
637 framelist = []
638 while tb:
639 framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
640 tb = tb.tb_next
641 return framelist
643 def currentframe():
644 """Return the frame object for the caller's stack frame."""
645 try:
646 raise 'catch me'
647 except:
648 return sys.exc_traceback.tb_frame.f_back
650 if hasattr(sys, '_getframe'): currentframe = sys._getframe
652 def stack(context=1):
653 """Return a list of records for the stack above the caller's frame."""
654 return getouterframes(currentframe().f_back, context)
656 def trace(context=1):
657 """Return a list of records for the stack below the current exception."""
658 return getinnerframes(sys.exc_traceback, context)