summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/tools/py/doc/code.txt
blob: bdd8691da03e2e3a2f768d8a8877c7d4e410f382 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
================================================================================
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: