142 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
==============
 | 
						|
:api:`py.code`
 | 
						|
==============
 | 
						|
 | 
						|
The :api:`py.code` part of the 'py lib' contains some functionality to help
 | 
						|
dealing with Python code objects. Even though working with Python's internal
 | 
						|
code objects (as found on frames and callables) can be very powerful, it's
 | 
						|
usually also quite cumbersome, because the API provided by core Python is
 | 
						|
relatively low level and not very accessible.
 | 
						|
 | 
						|
The :api:`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.
 | 
						|
 | 
						|
source: :source:`py/code/`
 | 
						|
 | 
						|
Contents of the library
 | 
						|
=======================
 | 
						|
 | 
						|
Every object in the :api:`py.code` library wraps a code Python object related
 | 
						|
to code objects, source code, frames and tracebacks: the :api:`py.code.Code`
 | 
						|
class wraps code objects, :api:`py.code.Source` source snippets,
 | 
						|
:api:`py.code.Traceback` exception tracebacks, :api:`py.code.Frame` frame 
 | 
						|
objects (as found in e.g. tracebacks) and :api:`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
 | 
						|
:api:`py.code.compile()` that provides the same functionality as Python's
 | 
						|
built-in 'compile()' function, but returns a wrapped code object.
 | 
						|
 | 
						|
The wrappers
 | 
						|
============
 | 
						|
 | 
						|
:api:`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='rb'):"
 | 
						|
 | 
						|
source: :source:`py/code/code.py`
 | 
						|
 | 
						|
:api:`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"'
 | 
						|
 | 
						|
source: :source:`py/code/source.py`
 | 
						|
 | 
						|
:api:`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
 | 
						|
 | 
						|
source: :source:`py/code/traceback2.py`
 | 
						|
 | 
						|
:api:`py.code.Frame`
 | 
						|
--------------------
 | 
						|
 | 
						|
Frame wrappers are used in :api:`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 :api:`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.local.LocalPath)
 | 
						|
  True
 | 
						|
  >>> [namevalue[0] for namevalue in frame.getargs()]
 | 
						|
  ['cls', 'path']
 | 
						|
 | 
						|
:api:`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
 | 
						|
  'exceptions.NameError'
 | 
						|
  >>> isinstance(excinfo.traceback, py.code.Traceback)
 | 
						|
  True
 | 
						|
  >>> excinfo.exconly()
 | 
						|
  "NameError: name 'foobar' is not defined"
 | 
						|
 |