py.code: higher level python code and introspection objects¶
py.code
provides higher level APIs and objects for Code, Frame, Traceback,
ExceptionInfo and source code construction. The py.code
library
tries to simplify accessing the code objects as well as creating them.
There is a small set of interfaces a user needs to deal with, all nicely
bundled together, and with a rich set of ‘Pythonic’ functionality.
Contents of the library¶
Every object in the py.code
library wraps a code Python object related
to code objects, source code, frames and tracebacks: the py.code.Code
class wraps code objects, py.code.Source
source snippets,
py.code.Traceback` exception tracebacks, ``py.code.Frame
frame
objects (as found in e.g. tracebacks) and py.code.ExceptionInfo
the
tuple provided by sys.exc_info() (containing exception and traceback
information when an exception occurs). Also in the library is a helper function
py.code.compile()
that provides the same functionality as Python’s
built-in ‘compile()’ function, but returns a wrapped code object.
The wrappers¶
py.code.Code
¶
Code objects are instantiated with a code object or a callable as argument, and provide functionality to compare themselves with other Code objects, get to the source file or its contents, create new Code objects from scratch, etc.
A quick example:
>>> import py
>>> c = py.code.Code(py.path.local.read)
>>> c.path.basename
'common.py'
>>> isinstance(c.source(), py.code.Source)
True
>>> str(c.source()).split('\n')[0]
"def read(self, mode='r'):"
py.code.Source
¶
Source objects wrap snippets of Python source code, providing a simple yet powerful interface to read, deindent, slice, compare, compile and manipulate them, things that are not so easy in core Python.
Example:
>>> s = py.code.Source("""\
... def foo():
... print "foo"
... """)
>>> str(s).startswith('def') # automatic de-indentation!
True
>>> s.isparseable()
True
>>> sub = s.getstatement(1) # get the statement starting at line 1
>>> str(sub).strip() # XXX why is the strip() required?!?
'print "foo"'
-
class
py.code.
Source
(*parts, **kwargs)[source]¶ a immutable object holding a source code fragment, possibly deindenting it.
-
putaround
(before='', after='', indent=' ')[source]¶ return a copy of the source object with ‘before’ and ‘after’ wrapped around it.
-
indent
(indent=' ')[source]¶ return a copy of the source object with all lines indented by the given indent-string.
-
getstatement
(lineno, assertion=False)[source]¶ return Source statement which contains the given linenumber (counted from 0).
-
getstatementrange
(lineno, assertion=False)[source]¶ return (start, end) tuple which spans the minimal statement region which containing the given lineno.
-
deindent
(offset=None)[source]¶ return a new source object deindented by offset. If offset is None then guess an indentation offset from the first non-blank line. Subsequent lines which have a lower indentation offset will be copied verbatim as they are assumed to be part of multilines.
-
py.code.Traceback
¶
Tracebacks are usually not very easy to examine, you need to access certain somewhat hidden attributes of the traceback’s items (resulting in expressions such as ‘fname = tb.tb_next.tb_frame.f_code.co_filename’). The Traceback interface (and its TracebackItem children) tries to improve this.
Example:
>>> import sys
>>> try:
... py.path.local(100) # illegal argument
... except:
... exc, e, tb = sys.exc_info()
>>> t = py.code.Traceback(tb)
>>> first = t[1] # get the second entry (first is in this doc)
>>> first.path.basename # second is in py/path/local.py
'local.py'
>>> isinstance(first.statement, py.code.Source)
True
>>> str(first.statement).strip().startswith('raise ValueError')
True
-
class
py.code.
Traceback
(tb)[source]¶ Traceback objects encapsulate and offer higher level access to Traceback entries.
-
Entry
¶ alias of
TracebackEntry
-
cut
(path=None, lineno=None, firstlineno=None, excludepath=None)[source]¶ return a Traceback instance wrapping part of this Traceback
by provding any combination of path, lineno and firstlineno, the first frame to start the to-be-returned traceback is determined
this allows cutting the first part of a Traceback instance e.g. for formatting reasons (removing some uninteresting bits that deal with handling of the exception/traceback)
-
filter
(fn=<function Traceback.<lambda>>)[source]¶ return a Traceback instance with certain items removed
fn is a function that gets a single argument, a TracebackItem instance, and should return True when the item should be added to the Traceback, False when not
by default this removes all the TracebackItems which are hidden (see ishidden() above)
-
py.code.Frame
¶
Frame wrappers are used in py.code.Traceback
items, and will usually not
directly be instantiated. They provide some nice methods to evaluate code
‘inside’ the frame (using the frame’s local variables), get to the underlying
code (frames have a code attribute that points to a py.code.Code
object)
and examine the arguments.
Example (using the ‘first’ TracebackItem instance created above):
>>> frame = first.frame
>>> isinstance(frame.code, py.code.Code)
True
>>> isinstance(frame.eval('self'), py.path.local)
True
>>> [namevalue[0] for namevalue in frame.getargs()]
['cls', 'path']
-
class
py.code.
Frame
(frame)[source]¶ Wrapper around a Python frame holding f_locals and f_globals in which expressions can be evaluated.
-
statement
¶ statement this frame is at
-
eval
(code, **vars)[source]¶ evaluate ‘code’ in the frame
‘vars’ are optional additional local variables
returns the result of the evaluation
-
py.code.ExceptionInfo
¶
A wrapper around the tuple returned by sys.exc_info() (will call sys.exc_info() itself if the tuple is not provided as an argument), provides some handy attributes to easily access the traceback and exception string.
Example:
>>> import sys
>>> try:
... foobar()
... except:
... excinfo = py.code.ExceptionInfo()
>>> excinfo.typename
'NameError'
>>> isinstance(excinfo.traceback, py.code.Traceback)
True
>>> excinfo.exconly()
"NameError: name 'foobar' is not defined"
-
class
py.code.
ExceptionInfo
(tup=None, exprinfo=None)[source]¶ wraps sys.exc_info() objects and offers help for navigating the traceback.
-
type
= None¶ the exception class
-
value
= None¶ the exception instance
-
tb
= None¶ the exception raw traceback
-
typename
= None¶ the exception type name
-
traceback
= None¶ the exception traceback (py.code.Traceback instance)
-
exconly
(tryshort=False)[source]¶ return the exception as a string
when ‘tryshort’ resolves to True, and the exception is a py.code._AssertionError, only the actual exception part of the exception representation is returned (so ‘AssertionError: ‘ is removed from the beginning)
-
getrepr
(showlocals=False, style='long', abspath=False, tbfilter=True, funcargs=False)[source]¶ return str()able representation of this exception info. showlocals: show locals per traceback entry style: long|short|no|native traceback style tbfilter: hide entries (where __tracebackhide__ is true)
in case of style==native, tbfilter and showlocals is ignored.
-
-
class
py.code.
Traceback
(tb)[source] Traceback objects encapsulate and offer higher level access to Traceback entries.
-
Entry
alias of
TracebackEntry
-
cut
(path=None, lineno=None, firstlineno=None, excludepath=None)[source] return a Traceback instance wrapping part of this Traceback
by provding any combination of path, lineno and firstlineno, the first frame to start the to-be-returned traceback is determined
this allows cutting the first part of a Traceback instance e.g. for formatting reasons (removing some uninteresting bits that deal with handling of the exception/traceback)
-
filter
(fn=<function Traceback.<lambda>>)[source] return a Traceback instance with certain items removed
fn is a function that gets a single argument, a TracebackItem instance, and should return True when the item should be added to the Traceback, False when not
by default this removes all the TracebackItems which are hidden (see ishidden() above)
-
getcrashentry
()[source] return last non-hidden traceback entry that lead to the exception of a traceback.
-
recursionindex
()[source] return the index of the frame/TracebackItem where recursion originates if appropriate, None if no recursion occurred
-