================================================================================ 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'):" .. autoclass:: py.code.Code :members: :inherited-members: ``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"' .. autoclass:: py.code.Source :members: ``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 .. autoclass:: py.code.Traceback :members: ``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'] .. autoclass:: py.code.Frame :members: ``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" .. autoclass:: py.code.ExceptionInfo :members: