| ================================================================================ |
| 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: |
| |
| .. autoclass:: py.code.Traceback |
| :members: |
| |