1 # -*- coding: iso-8859-1 -*-
2 """Get useful information from live Python objects.
4 This module encapsulates the interface provided by the internal special
5 attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
6 It also provides some help for examining source code and class layout.
8 Here are some of the useful functions provided by this module:
10 ismodule(), isclass(), ismethod(), isfunction(), istraceback(),
11 isframe(), iscode(), isbuiltin(), isroutine() - check object types
12 getmembers() - get members of an object that satisfy a given condition
14 getfile(), getsourcefile(), getsource() - find an object's source code
15 getdoc(), getcomments() - get documentation on an object
16 getmodule() - determine the module that an object came from
17 getclasstree() - arrange classes so as to represent their hierarchy
19 getargspec(), getargvalues() - get info about function arguments
20 formatargspec(), formatargvalues() - format an argument spec
21 getouterframes(), getinnerframes() - get info about frames
22 currentframe() - get the current stack frame
23 stack(), trace() - get info about frames on the stack or in a traceback
26 # This module is in the public domain. No warranties.
28 __author__
= 'Ka-Ping Yee <ping@lfw.org>'
29 __date__
= '1 Jan 2001'
31 import sys
, os
, types
, string
, re
, dis
, imp
, tokenize
, linecache
33 # ----------------------------------------------------------- type-checking
35 """Return true if the object is a module.
37 Module objects provide these attributes:
38 __doc__ documentation string
39 __file__ filename (missing for built-in modules)"""
40 return isinstance(object, types
.ModuleType
)
43 """Return true if the object is a class.
45 Class objects provide these attributes:
46 __doc__ documentation string
47 __module__ name of module in which this class was defined"""
48 return isinstance(object, types
.ClassType
) or hasattr(object, '__bases__')
51 """Return true if the object is an instance method.
53 Instance method objects provide these attributes:
54 __doc__ documentation string
55 __name__ name with which this method was defined
56 im_class class object in which this method belongs
57 im_func function object containing implementation of method
58 im_self instance to which this method is bound, or None"""
59 return isinstance(object, types
.MethodType
)
61 def ismethoddescriptor(object):
62 """Return true if the object is a method descriptor.
64 But not if ismethod() or isclass() or isfunction() are true.
66 This is new in Python 2.2, and, for example, is true of int.__add__.
67 An object passing this test has a __get__ attribute but not a __set__
68 attribute, but beyond that the set of attributes varies. __name__ is
69 usually sensible, and __doc__ often is.
71 Methods implemented via descriptors that also pass one of the other
72 tests return false from the ismethoddescriptor() test, simply because
73 the other tests promise more -- you can, e.g., count on having the
74 im_func attribute (etc) when an object passes ismethod()."""
75 return (hasattr(object, "__get__")
76 and not hasattr(object, "__set__") # else it's a data descriptor
77 and not ismethod(object) # mutual exclusion
78 and not isfunction(object)
79 and not isclass(object))
81 def isdatadescriptor(object):
82 """Return true if the object is a data descriptor.
84 Data descriptors have both a __get__ and a __set__ attribute. Examples are
85 properties (defined in Python) and getsets and members (defined in C).
86 Typically, data descriptors will also have __name__ and __doc__ attributes
87 (properties, getsets, and members have both of these attributes), but this
89 return (hasattr(object, "__set__") and hasattr(object, "__get__"))
91 def isfunction(object):
92 """Return true if the object is a user-defined function.
94 Function objects provide these attributes:
95 __doc__ documentation string
96 __name__ name with which this function was defined
97 func_code code object containing compiled function bytecode
98 func_defaults tuple of any default values for arguments
99 func_doc (same as __doc__)
100 func_globals global namespace in which this function was defined
101 func_name (same as __name__)"""
102 return isinstance(object, types
.FunctionType
)
104 def istraceback(object):
105 """Return true if the object is a traceback.
107 Traceback objects provide these attributes:
108 tb_frame frame object at this level
109 tb_lasti index of last attempted instruction in bytecode
110 tb_lineno current line number in Python source code
111 tb_next next inner traceback object (called by this level)"""
112 return isinstance(object, types
.TracebackType
)
115 """Return true if the object is a frame object.
117 Frame objects provide these attributes:
118 f_back next outer frame object (this frame's caller)
119 f_builtins built-in namespace seen by this frame
120 f_code code object being executed in this frame
121 f_exc_traceback traceback if raised in this frame, or None
122 f_exc_type exception type if raised in this frame, or None
123 f_exc_value exception value if raised in this frame, or None
124 f_globals global namespace seen by this frame
125 f_lasti index of last attempted instruction in bytecode
126 f_lineno current line number in Python source code
127 f_locals local namespace seen by this frame
128 f_restricted 0 or 1 if frame is in restricted execution mode
129 f_trace tracing function for this frame, or None"""
130 return isinstance(object, types
.FrameType
)
133 """Return true if the object is a code object.
135 Code objects provide these attributes:
136 co_argcount number of arguments (not including * or ** args)
137 co_code string of raw compiled bytecode
138 co_consts tuple of constants used in the bytecode
139 co_filename name of file in which this code object was created
140 co_firstlineno number of first line in Python source code
141 co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
142 co_lnotab encoded mapping of line numbers to bytecode indices
143 co_name name with which this code object was defined
144 co_names tuple of names of local variables
145 co_nlocals number of local variables
146 co_stacksize virtual machine stack space required
147 co_varnames tuple of names of arguments and local variables"""
148 return isinstance(object, types
.CodeType
)
150 def isbuiltin(object):
151 """Return true if the object is a built-in function or method.
153 Built-in functions and methods provide these attributes:
154 __doc__ documentation string
155 __name__ original name of this function or method
156 __self__ instance to which a method is bound, or None"""
157 return isinstance(object, types
.BuiltinFunctionType
)
159 def isroutine(object):
160 """Return true if the object is any kind of function or method."""
161 return (isbuiltin(object)
162 or isfunction(object)
164 or ismethoddescriptor(object))
166 def getmembers(object, predicate
=None):
167 """Return all members of an object as (name, value) pairs sorted by name.
168 Optionally, only return members that satisfy a given predicate."""
170 for key
in dir(object):
171 value
= getattr(object, key
)
172 if not predicate
or predicate(value
):
173 results
.append((key
, value
))
177 def classify_class_attrs(cls
):
178 """Return list of attribute-descriptor tuples.
180 For each name in dir(cls), the return list contains a 4-tuple
183 0. The name (a string).
185 1. The kind of attribute this is, one of these strings:
186 'class method' created via classmethod()
187 'static method' created via staticmethod()
188 'property' created via property()
189 'method' any other flavor of method
192 2. The class which defined this attribute (a class).
194 3. The object as obtained directly from the defining class's
195 __dict__, not via getattr. This is especially important for
196 data attributes: C.data is just a data object, but
197 C.__dict__['data'] may be a data descriptor with additional
198 info, like a __doc__ string.
205 # Get the object associated with the name.
206 # Getting an obj from the __dict__ sometimes reveals more than
207 # using getattr. Static and class methods are dramatic examples.
208 if name
in cls
.__dict
__:
209 obj
= cls
.__dict
__[name
]
211 obj
= getattr(cls
, name
)
213 # Figure out where it was defined.
214 homecls
= getattr(obj
, "__objclass__", None)
218 if name
in base
.__dict
__:
222 # Get the object again, in order to get it from the defining
223 # __dict__ instead of via getattr (if possible).
224 if homecls
is not None and name
in homecls
.__dict
__:
225 obj
= homecls
.__dict
__[name
]
227 # Also get the object via getattr.
228 obj_via_getattr
= getattr(cls
, name
)
230 # Classify the object.
231 if isinstance(obj
, staticmethod):
232 kind
= "static method"
233 elif isinstance(obj
, classmethod):
234 kind
= "class method"
235 elif isinstance(obj
, property):
237 elif (ismethod(obj_via_getattr
) or
238 ismethoddescriptor(obj_via_getattr
)):
243 result
.append((name
, kind
, homecls
, obj
))
247 # ----------------------------------------------------------- class helpers
248 def _searchbases(cls
, accum
):
249 # Simulate the "classic class" search order.
253 for base
in cls
.__bases
__:
254 _searchbases(base
, accum
)
257 "Return tuple of base classes (including cls) in method resolution order."
258 if hasattr(cls
, "__mro__"):
262 _searchbases(cls
, result
)
265 # -------------------------------------------------- source code extraction
266 def indentsize(line
):
267 """Return the indent size, in spaces, at the start of a line of text."""
268 expline
= string
.expandtabs(line
)
269 return len(expline
) - len(string
.lstrip(expline
))
272 """Get the documentation string for an object.
274 All tabs are expanded to spaces. To clean up docstrings that are
275 indented to line up with blocks of code, any whitespace than can be
276 uniformly removed from the second line onwards is removed."""
279 except AttributeError:
281 if not isinstance(doc
, types
.StringTypes
):
284 lines
= string
.split(string
.expandtabs(doc
), '\n')
288 # Find minimum indentation of any non-blank lines after first line.
290 for line
in lines
[1:]:
291 content
= len(string
.lstrip(line
))
293 indent
= len(line
) - content
294 margin
= min(margin
, indent
)
295 # Remove indentation.
297 lines
[0] = lines
[0].lstrip()
298 if margin
< sys
.maxint
:
299 for i
in range(1, len(lines
)): lines
[i
] = lines
[i
][margin
:]
300 # Remove any trailing or leading blank lines.
301 while lines
and not lines
[-1]:
303 while lines
and not lines
[0]:
305 return string
.join(lines
, '\n')
308 """Work out which source or compiled file an object was defined in."""
310 if hasattr(object, '__file__'):
311 return object.__file
__
312 raise TypeError('arg is a built-in module')
314 object = sys
.modules
.get(object.__module
__)
315 if hasattr(object, '__file__'):
316 return object.__file
__
317 raise TypeError('arg is a built-in class')
319 object = object.im_func
320 if isfunction(object):
321 object = object.func_code
322 if istraceback(object):
323 object = object.tb_frame
325 object = object.f_code
327 return object.co_filename
328 raise TypeError('arg is not a module, class, method, '
329 'function, traceback, frame, or code object')
331 def getmoduleinfo(path
):
332 """Get the module name, suffix, mode, and module type for a given file."""
333 filename
= os
.path
.basename(path
)
334 suffixes
= map(lambda (suffix
, mode
, mtype
):
335 (-len(suffix
), suffix
, mode
, mtype
), imp
.get_suffixes())
336 suffixes
.sort() # try longest suffixes first, in case they overlap
337 for neglen
, suffix
, mode
, mtype
in suffixes
:
338 if filename
[neglen
:] == suffix
:
339 return filename
[:neglen
], suffix
, mode
, mtype
341 def getmodulename(path
):
342 """Return the module name for a given file, or None."""
343 info
= getmoduleinfo(path
)
344 if info
: return info
[0]
346 def getsourcefile(object):
347 """Return the Python source file an object was defined in, if it exists."""
348 filename
= getfile(object)
349 if string
.lower(filename
[-4:]) in ['.pyc', '.pyo']:
350 filename
= filename
[:-4] + '.py'
351 for suffix
, mode
, kind
in imp
.get_suffixes():
352 if 'b' in mode
and string
.lower(filename
[-len(suffix
):]) == suffix
:
353 # Looks like a binary file. We want to only return a text file.
355 if os
.path
.exists(filename
):
358 def getabsfile(object):
359 """Return an absolute path to the source or compiled file for an object.
361 The idea is for each object to have a unique origin, so this routine
362 normalizes the result as much as possible."""
363 return os
.path
.normcase(
364 os
.path
.abspath(getsourcefile(object) or getfile(object)))
368 def getmodule(object):
369 """Return the module an object was defined in, or None if not found."""
372 if hasattr(object, '__module__'):
373 return sys
.modules
.get(object.__module
__)
375 file = getabsfile(object)
378 if file in modulesbyfile
:
379 return sys
.modules
.get(modulesbyfile
[file])
380 for module
in sys
.modules
.values():
381 if hasattr(module
, '__file__'):
384 getabsfile(module
))] = module
.__name
__
385 if file in modulesbyfile
:
386 return sys
.modules
.get(modulesbyfile
[file])
387 main
= sys
.modules
['__main__']
388 if not hasattr(object, '__name__'):
390 if hasattr(main
, object.__name
__):
391 mainobject
= getattr(main
, object.__name
__)
392 if mainobject
is object:
394 builtin
= sys
.modules
['__builtin__']
395 if hasattr(builtin
, object.__name
__):
396 builtinobject
= getattr(builtin
, object.__name
__)
397 if builtinobject
is object:
400 def findsource(object):
401 """Return the entire source file and starting line number for an object.
403 The argument may be a module, class, method, function, traceback, frame,
404 or code object. The source code is returned as a list of all the lines
405 in the file and the line number indexes a line in that list. An IOError
406 is raised if the source code cannot be retrieved."""
407 file = getsourcefile(object) or getfile(object)
408 lines
= linecache
.getlines(file)
410 raise IOError('could not get source code')
416 name
= object.__name
__
417 pat
= re
.compile(r
'^\s*class\s*' + name
+ r
'\b')
418 for i
in range(len(lines
)):
419 if pat
.match(lines
[i
]): return lines
, i
421 raise IOError('could not find class definition')
424 object = object.im_func
425 if isfunction(object):
426 object = object.func_code
427 if istraceback(object):
428 object = object.tb_frame
430 object = object.f_code
432 if not hasattr(object, 'co_firstlineno'):
433 raise IOError('could not find function definition')
434 lnum
= object.co_firstlineno
- 1
435 pat
= re
.compile(r
'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
437 if pat
.match(lines
[lnum
]): break
440 raise IOError('could not find code object')
442 def getcomments(object):
443 """Get lines of comments immediately preceding an object's source code.
445 Returns None when source can't be found.
448 lines
, lnum
= findsource(object)
449 except (IOError, TypeError):
453 # Look for a comment block at the top of the file.
455 if lines
and lines
[0][:2] == '#!': start
= 1
456 while start
< len(lines
) and string
.strip(lines
[start
]) in ['', '#']:
458 if start
< len(lines
) and lines
[start
][:1] == '#':
461 while end
< len(lines
) and lines
[end
][:1] == '#':
462 comments
.append(string
.expandtabs(lines
[end
]))
464 return string
.join(comments
, '')
466 # Look for a preceding block of comments at the same indentation.
468 indent
= indentsize(lines
[lnum
])
470 if end
>= 0 and string
.lstrip(lines
[end
])[:1] == '#' and \
471 indentsize(lines
[end
]) == indent
:
472 comments
= [string
.lstrip(string
.expandtabs(lines
[end
]))]
475 comment
= string
.lstrip(string
.expandtabs(lines
[end
]))
476 while comment
[:1] == '#' and indentsize(lines
[end
]) == indent
:
477 comments
[:0] = [comment
]
480 comment
= string
.lstrip(string
.expandtabs(lines
[end
]))
481 while comments
and string
.strip(comments
[0]) == '#':
483 while comments
and string
.strip(comments
[-1]) == '#':
485 return string
.join(comments
, '')
488 """Provide a readline() method to return lines from a list of strings."""
489 def __init__(self
, lines
):
495 if i
< len(self
.lines
):
500 class EndOfBlock(Exception): pass
503 """Provide a tokeneater() method to detect the end of a code block."""
507 self
.passline
= False
510 def tokeneater(self
, type, token
, (srow
, scol
), (erow
, ecol
), line
):
512 if token
in ("def", "class", "lambda"):
513 lastcolon
= line
.rfind(":")
515 oneline
= re
.search(r
"\w", line
[lastcolon
:])
516 if oneline
and line
[-2:] != "\\\n":
517 raise EndOfBlock
, srow
520 elif type == tokenize
.NEWLINE
:
521 self
.passline
= False
525 elif type == tokenize
.INDENT
:
526 self
.indent
= self
.indent
+ 1
528 elif type == tokenize
.DEDENT
:
529 self
.indent
= self
.indent
- 1
531 raise EndOfBlock
, self
.last
532 elif type == tokenize
.NAME
and scol
== 0:
533 raise EndOfBlock
, self
.last
536 """Extract the block of code at the top of the given list of lines."""
538 tokenize
.tokenize(ListReader(lines
).readline
, BlockFinder().tokeneater
)
539 except EndOfBlock
, eob
:
540 return lines
[:eob
.args
[0]]
541 # Fooling the indent/dedent logic implies a one-line definition
544 def getsourcelines(object):
545 """Return a list of source lines and starting line number for an object.
547 The argument may be a module, class, method, function, traceback, frame,
548 or code object. The source code is returned as a list of the lines
549 corresponding to the object and the line number indicates where in the
550 original source file the first line of code was found. An IOError is
551 raised if the source code cannot be retrieved."""
552 lines
, lnum
= findsource(object)
554 if ismodule(object): return lines
, 0
555 else: return getblock(lines
[lnum
:]), lnum
+ 1
557 def getsource(object):
558 """Return the text of the source code for an object.
560 The argument may be a module, class, method, function, traceback, frame,
561 or code object. The source code is returned as a single string. An
562 IOError is raised if the source code cannot be retrieved."""
563 lines
, lnum
= getsourcelines(object)
564 return string
.join(lines
, '')
566 # --------------------------------------------------- class tree extraction
567 def walktree(classes
, children
, parent
):
568 """Recursive helper function for getclasstree()."""
570 classes
.sort(key
=lambda c
: (c
.__module
__, c
.__name
__))
572 results
.append((c
, c
.__bases
__))
574 results
.append(walktree(children
[c
], children
, c
))
577 def getclasstree(classes
, unique
=0):
578 """Arrange the given list of classes into a hierarchy of nested lists.
580 Where a nested list appears, it contains classes derived from the class
581 whose entry immediately precedes the list. Each entry is a 2-tuple
582 containing a class and a tuple of its base classes. If the 'unique'
583 argument is true, exactly one entry appears in the returned structure
584 for each class in the given list. Otherwise, classes using multiple
585 inheritance and their descendants will appear multiple times."""
590 for parent
in c
.__bases
__:
591 if not parent
in children
:
592 children
[parent
] = []
593 children
[parent
].append(c
)
594 if unique
and parent
in classes
: break
597 for parent
in children
:
598 if parent
not in classes
:
600 return walktree(roots
, children
, None)
602 # ------------------------------------------------ argument list extraction
603 # These constants are from Python's compile.h.
604 CO_OPTIMIZED
, CO_NEWLOCALS
, CO_VARARGS
, CO_VARKEYWORDS
= 1, 2, 4, 8
607 """Get information about the arguments accepted by a code object.
609 Three things are returned: (args, varargs, varkw), where 'args' is
610 a list of argument names (possibly containing nested lists), and
611 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
614 raise TypeError('arg is not a code object')
617 nargs
= co
.co_argcount
618 names
= co
.co_varnames
619 args
= list(names
[:nargs
])
622 # The following acrobatics are for anonymous (tuple) arguments.
623 for i
in range(nargs
):
624 if args
[i
][:1] in ['', '.']:
625 stack
, remain
, count
= [], [], []
626 while step
< len(code
):
629 if op
>= dis
.HAVE_ARGUMENT
:
630 opname
= dis
.opname
[op
]
631 value
= ord(code
[step
]) + ord(code
[step
+1])*256
633 if opname
in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']:
636 elif opname
== 'STORE_FAST':
637 stack
.append(names
[value
])
639 # Special case for sublists of length 1: def foo((bar))
640 # doesn't generate the UNPACK_TUPLE bytecode, so if
641 # `remain` is empty here, we have such a sublist.
643 stack
[0] = [stack
[0]]
646 remain
[-1] = remain
[-1] - 1
647 while remain
[-1] == 0:
650 stack
[-size
:] = [stack
[-size
:]]
652 remain
[-1] = remain
[-1] - 1
657 if co
.co_flags
& CO_VARARGS
:
658 varargs
= co
.co_varnames
[nargs
]
661 if co
.co_flags
& CO_VARKEYWORDS
:
662 varkw
= co
.co_varnames
[nargs
]
663 return args
, varargs
, varkw
665 def getargspec(func
):
666 """Get the names and default values of a function's arguments.
668 A tuple of four things is returned: (args, varargs, varkw, defaults).
669 'args' is a list of the argument names (it may contain nested lists).
670 'varargs' and 'varkw' are the names of the * and ** arguments or None.
671 'defaults' is an n-tuple of the default values of the last n arguments.
676 if not isfunction(func
):
677 raise TypeError('arg is not a Python function')
678 args
, varargs
, varkw
= getargs(func
.func_code
)
679 return args
, varargs
, varkw
, func
.func_defaults
681 def getargvalues(frame
):
682 """Get information about arguments passed into a particular frame.
684 A tuple of four things is returned: (args, varargs, varkw, locals).
685 'args' is a list of the argument names (it may contain nested lists).
686 'varargs' and 'varkw' are the names of the * and ** arguments or None.
687 'locals' is the locals dictionary of the given frame."""
688 args
, varargs
, varkw
= getargs(frame
.f_code
)
689 return args
, varargs
, varkw
, frame
.f_locals
693 return '(' + seq
[0] + ',)'
695 return '(' + string
.join(seq
, ', ') + ')'
697 def strseq(object, convert
, join
=joinseq
):
698 """Recursively walk a sequence, stringifying each element."""
699 if type(object) in [types
.ListType
, types
.TupleType
]:
700 return join(map(lambda o
, c
=convert
, j
=join
: strseq(o
, c
, j
), object))
702 return convert(object)
704 def formatargspec(args
, varargs
=None, varkw
=None, defaults
=None,
706 formatvarargs
=lambda name
: '*' + name
,
707 formatvarkw
=lambda name
: '**' + name
,
708 formatvalue
=lambda value
: '=' + repr(value
),
710 """Format an argument spec from the 4 values returned by getargspec.
712 The first four arguments are (args, varargs, varkw, defaults). The
713 other four arguments are the corresponding optional formatting functions
714 that are called to turn names and values into strings. The ninth
715 argument is an optional function to format the sequence of arguments."""
718 firstdefault
= len(args
) - len(defaults
)
719 for i
in range(len(args
)):
720 spec
= strseq(args
[i
], formatarg
, join
)
721 if defaults
and i
>= firstdefault
:
722 spec
= spec
+ formatvalue(defaults
[i
- firstdefault
])
724 if varargs
is not None:
725 specs
.append(formatvarargs(varargs
))
726 if varkw
is not None:
727 specs
.append(formatvarkw(varkw
))
728 return '(' + string
.join(specs
, ', ') + ')'
730 def formatargvalues(args
, varargs
, varkw
, locals,
732 formatvarargs
=lambda name
: '*' + name
,
733 formatvarkw
=lambda name
: '**' + name
,
734 formatvalue
=lambda value
: '=' + repr(value
),
736 """Format an argument spec from the 4 values returned by getargvalues.
738 The first four arguments are (args, varargs, varkw, locals). The
739 next four arguments are the corresponding optional formatting functions
740 that are called to turn names and values into strings. The ninth
741 argument is an optional function to format the sequence of arguments."""
742 def convert(name
, locals=locals,
743 formatarg
=formatarg
, formatvalue
=formatvalue
):
744 return formatarg(name
) + formatvalue(locals[name
])
746 for i
in range(len(args
)):
747 specs
.append(strseq(args
[i
], convert
, join
))
749 specs
.append(formatvarargs(varargs
) + formatvalue(locals[varargs
]))
751 specs
.append(formatvarkw(varkw
) + formatvalue(locals[varkw
]))
752 return '(' + string
.join(specs
, ', ') + ')'
754 # -------------------------------------------------- stack frame extraction
755 def getframeinfo(frame
, context
=1):
756 """Get information about a frame or traceback object.
758 A tuple of five things is returned: the filename, the line number of
759 the current line, the function name, a list of lines of context from
760 the source code, and the index of the current line within that list.
761 The optional second argument specifies the number of lines of context
762 to return, which are centered around the current line."""
763 if istraceback(frame
):
764 lineno
= frame
.tb_lineno
765 frame
= frame
.tb_frame
767 lineno
= frame
.f_lineno
768 if not isframe(frame
):
769 raise TypeError('arg is not a frame or traceback object')
771 filename
= getsourcefile(frame
) or getfile(frame
)
773 start
= lineno
- 1 - context
//2
775 lines
, lnum
= findsource(frame
)
779 start
= max(start
, 1)
780 start
= max(0, min(start
, len(lines
) - context
))
781 lines
= lines
[start
:start
+context
]
782 index
= lineno
- 1 - start
786 return (filename
, lineno
, frame
.f_code
.co_name
, lines
, index
)
788 def getlineno(frame
):
789 """Get the line number from a frame object, allowing for optimization."""
790 # FrameType.f_lineno is now a descriptor that grovels co_lnotab
791 return frame
.f_lineno
793 def getouterframes(frame
, context
=1):
794 """Get a list of records for a frame and all higher (calling) frames.
796 Each record contains a frame object, filename, line number, function
797 name, a list of lines of context, and index within the context."""
800 framelist
.append((frame
,) + getframeinfo(frame
, context
))
804 def getinnerframes(tb
, context
=1):
805 """Get a list of records for a traceback's frame and all lower frames.
807 Each record contains a frame object, filename, line number, function
808 name, a list of lines of context, and index within the context."""
811 framelist
.append((tb
.tb_frame
,) + getframeinfo(tb
, context
))
815 currentframe
= sys
._getframe
817 def stack(context
=1):
818 """Return a list of records for the stack above the caller's frame."""
819 return getouterframes(sys
._getframe
(1), context
)
821 def trace(context
=1):
822 """Return a list of records for the stack below the current exception."""
823 return getinnerframes(sys
.exc_info()[2], context
)