[svn r63519] Initial Sphinx-ification of the documentation
run: 'make html' to build --HG-- branch : trunk
This commit is contained in:
parent
87bd1d998b
commit
4d95ec5c5c
|
@ -0,0 +1,88 @@
|
|||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf _build/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in _build/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in _build/dirhtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in _build/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in _build/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator _build/qthelp/py lib.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile _build/qthelp/py lib.qhc"
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in _build/latex."
|
||||
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
|
||||
"run these through (pdf)latex."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
|
||||
@echo
|
||||
@echo "The overview file is in _build/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in _build/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in _build/doctest/output.txt."
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 3aded863e1a877ce596c0a99a7f6ab46
|
||||
tags: fbb0d17656682115ca4d033fb2f83ba1
|
|
@ -0,0 +1,69 @@
|
|||
======================
|
||||
``py/bin/`` scripts
|
||||
======================
|
||||
|
||||
The py-lib contains some scripts, most of which are
|
||||
small ones (apart from ``py.test``) that help during
|
||||
the python development process. If working
|
||||
from a svn-checkout of py lib you may add ``py/bin``
|
||||
to your shell ``PATH`` which should make the scripts
|
||||
available on your command prompt.
|
||||
|
||||
``py.test``
|
||||
===========
|
||||
|
||||
The ``py.test`` executable is the main entry point into the py-lib testing tool,
|
||||
see the `py.test documentation`_.
|
||||
|
||||
.. _`py.test documentation`: test.html
|
||||
|
||||
``py.cleanup``
|
||||
==============
|
||||
|
||||
Usage: ``py.cleanup [PATH]``
|
||||
|
||||
Delete pyc file recursively, starting from ``PATH`` (which defaults to the
|
||||
current working directory). Don't follow links and don't recurse into
|
||||
directories with a ".".
|
||||
|
||||
|
||||
``py.countloc``
|
||||
===============
|
||||
|
||||
Usage: ``py.countloc [PATHS]``
|
||||
|
||||
Count (non-empty) lines of python code and number of python files recursively
|
||||
starting from a ``PATHS`` given on the command line (starting from the current
|
||||
working directory). Distinguish between test files and normal ones and report
|
||||
them separately.
|
||||
|
||||
``py.lookup``
|
||||
=============
|
||||
|
||||
Usage: ``py.lookup SEARCH_STRING [options]``
|
||||
|
||||
Looks recursively at Python files for a ``SEARCH_STRING``, starting from the
|
||||
present working directory. Prints the line, with the filename and line-number
|
||||
prepended.
|
||||
|
||||
``py.rest``
|
||||
===========
|
||||
|
||||
Usage: ``py.rest [PATHS] [options]``
|
||||
|
||||
Loot recursively for .txt files starting from ``PATHS`` and convert them to
|
||||
html using docutils or to pdf files, if the ``--pdf`` option is used. For
|
||||
conversion to PDF you will need several command line tools, on Ubuntu Linux
|
||||
this is **texlive** and **texlive-extra-utils**.
|
||||
|
||||
``py.rest`` has some extra features over rst2html (which is shipped with
|
||||
docutils). Most of these are still experimental, the one which is most likely
|
||||
not going to change is the `graphviz`_ directive. With that you can embed .dot
|
||||
files into your document and have them be converted to png (when outputting
|
||||
html) and to eps (when outputting pdf). Otherwise the directive works mostly
|
||||
like the image directive::
|
||||
|
||||
.. graphviz:: example.dot
|
||||
:scale: 90
|
||||
|
||||
.. _`graphviz`: http://www.graphviz.org
|
|
@ -0,0 +1,141 @@
|
|||
=======
|
||||
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
|
||||
'NameError'
|
||||
>>> isinstance(excinfo.traceback, py.code.Traceback)
|
||||
True
|
||||
>>> excinfo.exconly()
|
||||
"NameError: name 'foobar' is not defined"
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
=====================================================
|
||||
Coding Style for the Py lib and friendly applications
|
||||
=====================================================
|
||||
|
||||
|
||||
Honour PEP 8: Style Guide for Python Code
|
||||
-----------------------------------------
|
||||
|
||||
First of all, if you haven't already read it, read the `PEP 8
|
||||
Style Guide for Python Code`_ which, if in doubt, serves as
|
||||
the default coding-style for the py lib.
|
||||
|
||||
Documentation and Testing
|
||||
-------------------------
|
||||
|
||||
- generally we want to drive and interweave coding of
|
||||
documentation, tests and real code as much as possible.
|
||||
Without good documentation others may never know about
|
||||
your latest and greatest feature.
|
||||
|
||||
naming
|
||||
------
|
||||
|
||||
- directories, modules and namespaces are always **lowercase**
|
||||
|
||||
- classes and especially Exceptions are most often **CamelCase**
|
||||
|
||||
- types, i.e. very widely usable classes like the ``py.path``
|
||||
family are all lower case.
|
||||
|
||||
- never use plural names in directory and file names
|
||||
|
||||
- functions/methods are lowercase and ``_`` - separated if
|
||||
you really need to separate at all
|
||||
|
||||
- it's appreciated if you manage to name files in a directory
|
||||
so that tab-completion on the shell level is as easy as possible.
|
||||
|
||||
|
||||
committing
|
||||
----------
|
||||
|
||||
- adding features requires adding appropriate tests.
|
||||
|
||||
- bug fixes should be encoded in a test before being fixed.
|
||||
|
||||
- write telling log messages because several people
|
||||
will read your diffs, and we plan to have a search facility
|
||||
over the py lib's subversion repository.
|
||||
|
||||
- if you add ``.txt`` or ``.py`` files to the repository then
|
||||
please make sure you have ``svn:eol-style`` set to native.
|
||||
which allows checkin/checkout in native line-ending format.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
- Tests are the insurance that your code will be maintained
|
||||
further and survives major releases.
|
||||
|
||||
- Try to put the tests close to the tested code, don't
|
||||
overload directories with names.
|
||||
|
||||
- If you think of exporting new py lib APIs, discuss it first on the
|
||||
`py-dev mailing list`_ and possibly write a chapter in our
|
||||
`future_` book. Communication is considered a key here to make
|
||||
sure that the py lib develops in a consistent way.
|
||||
|
||||
.. _`PEP 8 Style Guide for Python Code`: http://www.python.org/peps/pep-0008.html
|
||||
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _`future`: future.html
|
|
@ -0,0 +1,47 @@
|
|||
Contact and communication
|
||||
===================================
|
||||
|
||||
- **#pylib on irc.freenode.net**: you are welcome to lurk or ask questions!
|
||||
|
||||
- `py-dev developers list`_ development mailing list.
|
||||
|
||||
- `tetamap`_: Holger Krekel's blog, often about testing and py.test related news.
|
||||
|
||||
- `py-svn general commit mailing list`_ to follow all development commits.
|
||||
|
||||
- `development bug/feature tracker`_ this roundup instance serves to file bugs and track issues.
|
||||
(soon to be substitued by a google-code or other hosted one).
|
||||
|
||||
- `merlinux.eu`_ offers teaching and consulting services.
|
||||
|
||||
.. _`merlinux.eu`: http://merlinux.eu
|
||||
|
||||
.. _future: future.html
|
||||
|
||||
.. _`get an account`:
|
||||
|
||||
.. _tetamap: http://tetamap.wordpress.com
|
||||
|
||||
|
||||
..
|
||||
get an account on codespeak
|
||||
---------------------------
|
||||
|
||||
codespeak_ is where the subversion repository is hosted. If you know
|
||||
someone who is active on codespeak already or you are otherwise known in
|
||||
the community (see also: FOAF_) you will get access. But even if
|
||||
you are new to the python developer community please come to the IRC
|
||||
or the mailing list and ask questions, get involved.
|
||||
|
||||
.. _FOAF: http://en.wikipedia.org/wiki/FOAF
|
||||
.. _`coding style`: coding-style.html
|
||||
.. _us: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _codespeak: http://codespeak.net/
|
||||
.. _`py-dev`:
|
||||
.. _`development mailing list`:
|
||||
.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _`subversion commit mailing list`:
|
||||
.. _`py-svn`:
|
||||
.. _`py-svn general commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
|
||||
.. _`development bug/feature tracker`: https://codespeak.net/issue/py-dev/
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
test
|
||||
execnet
|
||||
path
|
||||
code
|
||||
bin
|
||||
xml
|
||||
io
|
||||
log
|
||||
misc
|
||||
why_py
|
||||
future
|
||||
coding-style
|
||||
download
|
||||
links
|
||||
contact
|
||||
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
==============
|
||||
Downloading
|
||||
==============
|
||||
|
||||
|
||||
"easy_install py"
|
||||
===================================================
|
||||
|
||||
With a working `setuptools installation`_ you can install from the command line::
|
||||
|
||||
easy_install -U py
|
||||
|
||||
to get the latest release of the py lib. The ``-U`` switch
|
||||
will trigger an upgrade if you already have an older version installed.
|
||||
The py lib and its tools are expected to work well on Linux,
|
||||
Windows and OSX, Python versions 2.3, 2.4, 2.5 and 2.6.
|
||||
|
||||
We provide binary eggs for Windows machines.
|
||||
|
||||
On other systems you need a working C-compiler in order to
|
||||
install the full py lib. If you don't have a compiler available
|
||||
you can still install the py lib but without greenlets - look
|
||||
below for the ``install_lib`` target.
|
||||
|
||||
**IMPORTANT NOTE**: if you are using Windows and have previous
|
||||
installations of the py lib on your system, please download
|
||||
and execute http://codespeak.net/svn/py/build/winpathclean.py
|
||||
This will check that no previous files are getting in the way.
|
||||
(Unfortunately we don't know about a way to execute this
|
||||
code automatically during the above install).
|
||||
|
||||
Installing on Debian or Fedora
|
||||
===================================
|
||||
|
||||
On Debian systems look for ``python-codespeak-lib``.
|
||||
*This package is probably outdated - if somebody
|
||||
can help with bringing this up to date,
|
||||
that would be very much appreciated.*
|
||||
|
||||
Dwayne Bailey has thankfully put together a Fedora `RPM`_.
|
||||
|
||||
.. _`RPM`: http://translate.sourceforge.net/releases/testing/fedora/pylib-0.9.2-1.fc9.noarch.rpm
|
||||
|
||||
.. _`setuptools installation`: http://pypi.python.org/pypi/setuptools
|
||||
|
||||
|
||||
Downloading a tar/zip archive and installing that
|
||||
===================================================
|
||||
|
||||
Go to the python package index (pypi) and download a tar or zip file:
|
||||
|
||||
http://pypi.python.org/pypi/py/
|
||||
|
||||
and unpack it to a directory, where you then type::
|
||||
|
||||
python setup.py install
|
||||
|
||||
If you don't have a working C-compiler you can do::
|
||||
|
||||
python setup.py install_lib
|
||||
|
||||
You will then not be able to use greenlets but otherwise
|
||||
``py.test`` and all tools and APIs are fine to use.
|
||||
|
||||
Installing from subversion / develop mode
|
||||
============================================
|
||||
|
||||
To follow development or help with fixing things
|
||||
for the next release, checkout the complete code
|
||||
and documentation source::
|
||||
|
||||
svn co http://codespeak.net/svn/py/release/0.9.x py-0.9.x
|
||||
|
||||
You can then issue::
|
||||
|
||||
python setup.py develop
|
||||
|
||||
in order to work with your checkout version.
|
||||
|
||||
other interesting svn checkout points::
|
||||
|
||||
http://codespeak.net/
|
||||
svn/py/release # release tags and branches
|
||||
svn/py/dist # latest stable (may or may not be a release)
|
||||
svn/py/trunk # head development / merge point
|
||||
|
||||
|
||||
Working with multiple py lib versions / svn externals
|
||||
=======================================================
|
||||
|
||||
If you happen to have multiple versions of the py lib
|
||||
around or you ship the py lib as an svn-external to
|
||||
then you might want to use py lib scripts more directly.
|
||||
For example if you have a project layout like this::
|
||||
|
||||
mypkg/
|
||||
subpkg1/
|
||||
tests/
|
||||
tests/
|
||||
py/ # as svn-external, could be specific tag/version
|
||||
|
||||
then you want to make sure that the actual local py lib is used
|
||||
and not another system-wide version. For this you need to add
|
||||
``py/bin`` or ``py\bin\win32`` respectively to your system's PATH settings.
|
||||
|
||||
You can do this by executing (on windows) a script to set the environment::
|
||||
|
||||
c:\\path\to\checkout\py\env.cmd
|
||||
|
||||
or on linux/osx you can add something like this to your shell
|
||||
initialization::
|
||||
|
||||
eval `python ~/path/to/checkout/py/env.py`
|
||||
|
||||
to get good settings for PYTHONPATH and PATH.
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
==========
|
||||
py.execnet
|
||||
==========
|
||||
|
||||
``py.execnet`` allows to:
|
||||
|
||||
* instantiate local or remote Python Processes
|
||||
* send code for execution in one or many processes
|
||||
* asynchronously send and receive data between processes through channels
|
||||
* completely avoid manual installation steps on remote places
|
||||
|
||||
Gateways: immediately spawn local or remote process
|
||||
===================================================
|
||||
|
||||
In order to send code to a remote place or a subprocess
|
||||
you need to instantiate a so-called Gateway object.
|
||||
There are currently three Gateway classes:
|
||||
|
||||
* :api:`py.execnet.PopenGateway` to open a subprocess
|
||||
on the local machine. Useful for making use
|
||||
of multiple processors to to contain code execution
|
||||
in a separated environment.
|
||||
|
||||
* :api:`py.execnet.SshGateway` to connect to
|
||||
a remote ssh server and distribute execution to it.
|
||||
|
||||
* :api:`py.execnet.SocketGateway` a way to connect to
|
||||
a remote Socket based server. *Note* that this method
|
||||
requires a manually started
|
||||
:source:py/execnet/script/socketserver.py
|
||||
script. You can run this "server script" without
|
||||
having the py lib installed on the remote system
|
||||
and you can setup it up as permanent service.
|
||||
|
||||
|
||||
remote_exec: execute source code remotely
|
||||
===================================================
|
||||
|
||||
All gateways offer remote code execution via this high level function::
|
||||
|
||||
def remote_exec(source):
|
||||
"""return channel object for communicating with the asynchronously
|
||||
executing 'source' code which will have a corresponding 'channel'
|
||||
object in its executing namespace."""
|
||||
|
||||
With `remote_exec` you send source code to the other
|
||||
side and get both a local and a remote Channel_ object,
|
||||
which you can use to have the local and remote site
|
||||
communicate data in a structured way. Here is
|
||||
an example for reading the PID::
|
||||
|
||||
>>> import py
|
||||
>>> gw = py.execnet.PopenGateway()
|
||||
>>> channel = gw.remote_exec("""
|
||||
... import os
|
||||
... channel.send(os.getpid())
|
||||
... """)
|
||||
>>> remote_pid = channel.receive()
|
||||
>>> remote_pid != py.std.os.getpid()
|
||||
True
|
||||
|
||||
.. _`Channel`:
|
||||
.. _`channel-api`:
|
||||
.. _`exchange data`:
|
||||
|
||||
Channels: bidirectionally exchange data between hosts
|
||||
===================================================
|
||||
|
||||
A channel object allows to send and receive data between
|
||||
two asynchronously running programs. When calling
|
||||
`remote_exec` you will get a channel object back and
|
||||
the code fragment running on the other side will
|
||||
see a channel object in its global namespace.
|
||||
|
||||
Here is the interface of channel objects::
|
||||
|
||||
#
|
||||
# API for sending and receiving anonymous values
|
||||
#
|
||||
channel.send(item):
|
||||
sends the given item to the other side of the channel,
|
||||
possibly blocking if the sender queue is full.
|
||||
Note that items need to be marshallable (all basic
|
||||
python types are).
|
||||
|
||||
channel.receive():
|
||||
receives an item that was sent from the other side,
|
||||
possibly blocking if there is none.
|
||||
Note that exceptions from the other side will be
|
||||
reraised as gateway.RemoteError exceptions containing
|
||||
a textual representation of the remote traceback.
|
||||
|
||||
channel.waitclose(timeout=None):
|
||||
wait until this channel is closed. Note that a closed
|
||||
channel may still hold items that will be received or
|
||||
send. Note that exceptions from the other side will be
|
||||
reraised as gateway.RemoteError exceptions containing
|
||||
a textual representation of the remote traceback.
|
||||
|
||||
channel.close():
|
||||
close this channel on both the local and the remote side.
|
||||
A remote side blocking on receive() on this channel
|
||||
will get woken up and see an EOFError exception.
|
||||
|
||||
|
||||
.. _xspec:
|
||||
|
||||
|
||||
XSpec: string specification for gateway type and configuration
|
||||
===============================================================
|
||||
|
||||
``py.execnet`` supports a simple extensible format for
|
||||
specifying and configuring Gateways for remote execution.
|
||||
You can use a string specification to instantiate a new gateway,
|
||||
for example a new SshGateway::
|
||||
|
||||
gateway = py.execnet.makegateway("ssh=myhost")
|
||||
|
||||
Let's look at some examples for valid specifications.
|
||||
Specification for an ssh connection to `wyvern`, running on python2.4 in the (newly created) 'mycache' subdirectory::
|
||||
|
||||
ssh=wyvern//python=python2.4//chdir=mycache
|
||||
|
||||
Specification of a python2.5 subprocess; with a low CPU priority ("nice" level). Current dir will be the current dir of the instantiator (that's true for all 'popen' specifications unless they specify 'chdir')::
|
||||
|
||||
popen//python=2.5//nice=20
|
||||
|
||||
Specification of a Python Socket server process that listens on 192.168.1.4:8888; current dir will be the 'pyexecnet-cache' sub directory which is used a default for all remote processes::
|
||||
|
||||
socket=192.168.1.4:8888
|
||||
|
||||
More generally, a specification string has this general format::
|
||||
|
||||
key1=value1//key2=value2//key3=value3
|
||||
|
||||
If you omit a value, a boolean true value is assumed. Currently
|
||||
the following key/values are supported:
|
||||
|
||||
* ``popen`` for a PopenGateway
|
||||
* ``ssh=host`` for a SshGateway
|
||||
* ``socket=address:port`` for a SocketGateway
|
||||
* ``python=executable`` for specifying Python executables
|
||||
* ``chdir=path`` change remote working dir to given relative or absolute path
|
||||
* ``nice=value`` decrease remote nice level if platforms supports it
|
||||
|
||||
|
||||
Examples of py.execnet usage
|
||||
===============================================================
|
||||
|
||||
Compare cwd() of Popen Gateways
|
||||
----------------------------------------
|
||||
|
||||
A PopenGateway has the same working directory as the instantiatior::
|
||||
|
||||
>>> import py, os
|
||||
>>> gw = py.execnet.PopenGateway()
|
||||
>>> ch = gw.remote_exec("import os; channel.send(os.getcwd())")
|
||||
>>> res = ch.receive()
|
||||
>>> assert res == os.getcwd()
|
||||
>>> gw.exit()
|
||||
|
||||
Synchronously receive results from two sub processes
|
||||
-----------------------------------------------------
|
||||
|
||||
Use MultiChannels for receiving multiple results from remote code::
|
||||
|
||||
>>> import py
|
||||
>>> ch1 = py.execnet.PopenGateway().remote_exec("channel.send(1)")
|
||||
>>> ch2 = py.execnet.PopenGateway().remote_exec("channel.send(2)")
|
||||
>>> mch = py.execnet.MultiChannel([ch1, ch2])
|
||||
>>> l = mch.receive_each()
|
||||
>>> assert len(l) == 2
|
||||
>>> assert 1 in l
|
||||
>>> assert 2 in l
|
||||
|
||||
Asynchronously receive results from two sub processes
|
||||
-----------------------------------------------------
|
||||
|
||||
Use ``MultiChannel.make_receive_queue()`` for asynchronously receiving
|
||||
multiple results from remote code. This standard Queue provides
|
||||
``(channel, result)`` tuples which allows to determine where
|
||||
a result comes from::
|
||||
|
||||
>>> import py
|
||||
>>> ch1 = py.execnet.PopenGateway().remote_exec("channel.send(1)")
|
||||
>>> ch2 = py.execnet.PopenGateway().remote_exec("channel.send(2)")
|
||||
>>> mch = py.execnet.MultiChannel([ch1, ch2])
|
||||
>>> queue = mch.make_receive_queue()
|
||||
>>> chan1, res1 = queue.get() # you may also specify a timeout
|
||||
>>> chan2, res2 = queue.get()
|
||||
>>> res1 + res2
|
||||
3
|
||||
>>> assert chan1 in (ch1, ch2)
|
||||
>>> assert chan2 in (ch1, ch2)
|
||||
>>> assert chan1 != chan2
|
||||
|
||||
Receive file contents from remote SSH account
|
||||
-----------------------------------------------------
|
||||
|
||||
Here is a small program that you can use to retrieve
|
||||
contents of remote files::
|
||||
|
||||
import py
|
||||
# open a gateway to a fresh child process
|
||||
gw = py.execnet.SshGateway('codespeak.net')
|
||||
channel = gw.remote_exec("""
|
||||
for fn in channel:
|
||||
f = open(fn, 'rb')
|
||||
channel.send(f.read())
|
||||
f.close()
|
||||
""")
|
||||
|
||||
for fn in somefilelist:
|
||||
channel.send(fn)
|
||||
content = channel.receive()
|
||||
# process content
|
||||
|
||||
# later you can exit / close down the gateway
|
||||
gw.exit()
|
||||
|
||||
|
||||
Instantiate a socket server in a new subprocess
|
||||
-----------------------------------------------------
|
||||
|
||||
The following example opens a PopenGateway, i.e. a python
|
||||
child process, and starts a socket server within that process
|
||||
and then opens a second gateway to the freshly started
|
||||
socketserver::
|
||||
|
||||
import py
|
||||
|
||||
popengw = py.execnet.PopenGateway()
|
||||
socketgw = py.execnet.SocketGateway.new_remote(popengw, ("127.0.0.1", 0))
|
||||
|
||||
print socketgw._rinfo() # print some info about the remote environment
|
|
@ -0,0 +1,145 @@
|
|||
=======================================================
|
||||
Visions and ideas for further development of the py lib
|
||||
=======================================================
|
||||
|
||||
|
||||
This document tries to describe directions and guiding ideas
|
||||
for the near-future development of the py lib. *Note that all
|
||||
statements within this document - even if they sound factual -
|
||||
mostly just express thoughts and ideas. They not always refer to
|
||||
real code so read with some caution.*
|
||||
|
||||
|
||||
Distribute tests ad-hoc across multiple platforms
|
||||
======================================================
|
||||
|
||||
After some more refactoring and unification of
|
||||
the current testing and distribution support code
|
||||
we'd like to be able to run tests on multiple
|
||||
platforms simultanously and allow for interaction
|
||||
and introspection into the (remote) failures.
|
||||
|
||||
|
||||
Make APIGEN useful for more projects
|
||||
================================================
|
||||
|
||||
The new APIGEN tool offers rich information
|
||||
derived from running tests against an application:
|
||||
argument types and callsites, i.e. it shows
|
||||
the places where a particular API is used.
|
||||
In its first incarnation, there are still
|
||||
some specialties that likely prevent it
|
||||
from documenting APIs for other projects.
|
||||
We'd like to evolve to a `py.apigen` tool
|
||||
that can make use of information provided
|
||||
by a py.test run.
|
||||
|
||||
Consider APIGEN and pdb integration
|
||||
===================================
|
||||
|
||||
The information provided by APIGEN can be used in many
|
||||
different ways. An example of this could be to write
|
||||
an extension to pdb which makes it available.
|
||||
Imagine you could issue a pdb command
|
||||
"info <function name>" and get information
|
||||
regarding incoming, and outgoing types, possible
|
||||
exceptions, field types and call sites.
|
||||
|
||||
Distribute channels/programs across networks
|
||||
================================================
|
||||
|
||||
Apart from stabilizing setup/teardown procedures
|
||||
for `py.execnet`_, we'd like to generalize its
|
||||
implementation to allow connecting two programs
|
||||
across multiple hosts, i.e. we'd like to arbitrarily
|
||||
send "channels" across the network. Likely this
|
||||
will be done by using the "pipe" model, i.e.
|
||||
that each channel is actually a pair of endpoints,
|
||||
both of which can be independently transported
|
||||
across the network. The programs who "own"
|
||||
these endpoints remain connected.
|
||||
|
||||
.. _`py.execnet`: execnet.html
|
||||
|
||||
Benchmarking and persistent storage
|
||||
=========================================
|
||||
|
||||
For storing test results, but also benchmarking
|
||||
and other information, we need a solid way
|
||||
to store all kinds of information from test runs.
|
||||
We'd like to generate statistics or html-overview
|
||||
out of it, but also use such information to determine when
|
||||
a certain test broke, or when its performance
|
||||
decreased considerably.
|
||||
|
||||
.. _`restructured text`: http://docutils.sourceforge.net/docs/user/rst/quickref.html
|
||||
.. _`python standard library`: http://www.python.org/doc/2.3.4/lib/lib.html
|
||||
.. _`xpython EuroPython 2004 talk`: http://codespeak.net/svn/user/hpk/talks/xpython-talk.txt
|
||||
.. _`under the xpy tree`: http://codespeak.net/svn/user/hpk/xpy/xml.py
|
||||
.. _`future book`: future.html
|
||||
.. _`PEP-324 subprocess module`: http://www.python.org/peps/pep-0324.html
|
||||
.. _`subprocess implementation`: http://www.lysator.liu.se/~astrand/popen5/
|
||||
.. _`py.test`: test.html
|
||||
|
||||
|
||||
.. _`general-path`:
|
||||
.. _`a more general view on path objects`:
|
||||
|
||||
Refactor path implementations to use a Filesystem Abstraction
|
||||
=============================================================
|
||||
|
||||
It seems like a good idea to refactor all `py.path`_ Path implementations to
|
||||
use an internal Filesystem abstraction. The current code base
|
||||
would be transformed to have Filesystem implementations for e.g.
|
||||
local, subversion and subversion "working copy" filesystems. Today
|
||||
the according code is scattered through path-handling code.
|
||||
|
||||
On a related note, Armin Rigo has hacked `pylufs`_ and more recently has
|
||||
written `pyfuse`_ which allow to
|
||||
implement kernel-level linux filesystems with pure python. Now
|
||||
the idea is that the mentioned filesystem implementations would
|
||||
be directly usable for such linux-filesystem glue code.
|
||||
|
||||
In other words, implementing a `memoryfs`_ or a `dictfs`_ would
|
||||
give you two things for free: a filesystem mountable at kernel level
|
||||
as well as a uniform "path" object allowing you to access your
|
||||
filesystem in convenient ways.
|
||||
|
||||
Also interesting to check out is Will McGugan's work on
|
||||
his `fs package`_.
|
||||
|
||||
I think the main question is what the very fundamental
|
||||
filesystem API should look like. Here are some doctests
|
||||
on how a `draft py.fs`_ could look like. There also
|
||||
is Matthew Scotts `dictproxy patch`_ which adds
|
||||
``py.path.dict`` and ``py.path.proxy``.
|
||||
|
||||
|
||||
.. _`dictproxy patch`: http://codespeak.net/pipermail/py-dev/attachments/20050128/d9595512/virtual1-0001.bin
|
||||
.. _`draft py.fs`: draft_pyfs
|
||||
.. _`py.path`: http://codespeak.net/py/dist/path.html
|
||||
.. _`fs package`: http://www.willmcgugan.com/2008/09/21/announcing-fs-010-a-python-file-system/#comment-60276
|
||||
.. _`memoryfs`: http://codespeak.net/svn/user/arigo/hack/pyfuse/memoryfs.py
|
||||
.. _`dictfs`: http://codespeak.net/pipermail/py-dev/2005-January/000191.html
|
||||
.. _`pylufs`: http://codespeak.net/svn/user/arigo/hack/pylufs/
|
||||
.. _`pyfuse`: http://codespeak.net/svn/user/arigo/hack/pyfuse/
|
||||
|
||||
|
||||
Integrate interactive completion
|
||||
==================================
|
||||
|
||||
It'd be nice to integrate the bash-like
|
||||
rlcompleter2_ python command line completer
|
||||
into the py lib, and making it work remotely
|
||||
and with pdb.
|
||||
|
||||
.. _rlcompleter2: http://codespeak.net/rlcompleter2/
|
||||
|
||||
Consider more features
|
||||
==================================
|
||||
|
||||
There are many more features and useful classes
|
||||
that might be nice to integrate. For example, we might put
|
||||
Armin's `lazy list`_ implementation into the py lib.
|
||||
|
||||
.. _`lazy list`: http://codespeak.net/svn/user/arigo/hack/misc/collect.py
|
|
@ -0,0 +1,250 @@
|
|||
===============================================
|
||||
Implementation and Customization of ``py.test``
|
||||
===============================================
|
||||
|
||||
|
||||
.. _`basicpicture`:
|
||||
|
||||
|
||||
Collecting and running tests / implementation remarks
|
||||
======================================================
|
||||
|
||||
In order to customize ``py.test`` it's good to understand
|
||||
its basic architure (WARNING: these are not guaranteed
|
||||
yet to stay the way they are now!)::
|
||||
|
||||
___________________
|
||||
| |
|
||||
| Collector |
|
||||
|___________________|
|
||||
/ \
|
||||
| Item.run()
|
||||
| ^
|
||||
receive test Items /
|
||||
| /execute test Item
|
||||
| /
|
||||
___________________/
|
||||
| |
|
||||
| Session |
|
||||
|___________________|
|
||||
|
||||
.............................
|
||||
. conftest.py configuration .
|
||||
. cmdline options .
|
||||
.............................
|
||||
|
||||
|
||||
The *Session* basically receives test *Items* from a *Collector*,
|
||||
and executes them via the ``Item.run()`` method. It monitors
|
||||
the outcome of the test and reports about failures and successes.
|
||||
|
||||
.. _`collection process`:
|
||||
|
||||
Collectors and the test collection process
|
||||
------------------------------------------
|
||||
|
||||
The collecting process is iterative, i.e. the session
|
||||
traverses and generates a *collector tree*. Here is an example of such
|
||||
a tree, generated with the command ``py.test --collectonly py/xmlobj``::
|
||||
|
||||
<Directory 'xmlobj'>
|
||||
<Directory 'testing'>
|
||||
<Module 'test_html.py' (py.__.xmlobj.testing.test_html)>
|
||||
<Function 'test_html_name_stickyness'>
|
||||
<Function 'test_stylenames'>
|
||||
<Function 'test_class_None'>
|
||||
<Function 'test_alternating_style'>
|
||||
<Module 'test_xml.py' (py.__.xmlobj.testing.test_xml)>
|
||||
<Function 'test_tag_with_text'>
|
||||
<Function 'test_class_identity'>
|
||||
<Function 'test_tag_with_text_and_attributes'>
|
||||
<Function 'test_tag_with_subclassed_attr_simple'>
|
||||
<Function 'test_tag_nested'>
|
||||
<Function 'test_tag_xmlname'>
|
||||
|
||||
|
||||
By default all directories not starting with a dot are traversed,
|
||||
looking for ``test_*.py`` and ``*_test.py`` files. Those files
|
||||
are imported under their `package name`_.
|
||||
|
||||
The Module collector looks for test functions
|
||||
and test classes and methods. Test functions and methods
|
||||
are prefixed ``test`` by default. Test classes must
|
||||
start with a capitalized ``Test`` prefix.
|
||||
|
||||
|
||||
.. _`collector API`:
|
||||
|
||||
test items are collectors as well
|
||||
---------------------------------
|
||||
|
||||
To make the reporting life simple for the session object
|
||||
items offer a ``run()`` method as well. In fact the session
|
||||
distinguishes "collectors" from "items" solely by interpreting
|
||||
their return value. If it is a list, then we recurse into
|
||||
it, otherwise we consider the "test" as passed.
|
||||
|
||||
.. _`package name`:
|
||||
|
||||
constructing the package name for test modules
|
||||
-------------------------------------------------
|
||||
|
||||
Test modules are imported under their fully qualified
|
||||
name. Given a filesystem ``fspath`` it is constructed as follows:
|
||||
|
||||
* walk the directories up to the last one that contains
|
||||
an ``__init__.py`` file.
|
||||
|
||||
* perform ``sys.path.insert(0, basedir)``.
|
||||
|
||||
* import the root package as ``root``
|
||||
|
||||
* determine the fully qualified name for ``fspath`` by either:
|
||||
|
||||
* calling ``root.__pkg__.getimportname(fspath)`` if the
|
||||
``__pkg__`` exists.` or
|
||||
|
||||
* otherwise use the relative path of the module path to
|
||||
the base dir and turn slashes into dots and strike
|
||||
the trailing ``.py``.
|
||||
|
||||
|
||||
|
||||
Customizing the testing process
|
||||
===============================
|
||||
|
||||
writing conftest.py files
|
||||
-----------------------------------
|
||||
|
||||
You may put conftest.py files containing project-specific
|
||||
configuration in your project's root directory, it's usually
|
||||
best to put it just into the same directory level as your
|
||||
topmost ``__init__.py``. In fact, ``py.test`` performs
|
||||
an "upwards" search starting from the directory that you specify
|
||||
to be tested and will lookup configuration values right-to-left.
|
||||
You may have options that reside e.g. in your home directory
|
||||
but note that project specific settings will be considered
|
||||
first. There is a flag that helps you debugging your
|
||||
conftest.py configurations::
|
||||
|
||||
py.test --traceconfig
|
||||
|
||||
|
||||
customizing the collecting and running process
|
||||
-----------------------------------------------
|
||||
|
||||
To introduce different test items you can create
|
||||
one or more ``conftest.py`` files in your project.
|
||||
When the collection process traverses directories
|
||||
and modules the default collectors will produce
|
||||
custom Collectors and Items if they are found
|
||||
in a local ``conftest.py`` file.
|
||||
|
||||
example: perform additional ReST checks
|
||||
.......................................
|
||||
|
||||
With your custom collectors or items you can completely
|
||||
derive from the standard way of collecting and running
|
||||
tests in a localized manner. Let's look at an example.
|
||||
If you invoke ``py.test --collectonly py/documentation``
|
||||
then you get::
|
||||
|
||||
<DocDirectory 'documentation'>
|
||||
<DocDirectory 'example'>
|
||||
<DocDirectory 'pytest'>
|
||||
<Module 'test_setup_flow_example.py' (test_setup_flow_example)>
|
||||
<Class 'TestStateFullThing'>
|
||||
<Instance '()'>
|
||||
<Function 'test_42'>
|
||||
<Function 'test_23'>
|
||||
<ReSTChecker 'TODO.txt'>
|
||||
<ReSTSyntaxTest 'TODO.txt'>
|
||||
<LinkCheckerMaker 'checklinks'>
|
||||
<ReSTChecker 'api.txt'>
|
||||
<ReSTSyntaxTest 'api.txt'>
|
||||
<LinkCheckerMaker 'checklinks'>
|
||||
<CheckLink 'getting-started.html'>
|
||||
...
|
||||
|
||||
In ``py/documentation/conftest.py`` you find the following
|
||||
customization::
|
||||
|
||||
class DocDirectory(py.test.collect.Directory):
|
||||
|
||||
def run(self):
|
||||
results = super(DocDirectory, self).run()
|
||||
for x in self.fspath.listdir('*.txt', sort=True):
|
||||
results.append(x.basename)
|
||||
return results
|
||||
|
||||
def join(self, name):
|
||||
if not name.endswith('.txt'):
|
||||
return super(DocDirectory, self).join(name)
|
||||
p = self.fspath.join(name)
|
||||
if p.check(file=1):
|
||||
return ReSTChecker(p, parent=self)
|
||||
|
||||
Directory = DocDirectory
|
||||
|
||||
The existence of the 'Directory' name in the
|
||||
``pypy/documentation/conftest.py`` module makes the collection
|
||||
process defer to our custom "DocDirectory" collector. We extend
|
||||
the set of collected test items by ``ReSTChecker`` instances
|
||||
which themselves create ``ReSTSyntaxTest`` and ``LinkCheckerMaker``
|
||||
items. All of this instances (need to) follow the `collector API`_.
|
||||
|
||||
Customizing the reporting of Test Failures
|
||||
--------------------------------------------
|
||||
|
||||
XXX implement Item.repr_run and Item.repr_path for your test items
|
||||
|
||||
Writing new assertion methods
|
||||
-------------------------------------
|
||||
|
||||
XXX __tracebackhide__, and use "print"
|
||||
|
||||
|
||||
Customizing the collection process in a module
|
||||
----------------------------------------------
|
||||
|
||||
REPEATED WARNING: details of the collection and running process are
|
||||
still subject to refactorings and thus details will change.
|
||||
If you are customizing py.test at "Item" level then you
|
||||
definitely want to be subscribed to the `py-dev mailing list`_
|
||||
to follow ongoing development.
|
||||
|
||||
If you have a module where you want to take responsibility for
|
||||
collecting your own test Items and possibly even for executing
|
||||
a test then you can provide `generative tests`_ that yield
|
||||
callables and possibly arguments as a tuple. This is especially
|
||||
useful for calling application test machinery with different
|
||||
parameter sets but counting each of the calls as a separate
|
||||
tests.
|
||||
|
||||
.. _`generative tests`: test-features.html#generative-tests
|
||||
|
||||
The other extension possibility is about
|
||||
specifying a custom test ``Item`` class which
|
||||
is responsible for setting up and executing an underlying
|
||||
test. Or you can extend the collection process for a whole
|
||||
directory tree by putting Items in a ``conftest.py`` configuration file.
|
||||
The collection process dynamically consults the *chain of conftest.py*
|
||||
modules to determine collectors and items at ``Directory``, ``Module``,
|
||||
``Class``, ``Function`` or ``Generator`` level respectively.
|
||||
|
||||
Customizing execution of Functions
|
||||
----------------------------------
|
||||
|
||||
- ``py.test.collect.Function`` test items control execution
|
||||
of a test function. ``function.run()`` will get called by the
|
||||
session in order to actually run a test. The method is responsible
|
||||
for performing proper setup/teardown ("Test Fixtures") for a
|
||||
Function test.
|
||||
|
||||
- ``Function.execute(target, *args)`` methods are invoked by
|
||||
the default ``Function.run()`` to actually execute a python
|
||||
function with the given (usually empty set of) arguments.
|
||||
|
||||
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
py lib: Main tools and APIs
|
||||
===================================
|
||||
|
||||
`py.test`_ write and deploy unit- and functional tests to multiple machines.
|
||||
|
||||
`py.execnet`_ rapidly deploy local or remote processes from your program.
|
||||
|
||||
`py.path`_: use path objects to transparently access local and svn filesystems.
|
||||
|
||||
`py.code`_: generate python code and use advanced introspection/traceback support.
|
||||
|
||||
Minor support functionality
|
||||
===================================
|
||||
|
||||
`py lib scripts`_ to make python development easier.
|
||||
|
||||
`py.xml`_ for generating in-memory xml/html object trees
|
||||
|
||||
`py.io`_: Helper Classes for Capturing of Input/Output
|
||||
|
||||
`py.log`_: an alpha document about the ad-hoc logging facilities
|
||||
|
||||
`miscellaneous features`_ describes some small but nice py lib features.
|
||||
|
||||
|
||||
.. _`download and installation`: download.html
|
||||
.. _`py-dev at codespeak net`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _`py.execnet`: execnet.html
|
||||
.. _`py.log`: log.html
|
||||
.. _`py.io`: io.html
|
||||
.. _`py.path`: path.html
|
||||
.. _`py.code`: code.html
|
||||
.. _`py.test`: test.html
|
||||
.. _`py lib scripts`: bin.html
|
||||
.. _`py.xml`: xml.html
|
||||
.. _`Why What how py?`: why_py.html
|
||||
.. _`future`: future.html
|
||||
.. _`miscellaneous features`: misc.html
|
||||
.. _`0.9.2 release announcement`: release-0.9.2.html
|
||||
|
||||
|
||||
Full Contents
|
||||
===================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
test
|
||||
execnet
|
||||
path
|
||||
code
|
||||
bin
|
||||
xml
|
||||
io
|
||||
log
|
||||
misc
|
||||
why_py
|
||||
future
|
||||
coding-style
|
||||
links
|
||||
contact
|
||||
download
|
||||
releases
|
||||
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
=======
|
||||
py.io
|
||||
=======
|
||||
|
||||
|
||||
The 'py' lib provides helper classes for capturing IO during
|
||||
execution of a program.
|
||||
|
||||
IO Capturing examples
|
||||
===============================================
|
||||
|
||||
:api:`py.io.StdCapture`
|
||||
---------------------------
|
||||
|
||||
Basic Example:
|
||||
|
||||
>>> import py
|
||||
>>> capture = py.io.StdCapture()
|
||||
>>> print "hello"
|
||||
>>> out,err = capture.reset()
|
||||
>>> out.strip() == "hello"
|
||||
True
|
||||
|
||||
For calling functions you may use a shortcut:
|
||||
|
||||
>>> import py
|
||||
>>> def f(): print "hello"
|
||||
>>> res, out, err = py.io.StdCapture.call(f)
|
||||
>>> out.strip() == "hello"
|
||||
True
|
||||
|
||||
:api:`py.io.StdCaptureFD`
|
||||
---------------------------
|
||||
|
||||
If you also want to capture writes to the stdout/stderr
|
||||
filedescriptors you may invoke:
|
||||
|
||||
>>> import py, sys
|
||||
>>> capture = py.io.StdCaptureFD()
|
||||
>>> sys.stderr.write("world")
|
||||
>>> out,err = capture.reset()
|
||||
>>> err
|
||||
'world'
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
=====
|
||||
Links
|
||||
=====
|
||||
|
||||
Some links to ongoing discussions and comments about pylib and technics/concepts pylib uses.
|
||||
|
||||
* `Discussion <http://blog.ianbicking.org/site-packages-considered-harmful.html>`_
|
||||
about site-packages. That's why pylib autopath and py.__.misc.dynpkg are a good idea ;-)
|
||||
|
||||
|
||||
* `Pyinotify <http://pyinotify.sourceforge.net/>`_ uses code from pypy autopath functions.
|
||||
|
||||
* `Testing (WSGI) Applications with Paste <http://pythonpaste.org/testing-applications.html#the-test-environment>`_ and py.test. "This has been written with py.test in mind." Paste uses py.test.
|
||||
|
||||
|
||||
* `Agile Testing <http://agiletesting.blogspot.com/>`_ by Grig Gheorghiu
|
||||
|
||||
* `Slides from 'py library overview' presentation at SoCal Piggies meeting
|
||||
<http://agiletesting.blogspot.com/2005/07/slides-from-py-library-overview.html>`_
|
||||
|
||||
* `Python unit testing part 3: the py.test tool and library
|
||||
<http://agiletesting.blogspot.com/2005/01/python-unit-testing-part-3-pytest-tool.html>`_
|
||||
|
||||
* `greenlets and py.xml
|
||||
<http://agiletesting.blogspot.com/2005/07/py-lib-gems-greenlets-and-pyxml.html>`_
|
||||
|
||||
* `Keyword-based logging with the py library
|
||||
<http://agiletesting.blogspot.com/2005/06/keyword-based-logging-with-py-library.html>`_
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
.. role:: code(literal)
|
||||
.. role:: file(literal)
|
||||
|
||||
.. XXX figure out how the code literals should be dealt with in sphinx. There is probably something builtin.
|
||||
|
||||
========================================
|
||||
py.log documentation and musings
|
||||
========================================
|
||||
|
||||
|
||||
Foreword
|
||||
========
|
||||
|
||||
This document is an attempt to briefly state the actual specification of the
|
||||
:code:`py.log` module. It was written by Francois Pinard and also contains
|
||||
some ideas for enhancing the py.log facilities.
|
||||
|
||||
NOTE that :code:`py.log` is subject to refactorings, it may change with
|
||||
the next release.
|
||||
|
||||
This document is meant to trigger or facilitate discussions. It shamelessly
|
||||
steals from the `Agile Testing`__ comments, and from other sources as well,
|
||||
without really trying to sort them out.
|
||||
|
||||
__ http://agiletesting.blogspot.com/2005/06/keyword-based-logging-with-py-library.html
|
||||
|
||||
|
||||
Logging organisation
|
||||
====================
|
||||
|
||||
The :code:`py.log` module aims a niche comparable to the one of the
|
||||
`logging module`__ found within the standard Python distributions, yet
|
||||
with much simpler paradigms for configuration and usage.
|
||||
|
||||
__ http://www.python.org/doc/2.4.2/lib/module-logging.html
|
||||
|
||||
Holger Krekel, the main :code:`py` library developer, introduced
|
||||
the idea of keyword-based logging and the idea of logging *producers* and
|
||||
*consumers*. A log producer is an object used by the application code
|
||||
to send messages to various log consumers. When you create a log
|
||||
producer, you define a set of keywords that are then used to both route
|
||||
the logging messages to consumers, and to prefix those messages.
|
||||
|
||||
In fact, each log producer has a few keywords associated with it for
|
||||
identification purposes. These keywords form a tuple of strings, and
|
||||
may be used to later retrieve a particular log producer.
|
||||
|
||||
A log producer may (or may not) be associated with a log consumer, meant
|
||||
to handle log messages in particular ways. The log consumers can be
|
||||
``STDOUT``, ``STDERR``, log files, syslog, the Windows Event Log, user
|
||||
defined functions, etc. (Yet, logging to syslog or to the Windows Event
|
||||
Log is only future plans for now). A log producer has never more than
|
||||
one consumer at a given time, but it is possible to dynamically switch
|
||||
a producer to use another consumer. On the other hand, a single log
|
||||
consumer may be associated with many producers.
|
||||
|
||||
Note that creating and associating a producer and a consumer is done
|
||||
automatically when not otherwise overriden, so using :code:`py` logging
|
||||
is quite comfortable even in the smallest programs. More typically,
|
||||
the application programmer will likely design a hierarchy of producers,
|
||||
and will select keywords appropriately for marking the hierarchy tree.
|
||||
If a node of the hierarchical tree of producers has to be divided in
|
||||
sub-trees, all producers in the sub-trees share, as a common prefix, the
|
||||
keywords of the node being divided. In other words, we go further down
|
||||
in the hierarchy of producers merely by adding keywords.
|
||||
|
||||
Using the py.log library
|
||||
================================
|
||||
|
||||
To use the :code:`py.log` library, the user must import it into a Python
|
||||
application, create at least one log producer and one log consumer, have
|
||||
producers and consumers associated, and finally call the log producers
|
||||
as needed, giving them log messages.
|
||||
|
||||
Importing
|
||||
---------
|
||||
|
||||
Once the :code:`py` library is installed on your system, a mere::
|
||||
|
||||
import py
|
||||
|
||||
holds enough magic for lazily importing the various facilities of the
|
||||
:code:`py` library when they are first needed. This is really how
|
||||
:code:`py.log` is made available to the application. For example, after
|
||||
the above ``import py``, one may directly write ``py.log.Producer(...)``
|
||||
and everything should work fine, the user does not have to worry about
|
||||
specifically importing more modules.
|
||||
|
||||
Creating a producer
|
||||
-------------------
|
||||
|
||||
There are three ways for creating a log producer instance:
|
||||
|
||||
+ As soon as ``py.log`` is first evaluated within an application
|
||||
program, a default log producer is created, and made available under
|
||||
the name ``py.log.default``. The keyword ``default`` is associated
|
||||
with that producer.
|
||||
|
||||
+ The ``py.log.Producer()`` constructor may be explicitly called
|
||||
for creating a new instance of a log producer. That constructor
|
||||
accepts, as an argument, the keywords that should be associated with
|
||||
that producer. Keywords may be given either as a tuple of keyword
|
||||
strings, or as a single space-separated string of keywords.
|
||||
|
||||
+ Whenever an attribute is *taken* out of a log producer instance,
|
||||
for the first time that attribute is taken, a new log producer is
|
||||
created. The keywords associated with that new producer are those
|
||||
of the initial producer instance, to which is appended the name of
|
||||
the attribute being taken.
|
||||
|
||||
The last point is especially useful, as it allows using log producers
|
||||
without further declarations, merely creating them *on-the-fly*.
|
||||
|
||||
Creating a consumer
|
||||
-------------------
|
||||
|
||||
There are many ways for creating or denoting a log consumer:
|
||||
|
||||
+ A default consumer exists within the ``py.log`` facilities, which
|
||||
has the effect of writing log messages on the Python standard output
|
||||
stream. That consumer is associated at the very top of the producer
|
||||
hierarchy, and as such, is called whenever no other consumer is
|
||||
found.
|
||||
|
||||
+ The notation ``py.log.STDOUT`` accesses a log consumer which writes
|
||||
log messages on the Python standard output stream.
|
||||
|
||||
+ The notation ``py.log.STDERR`` accesses a log consumer which writes
|
||||
log messages on the Python standard error stream.
|
||||
|
||||
+ The ``py.log.File()`` constructor accepts, as argument, either a file
|
||||
already opened in write mode or any similar file-like object, and
|
||||
creates a log consumer able to write log messages onto that file.
|
||||
|
||||
+ The ``py.log.Path()`` constructor accepts a file name for its first
|
||||
argument, and creates a log consumer able to write log messages into
|
||||
that file. The constructor call accepts a few keyword parameters:
|
||||
|
||||
+ ``append``, which is ``False`` by default, may be used for
|
||||
opening the file in append mode instead of write mode.
|
||||
|
||||
+ ``delayed_create``, which is ``False`` by default, maybe be used
|
||||
for opening the file at the latest possible time. Consequently,
|
||||
the file will not be created if it did not exist, and no actual
|
||||
log message gets written to it.
|
||||
|
||||
+ ``buffering``, which is 1 by default, is used when opening the
|
||||
file. Buffering can be turned off by specifying a 0 value. The
|
||||
buffer size may also be selected through this argument.
|
||||
|
||||
+ Any user defined function may be used for a log consumer. Such a
|
||||
function should accept a single argument, which is the message to
|
||||
write, and do whatever is deemed appropriate by the programmer.
|
||||
When the need arises, this may be an especially useful and flexible
|
||||
feature.
|
||||
|
||||
+ The special value ``None`` means no consumer at all. This acts just
|
||||
like if there was a consumer which would silently discard all log
|
||||
messages sent to it.
|
||||
|
||||
Associating producers and consumers
|
||||
-----------------------------------
|
||||
|
||||
Each log producer may have at most one log consumer associated with
|
||||
it. A log producer gets associated with a log consumer through a
|
||||
``py.log.set_consumer()`` call. That function accepts two arguments,
|
||||
the first identifying a producer (a tuple of keyword strings or a single
|
||||
space-separated string of keywords), the second specifying the precise
|
||||
consumer to use for that producer. Until this function is called for a
|
||||
producer, that producer does not have any explicit consumer associated
|
||||
with it.
|
||||
|
||||
Now, the hierarchy of log producers establishes which consumer gets used
|
||||
whenever a producer has no explicit consumer. When a log producer
|
||||
has no consumer explicitly associated with it, it dynamically and
|
||||
recursively inherits the consumer of its parent node, that is, that node
|
||||
being a bit closer to the root of the hierarchy. In other words, the
|
||||
rightmost keywords of that producer are dropped until another producer
|
||||
is found which has an explicit consumer. A nice side-effect is that,
|
||||
by explicitly associating a consumer with a producer, all consumer-less
|
||||
producers which appear under that producer, in the hierarchy tree,
|
||||
automatically *inherits* that consumer.
|
||||
|
||||
Writing log messages
|
||||
--------------------
|
||||
|
||||
All log producer instances are also functions, and this is by calling
|
||||
them that log messages are generated. Each call to a producer object
|
||||
produces the text for one log entry, which in turn, is sent to the log
|
||||
consumer for that producer.
|
||||
|
||||
The log entry displays, after a prefix identifying the log producer
|
||||
being used, all arguments given in the call, converted to strings and
|
||||
space-separated. (This is meant by design to be fairly similar to what
|
||||
the ``print`` statement does in Python). The prefix itself is made up
|
||||
of a colon-separated list of keywords associated with the producer, the
|
||||
whole being set within square brackets.
|
||||
|
||||
Note that the consumer is responsible for adding the newline at the end
|
||||
of the log entry. That final newline is not part of the text for the
|
||||
log entry.
|
||||
|
||||
.. Other details
|
||||
.. -------------
|
||||
.. XXX: fill in details
|
||||
.. + Should speak about pickle-ability of :code:`py.log`.
|
||||
..
|
||||
.. + What is :code:`log.get` (in :file:`logger.py`)?
|
|
@ -0,0 +1,216 @@
|
|||
====================================
|
||||
Miscellaneous features of the py lib
|
||||
====================================
|
||||
|
||||
|
||||
Mapping the standard python library into py
|
||||
===========================================
|
||||
|
||||
Warning: This feature is very young and thus experimental.
|
||||
Be prepared to adapt your code later if you use it.
|
||||
|
||||
After you have worked with the py lib a bit, you might enjoy
|
||||
the lazy importing, i.e. you only have to do ``import py`` and
|
||||
work your way to your desired object. Using the full path
|
||||
also ensures that there remains a focus on getting short paths
|
||||
to objects.
|
||||
|
||||
The :api:`py.std` hook
|
||||
----------------------
|
||||
|
||||
Of course, no matter what, everybody will continue to use the
|
||||
python standard library because it is a very usable code base.
|
||||
However, to properly support lazyness the py lib offers a way
|
||||
to get to many standard modules without requiring "import"
|
||||
statements. For example, to get to the print-exception
|
||||
functionality of the standard library you can write::
|
||||
|
||||
py.std.traceback.print_exc()
|
||||
|
||||
without having to do anything else than the usual ``import py``
|
||||
at the beginning. Note that not having imports for the
|
||||
`python standard library` obviously gets rid of the *unused
|
||||
import* problem. Modules only get imported when you actually
|
||||
need them.
|
||||
|
||||
Moreover, this approach resolves some of the issues stated in
|
||||
`the relative/absolute import PEP-328`_, as with the above
|
||||
approach you never have ambiguity problems. The above
|
||||
traceback-usage is an absolute path that will not be
|
||||
accidentally get confused with local names. (Well, never put
|
||||
a file ``py.py`` in an importable path, btw, mind you :-)
|
||||
|
||||
Automagically accessing sub packages doesn't work (yet?)
|
||||
--------------------------------------------------------
|
||||
|
||||
If you use the :api:`py.std` hook you currently cannot magically
|
||||
import nested packages which otherwise need explicit imports of
|
||||
their sub-packages. For example, the suversion bindings
|
||||
require you to do something like::
|
||||
|
||||
import svn.client
|
||||
|
||||
If you just do the naive thing with the py lib, i.e. write
|
||||
``py.std.svn.client`` it will not work unless you previously
|
||||
imported it already. The py lib currently doesn't try to
|
||||
magically make this work. The :api:`py.std` hook really is
|
||||
intended for Python standard modules which very seldomly (if
|
||||
at all) provide such nested packages.
|
||||
|
||||
**Note that you may never rely** on module identity, i.e.
|
||||
that ``X is py.std.X`` for any ``X``. This is to allow
|
||||
us later to lazyly import nested packages. Yes, lazyness
|
||||
is hard to resist :-)
|
||||
|
||||
Note: you get an AttributeError, not an ImportError
|
||||
---------------------------------------------------
|
||||
|
||||
If you say ``py.std.XYZ`` and importing ``XYZ`` produces an
|
||||
``ImportError`` , it will actually show up as an
|
||||
``AttributeError``. It is deemed more important to adhere to
|
||||
the standard ``__getattr__`` protocol than to let the
|
||||
``ImportError`` pass through. For example, you might want to
|
||||
do::
|
||||
|
||||
getattr(py.std.cStringIO, 'StringIO', py.std.StringIO.StringIO)
|
||||
|
||||
and you would expect that it works. It does work although it will
|
||||
take away some lazyness because ``py.std.StringIO.StringIO`` will
|
||||
be imported in any case.
|
||||
|
||||
.. _`the relative/absolute import PEP-328`: http://www.python.org/peps/pep-0328.html
|
||||
|
||||
Support for interaction with system utilities/binaries
|
||||
======================================================
|
||||
|
||||
sources:
|
||||
|
||||
* :source:`py/process/`
|
||||
* :source:`py/path/local/`
|
||||
|
||||
Currently, the py lib offers two ways to interact with
|
||||
system executables. :api:`py.process.cmdexec()` invokes
|
||||
the shell in order to execute a string. The other
|
||||
one, :api:`py.path.local`'s 'sysexec()' method lets you
|
||||
directly execute a binary.
|
||||
|
||||
Both approaches will raise an exception in case of a return-
|
||||
code other than 0 and otherwise return the stdout-output
|
||||
of the child process.
|
||||
|
||||
The shell based approach
|
||||
------------------------
|
||||
|
||||
You can execute a command via your system shell
|
||||
by doing something like::
|
||||
|
||||
out = py.process.cmdexec('ls -v')
|
||||
|
||||
However, the ``cmdexec`` approach has a few shortcomings:
|
||||
|
||||
- it relies on the underlying system shell
|
||||
- it neccessitates shell-escaping for expressing arguments
|
||||
- it does not easily allow to "fix" the binary you want to run.
|
||||
- it only allows to execute executables from the local
|
||||
filesystem
|
||||
|
||||
.. _sysexec:
|
||||
|
||||
local paths have ``sysexec``
|
||||
----------------------------
|
||||
|
||||
The py lib currently offers a stripped down functionality of what
|
||||
the new `PEP-324 subprocess module`_ offers. The main functionality
|
||||
of synchronously executing a system executable has a straightforward API::
|
||||
|
||||
binsvn.sysexec('ls', 'http://codespeak.net/svn')
|
||||
|
||||
where ``binsvn`` is a path that points to the ``svn`` commandline
|
||||
binary. Note that this function would not offer any shell-escaping
|
||||
so you really have to pass in separated arguments. This idea
|
||||
fits nicely into `a more general view on path objects`_.
|
||||
|
||||
For a first go, we are just reusing the existing `subprocess
|
||||
implementation`_ but don't expose any of its API apart
|
||||
from the above ``sysexec()`` method.
|
||||
|
||||
Note, however, that currently the support for the ``sysexec`` interface on
|
||||
win32 is not thoroughly tested. If you run into problems with it, we are
|
||||
interested to hear about them. If you are running a Python older than 2.4 you
|
||||
will have to install the `pywin32 package`_.
|
||||
|
||||
|
||||
.. _`future book`: future.html
|
||||
.. _`PEP-324 subprocess module`: http://www.python.org/peps/pep-0324.html
|
||||
.. _`subprocess implementation`: http://www.lysator.liu.se/~astrand/popen5/
|
||||
.. _`a more general view on path objects`: future.html#general-path
|
||||
.. _`pywin32 package`: http://pywin32.sourceforge.net/
|
||||
|
||||
finding an executable local path
|
||||
--------------------------------
|
||||
|
||||
Finding an executable is quite different on multiple platforms.
|
||||
Currently, the ``PATH`` environment variable based search on
|
||||
unix platforms is supported::
|
||||
|
||||
py.path.local.sysfind('svn')
|
||||
|
||||
which returns the first path whose ``basename`` matches ``svn``.
|
||||
In principle, `sysfind` deploys platform specific algorithms
|
||||
to perform the search. On Windows, for example, it may look
|
||||
at the registry (XXX).
|
||||
|
||||
To make the story complete, we allow to pass in a second ``checker``
|
||||
argument that is called for each found executable. For example, if
|
||||
you have multiple binaries available you may want to select the
|
||||
right version::
|
||||
|
||||
def mysvn(p):
|
||||
""" check that the given svn binary has version 1.1. """
|
||||
line = p.execute('--version'').readlines()[0]
|
||||
if line.find('version 1.1'):
|
||||
return p
|
||||
binsvn = py.path.local.sysfind('svn', checker=mysvn)
|
||||
|
||||
|
||||
|
||||
Cross-Python Version compatibility helpers
|
||||
=============================================
|
||||
|
||||
sources:
|
||||
|
||||
* :source:`py/compat/`
|
||||
* :source:`py/builtin/`
|
||||
|
||||
The compat and builtin namespaces help to write code using newer python features on older python interpreters.
|
||||
|
||||
:api:`py.compat`
|
||||
----------------
|
||||
|
||||
:api:`py.compat` provides fixed versions (currently taken from Python 2.4.4) of
|
||||
a few selected modules to be able to use them across python versions. Currently these are:
|
||||
|
||||
* doctest
|
||||
* optparse
|
||||
* subprocess
|
||||
* textwrap
|
||||
|
||||
Note that for example ``import doctest`` and ``from py.compat import doctest`` result
|
||||
into two different module objects no matter what Python version you are using.
|
||||
So you should only use exactly one of these to avoid confusion in your program.
|
||||
|
||||
:api:`py.builtin`
|
||||
-----------------
|
||||
|
||||
:api:`py.builtin` provides builtin functions/types that were added in later Python
|
||||
versions. If the used Python version used does not provide these builtins the
|
||||
py lib provides some reimplementations. These currently are:
|
||||
|
||||
* enumerate
|
||||
* reversed
|
||||
* sorted
|
||||
* BaseException
|
||||
* set and frozenset (using either the builtin, if available, or the sets
|
||||
module)
|
||||
|
||||
:api:`py.builtin.BaseException` is just ``Exception`` before Python 2.5.
|
|
@ -0,0 +1,260 @@
|
|||
=======
|
||||
py.path
|
||||
=======
|
||||
|
||||
|
||||
The 'py' lib provides a uniform high-level api to deal with filesystems
|
||||
and filesystem-like interfaces: :api:`py.path`. It aims to offer a central
|
||||
object to fs-like object trees (reading from and writing to files, adding
|
||||
files/directories, examining the types and structure, etc.), and out-of-the-box
|
||||
provides a number of implementations of this API.
|
||||
|
||||
Path implementations provided by :api:`py.path`
|
||||
===============================================
|
||||
|
||||
:api:`py.path.local`
|
||||
--------------------
|
||||
|
||||
The first and most obvious of the implementations is a wrapper around a local
|
||||
filesystem. It's just a bit nicer in usage than the regular Python APIs, and
|
||||
of course all the functionality is bundled together rather than spread over a
|
||||
number of modules.
|
||||
|
||||
Example usage, here we use the :api:`py.test.ensuretemp()` function to create
|
||||
a :api:`py.path.local` object for us (which wraps a directory)::
|
||||
|
||||
>>> import py
|
||||
>>> temppath = py.test.ensuretemp('py.path_documentation')
|
||||
>>> foopath = temppath.join('foo') # get child 'foo' (lazily)
|
||||
>>> foopath.check() # check if child 'foo' exists
|
||||
False
|
||||
>>> foopath.write('bar') # write some data to it
|
||||
>>> foopath.check()
|
||||
True
|
||||
>>> foopath.read()
|
||||
'bar'
|
||||
>>> foofile = foopath.open() # return a 'real' file object
|
||||
>>> foofile.read(1)
|
||||
'b'
|
||||
|
||||
:api:`py.path.svnurl` and :api:`py.path.svnwc`
|
||||
----------------------------------------------
|
||||
|
||||
Two other :api:`py.path` implementations that the py lib provides wrap the
|
||||
popular `Subversion`_ revision control system: the first (called 'svnurl')
|
||||
by interfacing with a remote server, the second by wrapping a local checkout.
|
||||
Both allow you to access relatively advanced features such as metadata and
|
||||
versioning, and both in a way more user-friendly manner than existing other
|
||||
solutions.
|
||||
|
||||
Some example usage of :api:`py.path.svnurl`::
|
||||
|
||||
.. >>> import py
|
||||
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> url = py.path.svnurl('http://codespeak.net/svn/py')
|
||||
>>> info = url.info()
|
||||
>>> info.kind
|
||||
'dir'
|
||||
>>> firstentry = url.log()[-1]
|
||||
>>> import time
|
||||
>>> time.strftime('%Y-%m-%d', time.gmtime(firstentry.date))
|
||||
'2004-10-02'
|
||||
|
||||
Example usage of :api:`py.path.svnwc`::
|
||||
|
||||
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> temp = py.test.ensuretemp('py.path_documentation')
|
||||
>>> wc = py.path.svnwc(temp.join('svnwc'))
|
||||
>>> wc.checkout('http://codespeak.net/svn/py/dist/py/path/local')
|
||||
>>> wc.join('local.py').check()
|
||||
True
|
||||
|
||||
.. _`Subversion`: http://subversion.tigris.org/
|
||||
|
||||
Common vs. specific API
|
||||
=======================
|
||||
|
||||
All Path objects support a common set of operations, suitable
|
||||
for many use cases and allowing to transparently switch the
|
||||
path object within an application (e.g. from "local" to "svnwc").
|
||||
The common set includes functions such as `path.read()` to read all data
|
||||
from a file, `path.write()` to write data, `path.listdir()` to get a list
|
||||
of directory entries, `path.check()` to check if a node exists
|
||||
and is of a particular type, `path.join()` to get
|
||||
to a (grand)child, `path.visit()` to recursively walk through a node's
|
||||
children, etc. Only things that are not common on 'normal' filesystems (yet),
|
||||
such as handling metadata (e.g. the Subversion "properties") require
|
||||
using specific APIs.
|
||||
|
||||
Examples
|
||||
---------------------------------
|
||||
|
||||
A quick 'cookbook' of small examples that will be useful 'in real life',
|
||||
which also presents parts of the 'common' API, and shows some non-common
|
||||
methods:
|
||||
|
||||
Searching `.txt` files
|
||||
..........................
|
||||
|
||||
Search for a particular string inside all files with a .txt extension in a
|
||||
specific directory.
|
||||
|
||||
::
|
||||
|
||||
>>> dirpath = temppath.ensure('testdir', dir=True)
|
||||
>>> dirpath.join('textfile1.txt').write('foo bar baz')
|
||||
>>> dirpath.join('textfile2.txt').write('frob bar spam eggs')
|
||||
>>> subdir = dirpath.ensure('subdir', dir=True)
|
||||
>>> subdir.join('textfile1.txt').write('foo baz')
|
||||
>>> subdir.join('textfile2.txt').write('spam eggs spam foo bar spam')
|
||||
>>> results = []
|
||||
>>> for fpath in dirpath.visit('*.txt'):
|
||||
... if 'bar' in fpath.read():
|
||||
... results.append(fpath.basename)
|
||||
>>> results.sort()
|
||||
>>> results
|
||||
['textfile1.txt', 'textfile2.txt', 'textfile2.txt']
|
||||
|
||||
Working with Paths
|
||||
.......................
|
||||
|
||||
This example shows the :api:`py.path` features to deal with
|
||||
filesystem paths Note that the filesystem is never touched,
|
||||
all operations are performed on a string level (so the paths
|
||||
don't have to exist, either)::
|
||||
|
||||
>>> p1 = py.path.local('/foo/bar')
|
||||
>>> p2 = p1.join('baz/qux')
|
||||
>>> p2 == py.path.local('/foo/bar/baz/qux')
|
||||
True
|
||||
>>> sep = py.path.local.sep
|
||||
>>> p2.relto(p1).replace(sep, '/') # os-specific path sep in the string
|
||||
'baz/qux'
|
||||
>>> p2.bestrelpath(p1).replace(sep, '/')
|
||||
'../..'
|
||||
>>> p2.join(p2.bestrelpath(p1)) == p1
|
||||
True
|
||||
>>> p3 = p1 / 'baz/qux' # the / operator allows joining, too
|
||||
>>> p2 == p3
|
||||
True
|
||||
>>> p4 = p1 + ".py"
|
||||
>>> p4.basename == "bar.py"
|
||||
True
|
||||
>>> p4.ext == ".py"
|
||||
True
|
||||
>>> p4.purebasename == "bar"
|
||||
True
|
||||
|
||||
This should be possible on every implementation of :api:`py.path`, so
|
||||
regardless of whether the implementation wraps a UNIX filesystem, a Windows
|
||||
one, or a database or object tree, these functions should be available (each
|
||||
with their own notion of path seperators and dealing with conversions, etc.).
|
||||
|
||||
Checking path types
|
||||
.......................
|
||||
|
||||
Now we will show a bit about the powerful 'check()' method on paths, which
|
||||
allows you to check whether a file exists, what type it is, etc.::
|
||||
|
||||
>>> file1 = temppath.join('file1')
|
||||
>>> file1.check() # does it exist?
|
||||
False
|
||||
>>> file1 = file1.ensure(file=True) # 'touch' the file
|
||||
>>> file1.check()
|
||||
True
|
||||
>>> file1.check(dir=True) # is it a dir?
|
||||
False
|
||||
>>> file1.check(file=True) # or a file?
|
||||
True
|
||||
>>> file1.check(ext='.txt') # check the extension
|
||||
False
|
||||
>>> textfile = temppath.ensure('text.txt', file=True)
|
||||
>>> textfile.check(ext='.txt')
|
||||
True
|
||||
>>> file1.check(basename='file1') # we can use all the path's properties here
|
||||
True
|
||||
|
||||
Setting svn-properties
|
||||
.......................
|
||||
|
||||
As an example of 'uncommon' methods, we'll show how to read and write
|
||||
properties in an :api:`py.path.svnwc` instance::
|
||||
|
||||
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> wc.propget('foo')
|
||||
''
|
||||
>>> wc.propset('foo', 'bar')
|
||||
>>> wc.propget('foo')
|
||||
'bar'
|
||||
>>> len(wc.status().prop_modified) # our own props
|
||||
1
|
||||
>>> msg = wc.revert() # roll back our changes
|
||||
>>> len(wc.status().prop_modified)
|
||||
0
|
||||
|
||||
SVN authentication
|
||||
.......................
|
||||
|
||||
Some uncommon functionality can also be provided as extensions, such as SVN
|
||||
authentication::
|
||||
|
||||
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> auth = py.path.SvnAuth('anonymous', 'user', cache_auth=False,
|
||||
... interactive=False)
|
||||
>>> wc.auth = auth
|
||||
>>> wc.update() # this should work
|
||||
>>> path = wc.ensure('thisshouldnotexist.txt')
|
||||
>>> try:
|
||||
... path.commit('testing')
|
||||
... except py.process.cmdexec.Error, e:
|
||||
... pass
|
||||
>>> 'authorization failed' in str(e)
|
||||
True
|
||||
|
||||
Known problems / limitations
|
||||
===================================
|
||||
|
||||
* The SVN path objects require the "svn" command line,
|
||||
there is currently no support for python bindings.
|
||||
Parsing the svn output can lead to problems, particularly
|
||||
regarding if you have a non-english "locales" setting.
|
||||
|
||||
* While the path objects basically work on windows,
|
||||
there is no attention yet on making unicode paths
|
||||
work or deal with the famous "8.3" filename issues.
|
||||
|
||||
Future plans
|
||||
============
|
||||
|
||||
The Subversion path implementations are based
|
||||
on the `svn` command line, not on the bindings.
|
||||
It makes sense now to directly use the bindings.
|
||||
|
||||
Moreover, it would be good, also considering
|
||||
`py.execnet`_ distribution of programs, to
|
||||
be able to manipulate Windows Paths on Linux
|
||||
and vice versa. So we'd like to consider
|
||||
refactoring the path implementations
|
||||
to provide this choice (and getting rid
|
||||
of platform-dependencies as much as possible).
|
||||
|
||||
There is some experimental small approach
|
||||
(:source:`py/path/gateway/`) aiming at having
|
||||
a convenient Remote Path implementation
|
||||
and some considerations about future
|
||||
works in the according :source:`py/path/gateway/TODO.txt`
|
||||
|
||||
There are various hacks out there to have
|
||||
Memory-Filesystems and even path objects
|
||||
being directly mountable under Linux (via `fuse`).
|
||||
However, the Path object implementations
|
||||
do not internally have a clean abstraction
|
||||
of going to the filesystem - so with some
|
||||
refactoring it should become easier to
|
||||
have very custom Path objects, still offering
|
||||
the quite full interface without requiring
|
||||
to know about all details of the full path
|
||||
implementation.
|
||||
|
||||
.. _`py.execnet`: execnet.html
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
py lib 1.0.0: XXX
|
||||
======================================================================
|
||||
|
||||
Welcome to the 1.0.0 py lib release - a library aiming to
|
||||
support agile and test-driven python development on various levels.
|
||||
|
||||
XXX
|
|
@ -0,0 +1,27 @@
|
|||
py lib 0.9.2: bugfix release
|
||||
=============================
|
||||
|
||||
Welcome to the 0.9.2 py lib and py.test release -
|
||||
mainly fixing Windows issues, providing better
|
||||
packaging and integration with setuptools.
|
||||
|
||||
Here is a quick summary of what the py lib provides:
|
||||
|
||||
* py.test: cross-project testing tool with many advanced features
|
||||
* py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes
|
||||
* py.magic.greenlet: micro-threads on standard CPython ("stackless-light")
|
||||
* py.path: path abstractions over local and subversion files
|
||||
* rich documentation of py's exported API
|
||||
* tested against Linux, Win32, OSX, works on python 2.3-2.6
|
||||
|
||||
See here for more information:
|
||||
|
||||
Pypi pages: http://pypi.python.org/pypi/py/
|
||||
|
||||
Download/Install: http://codespeak.net/py/0.9.2/download.html
|
||||
|
||||
Documentation/API: http://codespeak.net/py/0.9.2/index.html
|
||||
|
||||
best and have fun,
|
||||
|
||||
holger krekel
|
|
@ -0,0 +1,31 @@
|
|||
py lib 0.9.0: py.test, distributed execution, greenlets and more
|
||||
======================================================================
|
||||
|
||||
Welcome to the 0.9.0 py lib release - a library aiming to
|
||||
support agile and test-driven python development on various levels.
|
||||
|
||||
Main API/Tool Features:
|
||||
|
||||
* py.test: cross-project testing tool with many advanced features
|
||||
* py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes
|
||||
* py.magic.greenlet: micro-threads on standard CPython ("stackless-light")
|
||||
* py.path: path abstractions over local and subversion files
|
||||
* rich documentation of py's exported API
|
||||
* tested against Linux, OSX and partly against Win32, python 2.3-2.5
|
||||
|
||||
All these features and their API have extensive documentation,
|
||||
generated with the new "apigen", which we intend to make accessible
|
||||
for other python projects as well.
|
||||
|
||||
Download/Install: http://codespeak.net/py/0.9.0/download.html
|
||||
Documentation/API: http://codespeak.net/py/0.9.0/index.html
|
||||
|
||||
Work on the py lib has been partially funded by the
|
||||
European Union IST programme and by http://merlinux.de
|
||||
within the PyPy project.
|
||||
|
||||
best, have fun and let us know what you think!
|
||||
|
||||
holger krekel, Maciej Fijalkowski,
|
||||
Guido Wesdorp, Carl Friedrich Bolz
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
=============
|
||||
Release notes
|
||||
=============
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
release-1.0.0
|
||||
release-0.9.2
|
||||
release-0.9.0
|
|
@ -0,0 +1,23 @@
|
|||
Test configuration
|
||||
========================
|
||||
|
||||
test options and values
|
||||
-----------------------------
|
||||
|
||||
You can see all available command line options by running::
|
||||
|
||||
py.test -h
|
||||
|
||||
py.test will lookup values of options in this order:
|
||||
|
||||
* option value supplied at command line
|
||||
* content of environment variable ``PYTEST_OPTION_NAME=...``
|
||||
* ``name = ...`` setting in the nearest ``conftest.py`` file.
|
||||
|
||||
The name of an option usually is the one you find
|
||||
in the longform of the option, i.e. the name
|
||||
behind the ``--`` double-dash.
|
||||
|
||||
IOW, you can set default values for options per project, per
|
||||
home-directoray, per shell session or per test-run.
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
.. _`distribute tests across machines`:
|
||||
|
||||
===================
|
||||
Distributed testing
|
||||
===================
|
||||
|
||||
``py.test`` can ad-hoc distribute test runs to multiple CPUs or remote
|
||||
machines. This allows to speed up development or to use special resources
|
||||
of remote machines. Before running tests remotely, ``py.test`` efficiently
|
||||
synchronizes your program source code to the remote place. All test results
|
||||
are reported back and displayed to your local test session. You may
|
||||
specify different Python versions and interpreters.
|
||||
|
||||
Synchronisation and running of tests only requires
|
||||
a bare Python installation on the remote side. No
|
||||
special software is installed - this is realized
|
||||
by use of the **zero installation** `py.execnet`_ mechanisms.
|
||||
|
||||
Speed up test runs by sending tests to multiple CPUs
|
||||
----------------------------------------------------------
|
||||
|
||||
To send tests to multiple CPUs, type::
|
||||
|
||||
py.test -n NUM
|
||||
|
||||
Especially for longer running tests or tests requiring
|
||||
a lot of IO this can lead to considerable speed ups.
|
||||
|
||||
|
||||
Running tests in a Python subprocess
|
||||
----------------------------------------
|
||||
|
||||
To instantiate a python2.4 sub process and send tests to it, you may type::
|
||||
|
||||
py.test -d --tx popen//python=python2.4
|
||||
|
||||
This will start a subprocess which is run with the "python2.4"
|
||||
Python interpreter, found in your system binary lookup path.
|
||||
|
||||
If you prefix the --tx option value like this::
|
||||
|
||||
--tx 3*popen//python=python2.4
|
||||
|
||||
then three subprocesses would be created and tests
|
||||
will be load-balanced across these three processes.
|
||||
|
||||
|
||||
Sending tests to remote SSH accounts
|
||||
-----------------------------------------------
|
||||
|
||||
Suppose you have a package ``mypkg`` which contains some
|
||||
tests that you can successfully run locally. And you
|
||||
have a ssh-reachable machine ``myhost``. Then
|
||||
you can ad-hoc distribute your tests by typing::
|
||||
|
||||
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||
|
||||
This will synchronize your ``mypkg`` package directory
|
||||
to an remote ssh account and then locally collect tests
|
||||
and send them to remote places for execution.
|
||||
|
||||
You can specify multiple ``--rsyncdir`` directories
|
||||
to be sent to the remote side.
|
||||
|
||||
|
||||
Sending tests to remote Socket Servers
|
||||
----------------------------------------
|
||||
|
||||
Download the single-module `socketserver.py`_ Python program
|
||||
and run it like this::
|
||||
|
||||
python socketserver.py
|
||||
|
||||
It will tell you that it starts listening on the default
|
||||
port. You can now on your home machine specify this
|
||||
new socket host with something like this::
|
||||
|
||||
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||
|
||||
|
||||
.. _`atonce`:
|
||||
|
||||
Running tests on many platforms at once
|
||||
-------------------------------------------------------------
|
||||
|
||||
The basic command to run tests on multiple platforms is::
|
||||
|
||||
py.test --dist=each --tx=spec1 --tx=spec2
|
||||
|
||||
If you specify a windows host, an OSX host and a Linux
|
||||
environment this command will send each tests to all
|
||||
platforms - and report back failures from all platforms
|
||||
at once. The provided specifications strings
|
||||
use the `xspec syntax`_.
|
||||
|
||||
.. _`xspec syntax`: execnet.html#xspec
|
||||
|
||||
.. _`socketserver.py`: http://codespeak.net/svn/py/dist/py/execnet/script/socketserver.py
|
||||
.. _`py.execnet`: execnet.html
|
||||
|
||||
Specifying test exec environments in a conftest.py
|
||||
-------------------------------------------------------------
|
||||
|
||||
Instead of specifying command line options, you can
|
||||
put options values in a ``conftest.py`` file like this::
|
||||
|
||||
pytest_option_tx = ['ssh=myhost//python=python2.5', 'popen//python=python2.5']
|
||||
pytest_option_dist = True
|
||||
|
||||
Any commandline ``--tx`` specifictions will add to the list of available execution
|
||||
environments.
|
||||
|
||||
Specifying "rsync" dirs in a conftest.py
|
||||
-------------------------------------------------------------
|
||||
|
||||
In your ``mypkg/conftest.py`` you may specify directories to synchronise
|
||||
or to exclude::
|
||||
|
||||
rsyncdirs = ['.', '../plugins']
|
||||
rsyncignore = ['_cache']
|
||||
|
||||
These directory specifications are relative to the directory
|
||||
where the ``conftest.py`` is found.
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
Working Examples
|
||||
================
|
||||
|
||||
managing state at module, class and method level
|
||||
------------------------------------------------------------
|
||||
|
||||
Here is a working example for what goes on when you setup modules,
|
||||
classes and methods::
|
||||
|
||||
# [[from py/documentation/example/pytest/test_setup_flow_example.py]]
|
||||
|
||||
def setup_module(module):
|
||||
module.TestStateFullThing.classcount = 0
|
||||
|
||||
class TestStateFullThing:
|
||||
def setup_class(cls):
|
||||
cls.classcount += 1
|
||||
|
||||
def teardown_class(cls):
|
||||
cls.classcount -= 1
|
||||
|
||||
def setup_method(self, method):
|
||||
self.id = eval(method.func_name[5:])
|
||||
|
||||
def test_42(self):
|
||||
assert self.classcount == 1
|
||||
assert self.id == 42
|
||||
|
||||
def test_23(self):
|
||||
assert self.classcount == 1
|
||||
assert self.id == 23
|
||||
|
||||
def teardown_module(module):
|
||||
assert module.TestStateFullThing.classcount == 0
|
||||
|
||||
For this example the control flow happens as follows::
|
||||
|
||||
import test_setup_flow_example
|
||||
setup_module(test_setup_flow_example)
|
||||
setup_class(TestStateFullThing)
|
||||
instance = TestStateFullThing()
|
||||
setup_method(instance, instance.test_42)
|
||||
instance.test_42()
|
||||
setup_method(instance, instance.test_23)
|
||||
instance.test_23()
|
||||
teardown_class(TestStateFullThing)
|
||||
teardown_module(test_setup_flow_example)
|
||||
|
||||
Note that ``setup_class(TestStateFullThing)`` is called and not
|
||||
``TestStateFullThing.setup_class()`` which would require you
|
||||
to insert ``setup_class = classmethod(setup_class)`` to make
|
||||
your setup function callable. Did we mention that lazyness
|
||||
is a virtue?
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
===============
|
||||
Writing plugins
|
||||
===============
|
||||
|
||||
Learning by examples
|
||||
=====================
|
||||
|
||||
XXX
|
||||
|
||||
adding custom options
|
||||
----------------------
|
||||
|
||||
py.test supports adding of standard optparse_ Options.
|
||||
A plugin may implement the ``addoption`` hook for registering
|
||||
custom options::
|
||||
|
||||
class ConftestPlugin:
|
||||
def pytest_addoption(self, parser):
|
||||
parser.addoption("-M", "--myopt", action="store",
|
||||
help="specify string to set myopt")
|
||||
|
||||
def pytest_configure(self, config):
|
||||
if config.option.myopt:
|
||||
# do action based on option value
|
||||
|
||||
.. _optparse: http://docs.python.org/library/optparse.html
|
||||
|
||||
Setting default values for test options
|
||||
=======================================
|
||||
|
||||
You can see all available command line options by running::
|
||||
|
||||
py.test -h
|
||||
|
||||
py.test will lookup values of options in this order:
|
||||
|
||||
* option value supplied at command line
|
||||
* content of environment variable ``PYTEST_OPTION_NAME=...``
|
||||
* ``name = ...`` setting in the nearest ``conftest.py`` file.
|
||||
|
||||
The name of an option usually is the one you find
|
||||
in the longform of the option, i.e. the name
|
||||
behind the ``--`` double-dash.
|
||||
|
||||
IOW, you can set default values for options per project, per
|
||||
home-directoray, per shell session or per test-run.
|
||||
|
||||
|
||||
|
||||
Plugin methods
|
||||
=======================================
|
||||
|
||||
A Plugin class may implement the following attributes and methods:
|
||||
|
||||
XXX
|
||||
|
||||
_`pytest event`:
|
||||
|
||||
Pytest Events
|
||||
=======================================
|
||||
|
||||
XXX
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
==================================================
|
||||
Features
|
||||
==================================================
|
||||
|
||||
py.test is a standalone-tool that collects and runs tests for
|
||||
your Python application and modules. py.test works across
|
||||
linux, windows and osx and on Python 2.3 - Python 2.6.
|
||||
|
||||
It aims to support *unit-tests* and *functional tests* written
|
||||
in Python and is used in projects that run more than 10000
|
||||
tests regularly.
|
||||
|
||||
py.test presents a clean and powerful command line interface
|
||||
and strives to generally make testing a fun effort.
|
||||
|
||||
automatically collects and executes tests
|
||||
===============================================
|
||||
|
||||
py.test discovers tests automatically by inspect specified
|
||||
directories or files. By default, it collects all python
|
||||
modules a leading ``test_`` or trailing ``_test`` filename.
|
||||
From each test module every function with a leading ``test_``
|
||||
or class with a leading ``Test`` name is collected.
|
||||
|
||||
.. _`generative tests`:
|
||||
.. _`collection process`: impl-test.html#collection-process
|
||||
|
||||
load-balance tests to multiple CPUs
|
||||
===================================
|
||||
|
||||
For large test suites you can distribute your
|
||||
tests to multiple CPUs by issuing for example::
|
||||
|
||||
py.test -n 3
|
||||
|
||||
Read more on `distributed testing`_.
|
||||
|
||||
.. _`distributed testing`: test-dist.html
|
||||
|
||||
Distribute tests across machines
|
||||
===================================
|
||||
|
||||
py.test supports the sending of tests to
|
||||
remote ssh-accounts or socket servers.
|
||||
It can `ad-hoc run your test on multiple
|
||||
platforms one a single test run`. Ad-hoc
|
||||
means that there are **no installation
|
||||
requirements whatsoever** on the remote side.
|
||||
|
||||
.. _`ad-hoc run your test on multiple platforms one a single test run`: test-dist.html#atonce
|
||||
|
||||
extensive debugging support
|
||||
===================================
|
||||
|
||||
testing starts immediately
|
||||
--------------------------
|
||||
|
||||
Testing starts as soon as the first ``test item``
|
||||
is collected. The collection process is iterative
|
||||
and does not need to complete before your first
|
||||
test items are executed.
|
||||
|
||||
support for modules containing tests
|
||||
--------------------------------------
|
||||
|
||||
As ``py.test`` operates as a separate cmdline
|
||||
tool you can easily have a command line utility and
|
||||
some tests in the same file.
|
||||
|
||||
debug with the ``print`` statement
|
||||
----------------------------------
|
||||
|
||||
By default, ``py.test`` catches text written to stdout/stderr during
|
||||
the execution of each individual test. This output will only be
|
||||
displayed however if the test fails; you will not see it
|
||||
otherwise. This allows you to put debugging print statements in your
|
||||
code without being overwhelmed by all the output that might be
|
||||
generated by tests that do not fail.
|
||||
|
||||
Each failing test that produced output during the running of the test
|
||||
will have its output displayed in the ``recorded stdout`` section.
|
||||
|
||||
The catching of stdout/stderr output can be disabled using the
|
||||
``--nocapture`` option to the ``py.test`` tool. Any output will
|
||||
in this case be displayed as soon as it is generated.
|
||||
|
||||
test execution order
|
||||
--------------------------------
|
||||
|
||||
Tests usually run in the order in which they appear in the files.
|
||||
However, tests should not rely on running one after another, as
|
||||
this prevents more advanced usages: running tests
|
||||
distributedly or selectively, or in "looponfailing" mode,
|
||||
will cause them to run in random order.
|
||||
|
||||
assert with the ``assert`` statement
|
||||
----------------------------------------
|
||||
|
||||
``py.test`` allows to use the standard python
|
||||
``assert statement`` for verifying expectations
|
||||
and values in Python tests. For example, you can
|
||||
write the following in your tests::
|
||||
|
||||
assert hasattr(x, 'attribute')
|
||||
|
||||
to state that your object has a certain ``attribute``. In case this
|
||||
assertion fails you will see the value of ``x``. Intermediate
|
||||
values are computed by executing the assert expression a second time.
|
||||
If you execute code with side effects, e.g. read from a file like this::
|
||||
|
||||
assert f.read() != '...'
|
||||
|
||||
then you may get a warning from pytest if that assertions
|
||||
first failed and then succeeded.
|
||||
|
||||
asserting expected exceptions
|
||||
----------------------------------------
|
||||
|
||||
In order to write assertions about exceptions, you use
|
||||
one of two forms::
|
||||
|
||||
py.test.raises(Exception, func, *args, **kwargs)
|
||||
py.test.raises(Exception, "func(*args, **kwargs)")
|
||||
|
||||
both of which execute the given function with args and kwargs and
|
||||
asserts that the given ``Exception`` is raised. The reporter will
|
||||
provide you with helpful output in case of failures such as *no
|
||||
exception* or *wrong exception*.
|
||||
|
||||
useful tracebacks, recursion detection
|
||||
--------------------------------------
|
||||
|
||||
A lot of care is taken to present nice tracebacks in case of test
|
||||
failure. Try::
|
||||
|
||||
py.test py/doc/example/pytest/failure_demo.py
|
||||
|
||||
to see a variety of tracebacks, each representing a different
|
||||
failure situation.
|
||||
|
||||
``py.test`` uses the same order for presenting tracebacks as Python
|
||||
itself: the oldest function call is shown first, and the most recent call is
|
||||
shown last. A ``py.test`` reported traceback starts with your
|
||||
failing test function. If the maximum recursion depth has been
|
||||
exceeded during the running of a test, for instance because of
|
||||
infinite recursion, ``py.test`` will indicate where in the
|
||||
code the recursion was taking place. You can inhibit
|
||||
traceback "cutting" magic by supplying ``--fulltrace``.
|
||||
|
||||
There is also the possibility of using ``--tb=short`` to get regular CPython
|
||||
tracebacks. Or you can use ``--tb=no`` to not show any tracebacks at all.
|
||||
|
||||
no inheritance requirement
|
||||
--------------------------
|
||||
|
||||
Test classes are recognized by their leading ``Test`` name. Unlike
|
||||
``unitest.py``, you don't need to inherit from some base class to make
|
||||
them be found by the test runner. Besides being easier, it also allows
|
||||
you to write test classes that subclass from application level
|
||||
classes.
|
||||
|
||||
testing for deprecated APIs
|
||||
------------------------------
|
||||
|
||||
In your tests you can use ``py.test.deprecated_call(func, *args, **kwargs)``
|
||||
to test that a particular function call triggers a DeprecationWarning.
|
||||
This is useful for testing phasing out of old APIs in your projects.
|
||||
|
||||
|
||||
advanced test selection / skipping
|
||||
=========================================================
|
||||
|
||||
dynamically skipping tests
|
||||
-------------------------------
|
||||
|
||||
If you want to skip tests you can use ``py.test.skip`` within
|
||||
test or setup functions. Example::
|
||||
|
||||
py.test.skip("message")
|
||||
|
||||
You can also use a helper to skip on a failing import::
|
||||
|
||||
docutils = py.test.importorskip("docutils")
|
||||
|
||||
or to skip if a library does not have the right version::
|
||||
|
||||
docutils = py.test.importorskip("docutils", minversion="0.3")
|
||||
|
||||
The version will be read from the module's ``__version__`` attribute.
|
||||
|
||||
.. _`selection by keyword`:
|
||||
|
||||
selecting/unselecting tests by keyword
|
||||
---------------------------------------------
|
||||
|
||||
Pytest's keyword mechanism provides a powerful way to
|
||||
group and selectively run tests in your test code base.
|
||||
You can selectively run tests by specifiying a keyword
|
||||
on the command line. Examples::
|
||||
|
||||
py.test -k test_simple
|
||||
py.test -k "-test_simple"
|
||||
|
||||
will run all tests matching (or not matching) the
|
||||
"test_simple" keyword. Note that you need to quote
|
||||
the keyword if "-" is recognized as an indicator
|
||||
for a commandline option. Lastly, you may use::
|
||||
|
||||
py.test. -k "test_simple:"
|
||||
|
||||
which will run all tests after the expression has *matched once*, i.e.
|
||||
all tests that are seen after a test that matches the "test_simple"
|
||||
keyword.
|
||||
|
||||
By default, all filename parts and
|
||||
class/function names of a test function are put into the set
|
||||
of keywords for a given test. You may specify additional
|
||||
kewords like this::
|
||||
|
||||
@py.test.mark(webtest=True)
|
||||
def test_send_http():
|
||||
...
|
||||
|
||||
disabling a test class
|
||||
----------------------
|
||||
|
||||
If you want to disable a complete test class you
|
||||
can set the class-level attribute ``disabled``.
|
||||
For example, in order to avoid running some tests on Win32::
|
||||
|
||||
class TestPosixOnly:
|
||||
disabled = sys.platform == 'win32'
|
||||
|
||||
def test_xxx(self):
|
||||
...
|
||||
|
||||
generative tests: yielding parametrized tests
|
||||
====================================================
|
||||
|
||||
*Generative tests* are test methods that are *generator functions* which
|
||||
``yield`` callables and their arguments. This is most useful for running a
|
||||
test function multiple times against different parameters. Example::
|
||||
|
||||
def test_generative():
|
||||
for x in (42,17,49):
|
||||
yield check, x
|
||||
|
||||
def check(arg):
|
||||
assert arg % 7 == 0 # second generated tests fails!
|
||||
|
||||
Note that ``test_generative()`` will cause three tests
|
||||
to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
|
||||
of which the middle one will obviously fail.
|
||||
|
||||
To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
|
||||
|
||||
def test_generative():
|
||||
for x in (42,17,49):
|
||||
yield "case %d" % x, check, x
|
||||
|
||||
extensible plugin system
|
||||
=========================================
|
||||
|
||||
py.test itself consists of many plugins
|
||||
and you can easily write new `py.test plugins`_
|
||||
for these purposes:
|
||||
|
||||
* reporting extensions
|
||||
* customizing collection and run of tests
|
||||
* running non-python tests
|
||||
* managing test state setup
|
||||
|
||||
.. _`py.test plugins`: test-plugins.html
|
||||
|
||||
.. _`reStructured Text`: http://docutils.sourceforge.net
|
||||
.. _`Python debugger`: http://docs.python.org/lib/module-pdb.html
|
||||
|
||||
|
||||
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/
|
|
@ -0,0 +1,71 @@
|
|||
================
|
||||
Included plugins
|
||||
================
|
||||
|
||||
Many of py.test's features are implemented as a plugin.
|
||||
|
||||
Included plugins
|
||||
================
|
||||
|
||||
You can find the source code of all default plugins in
|
||||
http://codespeak.net/svn/py/trunk/py/test/plugin/
|
||||
|
||||
plugins that add reporting asepcts
|
||||
-----------------------------------
|
||||
|
||||
pytest_terminal: default reporter for writing info to terminals
|
||||
|
||||
pytest_resultlog: log test results in machine-readable form to a file
|
||||
|
||||
pytest_eventlog: log all internal pytest events to a file
|
||||
|
||||
plugins for adding new test types
|
||||
-----------------------------------
|
||||
|
||||
pytest_unittest: run traditional unittest TestCase instances
|
||||
|
||||
pytest_doctest: run doctests in python modules or .txt files
|
||||
|
||||
pytest_restdoc: provide RestructuredText syntax and link checking
|
||||
|
||||
plugins for python test functions
|
||||
-----------------------------------
|
||||
|
||||
pytest_xfail: provides "expected to fail" test marker
|
||||
|
||||
pytest_tmpdir: provide temporary directories to test functions
|
||||
|
||||
pytest_plugintester: generic plugin apichecks, support for functional plugin tests
|
||||
|
||||
pytest_apigen: tracing values of function/method calls when running tests
|
||||
|
||||
Loading plugins and specifying dependencies
|
||||
============================================
|
||||
|
||||
py.test loads and configures plugins at tool startup:
|
||||
|
||||
* by reading the ``PYTEST_PLUGINS`` environment variable
|
||||
and importing the comma-separated list of plugin names.
|
||||
|
||||
* by loading all plugins specified via one or more ``-p name``
|
||||
command line options.
|
||||
|
||||
* by loading all plugins specified via a ``pytest_plugins``
|
||||
variable in ``conftest.py`` files or test modules.
|
||||
|
||||
example: ensure a plugin is loaded
|
||||
-----------------------------------
|
||||
|
||||
If you create a ``conftest.py`` file with the following content::
|
||||
|
||||
pytest_plugins = "pytest_myextension",
|
||||
|
||||
then all tests in that directory and below it will run with
|
||||
an instantiated "pytest_myextension". Here is how instantiation
|
||||
takes place:
|
||||
|
||||
* the module ``pytest_extension`` will be imported and
|
||||
and its contained `ExtensionPlugin`` class will
|
||||
be instantiated. A plugin module may specify its
|
||||
dependencies via another ``pytest_plugins`` definition.
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
.. _`setuptools installation`: http://pypi.python.org/pypi/setuptools
|
||||
|
||||
|
||||
==================
|
||||
Quickstart
|
||||
==================
|
||||
|
||||
This document assumes basic python knowledge. If you have a
|
||||
`setuptools installation`_, install ``py.test`` by typing::
|
||||
|
||||
easy_install -U py
|
||||
|
||||
For alternative installation methods please see the download_ page.
|
||||
|
||||
You should now have a ``py.test`` command line tool and can
|
||||
look at its documented cmdline options via this command::
|
||||
|
||||
py.test -h
|
||||
|
||||
Writing and running a test
|
||||
==========================
|
||||
|
||||
``py.test`` is the command line tool to run tests.
|
||||
Let's write a first test module by putting the following
|
||||
test function into a ``test_sample.py`` file::
|
||||
|
||||
# content of test_sample.py
|
||||
def test_answer():
|
||||
assert 42 == 43
|
||||
|
||||
Now you can run the test by passing it as an argument::
|
||||
|
||||
py.test test_sample.py
|
||||
|
||||
What does happen here? ``py.test`` looks for functions and
|
||||
methods in the module that start with ``test_``. It then
|
||||
executes those tests. Assertions about test outcomes are
|
||||
done via the standard ``assert`` statement.
|
||||
|
||||
You can also use ``py.test`` to run all tests in a directory structure by
|
||||
invoking it without any arguments::
|
||||
|
||||
py.test
|
||||
|
||||
This will automatically collect and run any Python module whose filenames
|
||||
start with ``test_`` or ends with ``_test`` from the directory and any
|
||||
subdirectories, starting with the current directory, and run them. Each
|
||||
Python test module is inspected for test methods starting with ``test_``.
|
||||
|
||||
.. Organising your tests
|
||||
.. ---------------------------
|
||||
|
||||
Please refer to `features`_ for a walk through the basic features.
|
||||
|
||||
|
||||
.. _download: download.html
|
||||
.. _features: test-features.html
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
=======
|
||||
py.test
|
||||
=======
|
||||
|
||||
*py.test* is a tool for:
|
||||
|
||||
* rapidly writing unit- and functional tests in Python
|
||||
* writing tests for non-python code and data
|
||||
* receiving useful reports on test failures
|
||||
* distributing tests to multiple CPUs and remote environments
|
||||
|
||||
quickstart_: for getting started immediately.
|
||||
|
||||
features_: a walk through basic features and usage.
|
||||
|
||||
plugins_: using available plugins.
|
||||
|
||||
extend_: writing plugins and advanced configuration.
|
||||
|
||||
`distributed testing`_ how to distribute test runs to other machines and platforms.
|
||||
|
||||
.. _quickstart: test-quickstart.html
|
||||
.. _features: test-features.html
|
||||
.. _plugins: test-plugins.html
|
||||
.. _extend: test-ext.html
|
||||
.. _`distributed testing`: test-dist.html
|
||||
|
||||
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
test-quickstart
|
||||
test-features
|
||||
test-plugins
|
||||
test-ext
|
||||
test-dist
|
||||
test-config
|
||||
test-examples
|
||||
impl-test
|
|
@ -0,0 +1,182 @@
|
|||
==============================================
|
||||
Why, who, what and how do you do *the py lib*?
|
||||
==============================================
|
||||
|
||||
|
||||
Why did we start the py lib?
|
||||
============================
|
||||
|
||||
Among the main motivation for the py lib and its flagship
|
||||
py.test tool were:
|
||||
|
||||
- to test applications with a testing tool that provides
|
||||
advanced features out of the box, yet allows full customization
|
||||
per-project.
|
||||
|
||||
- distribute applications in an ad-hoc way both for testing
|
||||
and for application integration purposes.
|
||||
|
||||
- help with neutralizing platform and python version differences
|
||||
|
||||
- offer a uniform way to access local and remote file resources
|
||||
|
||||
- offer some unique features like micro-threads (greenlets)
|
||||
|
||||
|
||||
What is the py libs current focus?
|
||||
==================================
|
||||
|
||||
testing testing testing
|
||||
-----------------------
|
||||
|
||||
Currently, the main focus of the py lib is to get a decent
|
||||
`test environment`_, indeed to produce the best one out there.
|
||||
Writing, distributing and deploying tests should become
|
||||
a snap ... and fun!
|
||||
|
||||
On a side note: automated tests fit very well to the dynamism
|
||||
of Python. Automated tests ease development and allow fast
|
||||
refactoring cycles. Automated tests are a means of
|
||||
communication as well.
|
||||
|
||||
|
||||
ad-hoc distribution of programs
|
||||
------------------------------------
|
||||
|
||||
The py lib through its `py.execnet`_ namespaces offers
|
||||
support for ad-hoc distributing programs across
|
||||
a network and subprocesses. We'd like to generalize
|
||||
this approach further to instantiate and let whole
|
||||
ad-hoc networks communicate with each other while
|
||||
keeping to a simple programming model.
|
||||
|
||||
.. _`py.execnet`: execnet.html
|
||||
|
||||
|
||||
allowing maximum refactoring in the future ...
|
||||
----------------------------------------------
|
||||
|
||||
explicit name export control
|
||||
............................
|
||||
|
||||
In order to allow a fast development pace across versions of
|
||||
the py lib there is **explicit name export control**. You
|
||||
should only see names which make sense to use from the outside
|
||||
and which the py lib developers want to guarantee across versions.
|
||||
However, you don't need to treat the ``py`` lib as
|
||||
anything special. You can simply use the usual ``import``
|
||||
statement and will not notice much of a difference - except that
|
||||
the namespaces you'll see from the ``py`` lib are relatively
|
||||
clean and have no clutter.
|
||||
|
||||
Release policy & API maintenance
|
||||
........................................
|
||||
|
||||
We'll talk about major, minor and micro numbers as the three
|
||||
numbers in "1.2.3" respectively. These are the
|
||||
the rough release policies:
|
||||
|
||||
- Micro-releases are bug fix releases and should not introduce
|
||||
new names to the public API. They may add tests and thus
|
||||
further define the behaviour of the py lib. They may
|
||||
completly change the implementation but the public API
|
||||
tests should continue to run (unless they needed to
|
||||
get fixed themselves).
|
||||
|
||||
- No **tested feature** of the exported py API shall vanish
|
||||
across minor releases until it is marked deprecated.
|
||||
|
||||
For example, pure API tests of a future version 1.0 are to
|
||||
continue to fully run on 1.1 and so on. If an API gets
|
||||
deprecated with a minor release it goes with the next minor
|
||||
release. Thus if you don't use deprecated APIs you should
|
||||
be able to use the next two minor releases. However, if
|
||||
you relied on some untested implementation behaviour,
|
||||
you may still get screwed. Solution: add API tests to the
|
||||
py lib :-) It's really the tests that make the difference.
|
||||
|
||||
- Pure API tests are not allowed to access any implementation
|
||||
level details. For example, accessing names starting with
|
||||
a single leading '_' is generally seen as an implementation
|
||||
level detail.
|
||||
|
||||
- major releases *should*, but are not required to, pass
|
||||
all API tests of the previous latest major released
|
||||
version.
|
||||
|
||||
|
||||
the need to find the right *paths* ...
|
||||
--------------------------------------
|
||||
|
||||
Another focus are well tested so called *path* implementations
|
||||
that allow you to seemlessly work with different backends,
|
||||
currently a local filesystem, subversion working copies and
|
||||
subversion remote URLs.
|
||||
|
||||
How does py development work?
|
||||
=============================
|
||||
|
||||
Communication and coding style
|
||||
------------------------------
|
||||
|
||||
We are discussing things on our `py-dev mailing list`_
|
||||
and collaborate via the codespeak subversion repository.
|
||||
|
||||
We follow a `coding style`_ which strongly builds on `PEP 8`_,
|
||||
the basic python coding style document.
|
||||
|
||||
It's easy to get commit rights especially if you are an
|
||||
experienced python developer and share some of the
|
||||
frustrations described above.
|
||||
|
||||
Licensing
|
||||
-----------------
|
||||
|
||||
The Py lib is released under the MIT license and all
|
||||
contributors need to release their contributions
|
||||
under this license as well.
|
||||
|
||||
connections with PyPy_
|
||||
---------------------------------
|
||||
|
||||
A major motivation for writing the py lib stems from needs
|
||||
during PyPy_ development, most importantly testing and
|
||||
file system access issues. PyPy puts a lot of pressure
|
||||
on a testing environment and thus is a good **reality test**.
|
||||
|
||||
Who is "we"?
|
||||
=============================
|
||||
|
||||
Some initial code was written from *Jens-Uwe Mager* and *Holger
|
||||
Krekel*, after which Holger continued on a previous
|
||||
incarnations of the py.test tool (known first as 'utest', then
|
||||
as 'std.utest', now for some 2 years 'py.test').
|
||||
|
||||
Helpful discussions took place with *Martijn Faassen*, *Stephan
|
||||
Schwarzer*, *Brian Dorsey*, *Grigh Gheorghiu* and then
|
||||
*Armin Rigo* who contributed important parts.
|
||||
He and Holger came up with a couple of iterations of the
|
||||
testing-code that reduced the API to basically nothing: just the
|
||||
plain assert statement and a ``py.test.raises`` method to
|
||||
check for occuring exceptions within tests.
|
||||
|
||||
Currently (as of 2007), there are more people involved
|
||||
and also have worked funded through merlinux_ and the
|
||||
PyPy EU project, Carl Friedrich Bolz, Guido Wesdorp
|
||||
and Maciej Fijalkowski who contributed particularly
|
||||
in 2006 and 2007 major parts of the py lib.
|
||||
|
||||
.. _`talk at EP2004`: http://codespeak.net/svn/user/hpk/talks/std-talk.txt
|
||||
.. _`coding style`: coding-style.html
|
||||
.. _`PEP 8`: http://www.python.org/peps/pep-0008.html
|
||||
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _`test environment`: test.html
|
||||
.. _`PyPy`: http://codespeak.net/pypy
|
||||
.. _future: future.html
|
||||
.. _`py.test tool and library`: test.html
|
||||
.. _merlinux: http://merlinux.de
|
||||
|
||||
--
|
||||
|
||||
.. [#] FOSS is an evolving acronym for Free and Open Source Software
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
====================================================
|
||||
py.xml: Lightweight and flexible xml/html generation
|
||||
====================================================
|
||||
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
There are a plethora of frameworks and libraries to generate
|
||||
xml and html trees. However, many of them are large, have a
|
||||
steep learning curve and are often hard to debug. Not to
|
||||
speak of the fact that they are frameworks to begin with.
|
||||
|
||||
The py lib strives to offer enough functionality to represent
|
||||
itself and especially its API in html or xml.
|
||||
|
||||
.. _xist: http://www.livinglogic.de/Python/xist/index.html
|
||||
.. _`exchange data`: execnet.html#exchange-data
|
||||
|
||||
a pythonic object model , please
|
||||
================================
|
||||
|
||||
The py lib offers a pythonic way to generate xml/html, based on
|
||||
ideas from xist_ which `uses python class objects`_ to build
|
||||
xml trees. However, xist_'s implementation is somewhat heavy
|
||||
because it has additional goals like transformations and
|
||||
supporting many namespaces. But its basic idea is very easy.
|
||||
|
||||
.. _`uses python class objects`: http://www.livinglogic.de/Python/xist/Howto.html
|
||||
|
||||
generating arbitrary xml structures
|
||||
-----------------------------------
|
||||
|
||||
With ``py.xml.Namespace`` you have the basis
|
||||
to generate custom xml-fragments on the fly::
|
||||
|
||||
class ns(py.xml.Namespace):
|
||||
"my custom xml namespace"
|
||||
doc = ns.books(
|
||||
ns.book(
|
||||
ns.author("May Day"),
|
||||
ns.title("python for java programmers"),),
|
||||
ns.book(
|
||||
ns.author("why"),
|
||||
ns.title("Java for Python programmers"),),
|
||||
publisher="N.N",
|
||||
)
|
||||
print doc.unicode(indent=2).encode('utf8')
|
||||
|
||||
will give you this representation::
|
||||
|
||||
<books publisher="N.N">
|
||||
<book>
|
||||
<author>May Day</author>
|
||||
<title>python for java programmers</title></book>
|
||||
<book>
|
||||
<author>why</author>
|
||||
<title>Java for Python programmers</title></book></books>
|
||||
|
||||
In a sentence: positional arguments are child-tags and
|
||||
keyword-arguments are attributes.
|
||||
|
||||
On a side note, you'll see that the unicode-serializer
|
||||
supports a nice indentation style which keeps your generated
|
||||
html readable, basically through emulating python's white
|
||||
space significance by putting closing-tags rightmost and
|
||||
almost invisible at first glance :-)
|
||||
|
||||
basic example for generating html
|
||||
---------------------------------
|
||||
|
||||
Consider this example::
|
||||
|
||||
from py.xml import html # html namespace
|
||||
|
||||
paras = "First Para", "Second para"
|
||||
|
||||
doc = html.html(
|
||||
html.head(
|
||||
html.meta(name="Content-Type", value="text/html; charset=latin1")),
|
||||
html.body(
|
||||
[html.p(p) for p in paras]))
|
||||
|
||||
print unicode(doc).encode('latin1')
|
||||
|
||||
Again, tags are objects which contain tags and have attributes.
|
||||
More exactly, Tags inherit from the list type and thus can be
|
||||
manipulated as list objects. They additionally support a default
|
||||
way to represent themselves as a serialized unicode object.
|
||||
|
||||
If you happen to look at the py.xml implementation you'll
|
||||
note that the tag/namespace implementation consumes some 50 lines
|
||||
with another 50 lines for the unicode serialization code.
|
||||
|
||||
CSS-styling your html Tags
|
||||
--------------------------
|
||||
|
||||
One aspect where many of the huge python xml/html generation
|
||||
frameworks utterly fail is a clean and convenient integration
|
||||
of CSS styling. Often, developers are left alone with keeping
|
||||
CSS style definitions in sync with some style files
|
||||
represented as strings (often in a separate .css file). Not
|
||||
only is this hard to debug but the missing abstractions make
|
||||
it hard to modify the styling of your tags or to choose custom
|
||||
style representations (inline, html.head or external). Add the
|
||||
Browers usual tolerance of messyness and errors in Style
|
||||
references and welcome to hell, known as the domain of
|
||||
developing web applications :-)
|
||||
|
||||
By contrast, consider this CSS styling example::
|
||||
|
||||
class my(html):
|
||||
"my initial custom style"
|
||||
class body(html.body):
|
||||
style = html.Style(font_size = "120%")
|
||||
|
||||
class h2(html.h2):
|
||||
style = html.Style(background = "grey")
|
||||
|
||||
class p(html.p):
|
||||
style = html.Style(font_weight="bold")
|
||||
|
||||
doc = my.html(
|
||||
my.head(),
|
||||
my.body(
|
||||
my.h2("hello world"),
|
||||
my.p("bold as bold can")
|
||||
)
|
||||
)
|
||||
|
||||
print doc.unicode(indent=2)
|
||||
|
||||
This will give you a small'n mean self contained
|
||||
represenation by default::
|
||||
|
||||
<html>
|
||||
<head/>
|
||||
<body style="font-size: 120%">
|
||||
<h2 style="background: grey">hello world</h2>
|
||||
<p style="font-weight: bold">bold as bold can</p></body></html>
|
||||
|
||||
Most importantly, note that the inline-styling is just an
|
||||
implementation detail of the unicode serialization code.
|
||||
You can easily modify the serialization to put your styling into the
|
||||
``html.head`` or in a separate file and autogenerate CSS-class
|
||||
names or ids.
|
||||
|
||||
Hey, you could even write tests that you are using correct
|
||||
styles suitable for specific browser requirements. Did i mention
|
||||
that the ability to easily write tests for your generated
|
||||
html and its serialization could help to develop _stable_ user
|
||||
interfaces?
|
||||
|
||||
More to come ...
|
||||
----------------
|
||||
|
||||
For now, i don't think we should strive to offer much more
|
||||
than the above. However, it is probably not hard to offer
|
||||
*partial serialization* to allow generating maybe hundreds of
|
||||
complex html documents per second. Basically we would allow
|
||||
putting callables both as Tag content and as values of
|
||||
attributes. A slightly more advanced Serialization would then
|
||||
produce a list of unicode objects intermingled with callables.
|
||||
At HTTP-Request time the callables would get called to
|
||||
complete the probably request-specific serialization of
|
||||
your Tags. Hum, it's probably harder to explain this than to
|
||||
actually code it :-)
|
||||
|
||||
.. _`py.test`: test.html
|
|
@ -0,0 +1,414 @@
|
|||
/**
|
||||
* Sphinx stylesheet -- basic theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li div.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable dl, table.indextable dd {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px 7px 0 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px 7px 0 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition dl {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 0;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd p {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dt:target, .highlight {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.refcount {
|
||||
color: #060;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
padding: 5px 0px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
tt.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
tt.xref, a tt {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/**
|
||||
* Sphinx stylesheet -- default theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #11303d;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: #1c4e63;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
padding: 0 20px 30px 20px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #ffffff;
|
||||
width: 100%;
|
||||
padding: 9px 0 9px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #ffffff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #133f52;
|
||||
line-height: 30px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
color: #ffffff;
|
||||
font-size: 1.4em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
color: #ffffff;
|
||||
font-size: 1.3em;
|
||||
font-weight: normal;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
margin: 5px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #98dbcc;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #355f7c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
background-color: #f2f2f2;
|
||||
font-weight: normal;
|
||||
color: #20435c;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 20px -20px 10px -20px;
|
||||
padding: 3px 0 3px 10px;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 160%; }
|
||||
div.body h3 { font-size: 140%; }
|
||||
div.body h4 { font-size: 120%; }
|
||||
div.body h5 { font-size: 110%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px;
|
||||
background-color: #eeffcc;
|
||||
color: #333333;
|
||||
line-height: 120%;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 0.95em;
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/// XXX: make it cross browser
|
||||
|
||||
/**
|
||||
* make the code below compatible with browsers without
|
||||
* an installed firebug like debugger
|
||||
*/
|
||||
if (!window.console || !console.firebug) {
|
||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
|
||||
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
|
||||
window.console = {};
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
window.console[names[i]] = function() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* small helper function to urldecode strings
|
||||
*/
|
||||
jQuery.urldecode = function(x) {
|
||||
return decodeURIComponent(x).replace(/\+/g, ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* small helper function to urlencode strings
|
||||
*/
|
||||
jQuery.urlencode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* This function returns the parsed url parameters of the
|
||||
* current request. Multiple values per key are supported,
|
||||
* it will always return arrays of strings for the value parts.
|
||||
*/
|
||||
jQuery.getQueryParameters = function(s) {
|
||||
if (typeof s == 'undefined')
|
||||
s = document.location.search;
|
||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||
var result = {};
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var tmp = parts[i].split('=', 2);
|
||||
var key = jQuery.urldecode(tmp[0]);
|
||||
var value = jQuery.urldecode(tmp[1]);
|
||||
if (key in result)
|
||||
result[key].push(value);
|
||||
else
|
||||
result[key] = [value];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* small function to check if an array contains
|
||||
* a given item.
|
||||
*/
|
||||
jQuery.contains = function(arr, item) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i] == item)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* highlight a given string on a jquery object by wrapping it in
|
||||
* span elements with the given class name.
|
||||
*/
|
||||
jQuery.fn.highlightText = function(text, className) {
|
||||
function highlight(node) {
|
||||
if (node.nodeType == 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 && !jQuery.className.has(node.parentNode, className)) {
|
||||
var span = document.createElement("span");
|
||||
span.className = className;
|
||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||
document.createTextNode(val.substr(pos + text.length)),
|
||||
node.nextSibling));
|
||||
node.nodeValue = val.substr(0, pos);
|
||||
}
|
||||
}
|
||||
else if (!jQuery(node).is("button, select, textarea")) {
|
||||
jQuery.each(node.childNodes, function() {
|
||||
highlight(this)
|
||||
});
|
||||
}
|
||||
}
|
||||
return this.each(function() {
|
||||
highlight(this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
var Documentation = {
|
||||
|
||||
init : function() {
|
||||
this.fixFirefoxAnchorBug();
|
||||
this.highlightSearchWords();
|
||||
this.initModIndex();
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS : {},
|
||||
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
|
||||
LOCALE : 'unknown',
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can savely bound to a different name (_ = Documentation.gettext)
|
||||
gettext : function(string) {
|
||||
var translated = Documentation.TRANSLATIONS[string];
|
||||
if (typeof translated == 'undefined')
|
||||
return string;
|
||||
return (typeof translated == 'string') ? translated : translated[0];
|
||||
},
|
||||
|
||||
ngettext : function(singular, plural, n) {
|
||||
var translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated == 'undefined')
|
||||
return (n == 1) ? singular : plural;
|
||||
return translated[Documentation.PLURALEXPR(n)];
|
||||
},
|
||||
|
||||
addTranslations : function(catalog) {
|
||||
for (var key in catalog.messages)
|
||||
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||
this.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* add context elements like header anchor links
|
||||
*/
|
||||
addContextElements : function() {
|
||||
$('div[id] > :header:first').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this headline')).
|
||||
appendTo(this);
|
||||
});
|
||||
$('dt[id]').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this definition')).
|
||||
appendTo(this);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* workaround a firefox stupidity
|
||||
*/
|
||||
fixFirefoxAnchorBug : function() {
|
||||
if (document.location.hash && $.browser.mozilla)
|
||||
window.setTimeout(function() {
|
||||
document.location.href += '';
|
||||
}, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* highlight the search words provided in the url in the text
|
||||
*/
|
||||
highlightSearchWords : function() {
|
||||
var params = $.getQueryParameters();
|
||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||
if (terms.length) {
|
||||
var body = $('div.body');
|
||||
window.setTimeout(function() {
|
||||
$.each(terms, function() {
|
||||
body.highlightText(this.toLowerCase(), 'highlight');
|
||||
});
|
||||
}, 10);
|
||||
$('<li class="highlight-link"><a href="javascript:Documentation.' +
|
||||
'hideSearchWords()">' + _('Hide Search Matches') + '</a></li>')
|
||||
.appendTo($('.sidebar .this-page-menu'));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* init the modindex toggle buttons
|
||||
*/
|
||||
initModIndex : function() {
|
||||
var togglers = $('img.toggler').click(function() {
|
||||
var src = $(this).attr('src');
|
||||
var idnum = $(this).attr('id').substr(7);
|
||||
console.log($('tr.cg-' + idnum).toggle());
|
||||
if (src.substr(-9) == 'minus.png')
|
||||
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||
else
|
||||
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||
}).css('display', '');
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX) {
|
||||
togglers.click();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to hide the search marks again
|
||||
*/
|
||||
hideSearchWords : function() {
|
||||
$('.sidebar .this-page-menu li.highlight-link').fadeOut(300);
|
||||
$('span.highlight').removeClass('highlight');
|
||||
},
|
||||
|
||||
/**
|
||||
* make the url absolute
|
||||
*/
|
||||
makeURL : function(relativeURL) {
|
||||
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* get the current relative url
|
||||
*/
|
||||
getCurrentURL : function() {
|
||||
var path = document.location.pathname;
|
||||
var parts = path.split(/\//);
|
||||
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||
if (this == '..')
|
||||
parts.pop();
|
||||
});
|
||||
var url = parts.join('/');
|
||||
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||
}
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
_ = Documentation.gettext;
|
||||
|
||||
$(document).ready(function() {
|
||||
Documentation.init();
|
||||
});
|
Binary file not shown.
After Width: | Height: | Size: 392 B |
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 199 B |
Binary file not shown.
After Width: | Height: | Size: 199 B |
|
@ -0,0 +1,61 @@
|
|||
.hll { background-color: #ffffcc }
|
||||
.c { color: #408090; font-style: italic } /* Comment */
|
||||
.err { border: 1px solid #FF0000 } /* Error */
|
||||
.k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.o { color: #666666 } /* Operator */
|
||||
.cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||
.cp { color: #007020 } /* Comment.Preproc */
|
||||
.c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||
.cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||
.gd { color: #A00000 } /* Generic.Deleted */
|
||||
.ge { font-style: italic } /* Generic.Emph */
|
||||
.gr { color: #FF0000 } /* Generic.Error */
|
||||
.gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.gi { color: #00A000 } /* Generic.Inserted */
|
||||
.go { color: #303030 } /* Generic.Output */
|
||||
.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.gs { font-weight: bold } /* Generic.Strong */
|
||||
.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.gt { color: #0040D0 } /* Generic.Traceback */
|
||||
.kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.kt { color: #902000 } /* Keyword.Type */
|
||||
.m { color: #208050 } /* Literal.Number */
|
||||
.s { color: #4070a0 } /* Literal.String */
|
||||
.na { color: #4070a0 } /* Name.Attribute */
|
||||
.nb { color: #007020 } /* Name.Builtin */
|
||||
.nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.no { color: #60add5 } /* Name.Constant */
|
||||
.nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.ne { color: #007020 } /* Name.Exception */
|
||||
.nf { color: #06287e } /* Name.Function */
|
||||
.nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.nv { color: #bb60d5 } /* Name.Variable */
|
||||
.ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.mf { color: #208050 } /* Literal.Number.Float */
|
||||
.mh { color: #208050 } /* Literal.Number.Hex */
|
||||
.mi { color: #208050 } /* Literal.Number.Integer */
|
||||
.mo { color: #208050 } /* Literal.Number.Oct */
|
||||
.sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.sr { color: #235388 } /* Literal.String.Regex */
|
||||
.s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.il { color: #208050 } /* Literal.Number.Integer.Long */
|
|
@ -0,0 +1,467 @@
|
|||
/**
|
||||
* helper function to return a node containing the
|
||||
* search summary for a given text. keywords is a list
|
||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||
* words. the first one is used to find the occurance, the
|
||||
* latter for highlighting it.
|
||||
*/
|
||||
|
||||
jQuery.makeSearchSummary = function(text, keywords, hlwords) {
|
||||
var textLower = text.toLowerCase();
|
||||
var start = 0;
|
||||
$.each(keywords, function() {
|
||||
var i = textLower.indexOf(this.toLowerCase());
|
||||
if (i > -1)
|
||||
start = i;
|
||||
});
|
||||
start = Math.max(start - 120, 0);
|
||||
var excerpt = ((start > 0) ? '...' : '') +
|
||||
$.trim(text.substr(start, 240)) +
|
||||
((start + 240 - text.length) ? '...' : '');
|
||||
var rv = $('<div class="context"></div>').text(excerpt);
|
||||
$.each(hlwords, function() {
|
||||
rv = rv.highlightText(this, 'highlight');
|
||||
});
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
var PorterStemmer = function() {
|
||||
|
||||
var step2list = {
|
||||
ational: 'ate',
|
||||
tional: 'tion',
|
||||
enci: 'ence',
|
||||
anci: 'ance',
|
||||
izer: 'ize',
|
||||
bli: 'ble',
|
||||
alli: 'al',
|
||||
entli: 'ent',
|
||||
eli: 'e',
|
||||
ousli: 'ous',
|
||||
ization: 'ize',
|
||||
ation: 'ate',
|
||||
ator: 'ate',
|
||||
alism: 'al',
|
||||
iveness: 'ive',
|
||||
fulness: 'ful',
|
||||
ousness: 'ous',
|
||||
aliti: 'al',
|
||||
iviti: 'ive',
|
||||
biliti: 'ble',
|
||||
logi: 'log'
|
||||
};
|
||||
|
||||
var step3list = {
|
||||
icate: 'ic',
|
||||
ative: '',
|
||||
alize: 'al',
|
||||
iciti: 'ic',
|
||||
ical: 'ic',
|
||||
ful: '',
|
||||
ness: ''
|
||||
};
|
||||
|
||||
var c = "[^aeiou]"; // consonant
|
||||
var v = "[aeiouy]"; // vowel
|
||||
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||
var V = v + "[aeiou]*"; // vowel sequence
|
||||
|
||||
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||
|
||||
this.stemWord = function (w) {
|
||||
var stem;
|
||||
var suffix;
|
||||
var firstch;
|
||||
var origword = w;
|
||||
|
||||
if (w.length < 3)
|
||||
return w;
|
||||
|
||||
var re;
|
||||
var re2;
|
||||
var re3;
|
||||
var re4;
|
||||
|
||||
firstch = w.substr(0,1);
|
||||
if (firstch == "y")
|
||||
w = firstch.toUpperCase() + w.substr(1);
|
||||
|
||||
// Step 1a
|
||||
re = /^(.+?)(ss|i)es$/;
|
||||
re2 = /^(.+?)([^s])s$/;
|
||||
|
||||
if (re.test(w))
|
||||
w = w.replace(re,"$1$2");
|
||||
else if (re2.test(w))
|
||||
w = w.replace(re2,"$1$2");
|
||||
|
||||
// Step 1b
|
||||
re = /^(.+?)eed$/;
|
||||
re2 = /^(.+?)(ed|ing)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(fp[1])) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1];
|
||||
re2 = new RegExp(s_v);
|
||||
if (re2.test(stem)) {
|
||||
w = stem;
|
||||
re2 = /(at|bl|iz)$/;
|
||||
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re2.test(w))
|
||||
w = w + "e";
|
||||
else if (re3.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
else if (re4.test(w))
|
||||
w = w + "e";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1c
|
||||
re = /^(.+?)y$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(s_v);
|
||||
if (re.test(stem))
|
||||
w = stem + "i";
|
||||
}
|
||||
|
||||
// Step 2
|
||||
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step2list[suffix];
|
||||
}
|
||||
|
||||
// Step 3
|
||||
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step3list[suffix];
|
||||
}
|
||||
|
||||
// Step 4
|
||||
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||
re2 = /^(.+?)(s|t)(ion)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
if (re.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1] + fp[2];
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re2.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
re = /^(.+?)e$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
re2 = new RegExp(meq1);
|
||||
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||
w = stem;
|
||||
}
|
||||
re = /ll$/;
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re.test(w) && re2.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
|
||||
// and turn initial Y back to y
|
||||
if (firstch == "y")
|
||||
w = firstch.toLowerCase() + w.substr(1);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search Module
|
||||
*/
|
||||
var Search = {
|
||||
|
||||
_index : null,
|
||||
_queued_query : null,
|
||||
_pulse_status : -1,
|
||||
|
||||
init : function() {
|
||||
var params = $.getQueryParameters();
|
||||
if (params.q) {
|
||||
var query = params.q[0];
|
||||
$('input[name="q"]')[0].value = query;
|
||||
this.performSearch(query);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the index
|
||||
*/
|
||||
setIndex : function(index) {
|
||||
var q;
|
||||
this._index = index;
|
||||
if ((q = this._queued_query) !== null) {
|
||||
this._queued_query = null;
|
||||
Search.query(q);
|
||||
}
|
||||
},
|
||||
|
||||
hasIndex : function() {
|
||||
return this._index !== null;
|
||||
},
|
||||
|
||||
deferQuery : function(query) {
|
||||
this._queued_query = query;
|
||||
},
|
||||
|
||||
stopPulse : function() {
|
||||
this._pulse_status = 0;
|
||||
},
|
||||
|
||||
startPulse : function() {
|
||||
if (this._pulse_status >= 0)
|
||||
return;
|
||||
function pulse() {
|
||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||
var dotString = '';
|
||||
for (var i = 0; i < Search._pulse_status; i++)
|
||||
dotString += '.';
|
||||
Search.dots.text(dotString);
|
||||
if (Search._pulse_status > -1)
|
||||
window.setTimeout(pulse, 500);
|
||||
};
|
||||
pulse();
|
||||
},
|
||||
|
||||
/**
|
||||
* perform a search for something
|
||||
*/
|
||||
performSearch : function(query) {
|
||||
// create the required interface elements
|
||||
this.out = $('#search-results');
|
||||
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||
this.dots = $('<span></span>').appendTo(this.title);
|
||||
this.status = $('<p style="display: none"></p>').appendTo(this.out);
|
||||
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||
|
||||
$('#search-progress').text(_('Preparing search...'));
|
||||
this.startPulse();
|
||||
|
||||
// index already loaded, the browser was quick!
|
||||
if (this.hasIndex())
|
||||
this.query(query);
|
||||
else
|
||||
this.deferQuery(query);
|
||||
},
|
||||
|
||||
query : function(query) {
|
||||
// stem the searchterms and add them to the
|
||||
// correct list
|
||||
var stemmer = new PorterStemmer();
|
||||
var searchterms = [];
|
||||
var excluded = [];
|
||||
var hlterms = [];
|
||||
var tmp = query.split(/\s+/);
|
||||
var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null;
|
||||
for (var i = 0; i < tmp.length; i++) {
|
||||
// stem the word
|
||||
var word = stemmer.stemWord(tmp[i]).toLowerCase();
|
||||
// select the correct list
|
||||
if (word[0] == '-') {
|
||||
var toAppend = excluded;
|
||||
word = word.substr(1);
|
||||
}
|
||||
else {
|
||||
var toAppend = searchterms;
|
||||
hlterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
// only add if not already in the list
|
||||
if (!$.contains(toAppend, word))
|
||||
toAppend.push(word);
|
||||
};
|
||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||
|
||||
console.debug('SEARCH: searching for:');
|
||||
console.info('required: ', searchterms);
|
||||
console.info('excluded: ', excluded);
|
||||
|
||||
// prepare search
|
||||
var filenames = this._index.filenames;
|
||||
var titles = this._index.titles;
|
||||
var terms = this._index.terms;
|
||||
var descrefs = this._index.descrefs;
|
||||
var modules = this._index.modules;
|
||||
var desctypes = this._index.desctypes;
|
||||
var fileMap = {};
|
||||
var files = null;
|
||||
var objectResults = [];
|
||||
var regularResults = [];
|
||||
$('#search-progress').empty();
|
||||
|
||||
// lookup as object
|
||||
if (object != null) {
|
||||
for (var module in modules) {
|
||||
if (module.indexOf(object) > -1) {
|
||||
fn = modules[module];
|
||||
descr = _('module, in ') + titles[fn];
|
||||
objectResults.push([filenames[fn], module, '#module-'+module, descr]);
|
||||
}
|
||||
}
|
||||
for (var prefix in descrefs) {
|
||||
for (var name in descrefs[prefix]) {
|
||||
if (name.toLowerCase().indexOf(object) > -1) {
|
||||
match = descrefs[prefix][name];
|
||||
fullname = (prefix ? prefix + '.' : '') + name;
|
||||
descr = desctypes[match[1]] + _(', in ') + titles[match[0]];
|
||||
objectResults.push([filenames[match[0]], fullname, '#'+fullname, descr]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort results descending
|
||||
objectResults.sort(function(a, b) {
|
||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
||||
});
|
||||
|
||||
|
||||
// perform the search on the required terms
|
||||
for (var i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
// no match but word was a required one
|
||||
if ((files = terms[word]) == null)
|
||||
break;
|
||||
if (files.length == undefined) {
|
||||
files = [files];
|
||||
}
|
||||
// create the mapping
|
||||
for (var j = 0; j < files.length; j++) {
|
||||
var file = files[j];
|
||||
if (file in fileMap)
|
||||
fileMap[file].push(word);
|
||||
else
|
||||
fileMap[file] = [word];
|
||||
}
|
||||
}
|
||||
|
||||
// now check if the files don't contain excluded terms
|
||||
for (var file in fileMap) {
|
||||
var valid = true;
|
||||
|
||||
// check if all requirements are matched
|
||||
if (fileMap[file].length != searchterms.length)
|
||||
continue;
|
||||
|
||||
// ensure that none of the excluded terms is in the
|
||||
// search result.
|
||||
for (var i = 0; i < excluded.length; i++) {
|
||||
if (terms[excluded[i]] == file ||
|
||||
$.contains(terms[excluded[i]] || [], file)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have still a valid result we can add it
|
||||
// to the result list
|
||||
if (valid)
|
||||
regularResults.push([filenames[file], titles[file], '', null]);
|
||||
}
|
||||
|
||||
// delete unused variables in order to not waste
|
||||
// memory until list is retrieved completely
|
||||
delete filenames, titles, terms;
|
||||
|
||||
// now sort the regular results descending by title
|
||||
regularResults.sort(function(a, b) {
|
||||
var left = a[1].toLowerCase();
|
||||
var right = b[1].toLowerCase();
|
||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||
});
|
||||
|
||||
// combine both
|
||||
var results = regularResults.concat(objectResults);
|
||||
|
||||
// print the results
|
||||
var resultCount = results.length;
|
||||
function displayNextItem() {
|
||||
// results left, load the summary and display it
|
||||
if (results.length) {
|
||||
var item = results.pop();
|
||||
var listItem = $('<li style="display:none"></li>');
|
||||
listItem.append($('<a/>').attr(
|
||||
'href',
|
||||
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
if (item[3]) {
|
||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||
$.get('_sources/' + item[0] + '.txt', function(data) {
|
||||
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// no source available, just display title
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
}
|
||||
}
|
||||
// search finished, update title and status message
|
||||
else {
|
||||
Search.stopPulse();
|
||||
Search.title.text(_('Search Results'));
|
||||
if (!resultCount)
|
||||
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||
else
|
||||
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||
Search.status.fadeIn(500);
|
||||
}
|
||||
}
|
||||
displayNextItem();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
Search.init();
|
||||
});
|
|
@ -0,0 +1,171 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>5. py/bin/ scripts — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="Contents" href="contents.html" />
|
||||
<link rel="next" title="6. 1 py.xml: Lightweight and flexible xml/html generation" href="xml.html" />
|
||||
<link rel="prev" title="4. py.code" href="code.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="xml.html" title="6. 1 py.xml: Lightweight and flexible xml/html generation"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="code.html" title="4. py.code"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" accesskey="U">Contents</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-bin-scripts">
|
||||
<h1>5. <tt class="docutils literal"><span class="pre">py/bin/</span></tt> scripts<a class="headerlink" href="#py-bin-scripts" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The py-lib contains some scripts, most of which are
|
||||
small ones (apart from <tt class="docutils literal"><span class="pre">py.test</span></tt>) that help during
|
||||
the python development process. If working
|
||||
from a svn-checkout of py lib you may add <tt class="docutils literal"><span class="pre">py/bin</span></tt>
|
||||
to your shell <tt class="docutils literal"><span class="pre">PATH</span></tt> which should make the scripts
|
||||
available on your command prompt.</p>
|
||||
<div class="section" id="py-test">
|
||||
<h2>5.1. <tt class="docutils literal"><span class="pre">py.test</span></tt><a class="headerlink" href="#py-test" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <tt class="docutils literal"><span class="pre">py.test</span></tt> executable is the main entry point into the py-lib testing tool,
|
||||
see the <a class="reference external" href="test.html">py.test documentation</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="py-cleanup">
|
||||
<h2>5.2. <tt class="docutils literal"><span class="pre">py.cleanup</span></tt><a class="headerlink" href="#py-cleanup" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Usage: <tt class="docutils literal"><span class="pre">py.cleanup</span> <span class="pre">[PATH]</span></tt></p>
|
||||
<p>Delete pyc file recursively, starting from <tt class="docutils literal"><span class="pre">PATH</span></tt> (which defaults to the
|
||||
current working directory). Don’t follow links and don’t recurse into
|
||||
directories with a “.”.</p>
|
||||
</div>
|
||||
<div class="section" id="py-countloc">
|
||||
<h2>5.3. <tt class="docutils literal"><span class="pre">py.countloc</span></tt><a class="headerlink" href="#py-countloc" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Usage: <tt class="docutils literal"><span class="pre">py.countloc</span> <span class="pre">[PATHS]</span></tt></p>
|
||||
<p>Count (non-empty) lines of python code and number of python files recursively
|
||||
starting from a <tt class="docutils literal"><span class="pre">PATHS</span></tt> given on the command line (starting from the current
|
||||
working directory). Distinguish between test files and normal ones and report
|
||||
them separately.</p>
|
||||
</div>
|
||||
<div class="section" id="py-lookup">
|
||||
<h2>5.4. <tt class="docutils literal"><span class="pre">py.lookup</span></tt><a class="headerlink" href="#py-lookup" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Usage: <tt class="docutils literal"><span class="pre">py.lookup</span> <span class="pre">SEARCH_STRING</span> <span class="pre">[options]</span></tt></p>
|
||||
<p>Looks recursively at Python files for a <tt class="docutils literal"><span class="pre">SEARCH_STRING</span></tt>, starting from the
|
||||
present working directory. Prints the line, with the filename and line-number
|
||||
prepended.</p>
|
||||
</div>
|
||||
<div class="section" id="py-rest">
|
||||
<h2>5.5. <tt class="docutils literal"><span class="pre">py.rest</span></tt><a class="headerlink" href="#py-rest" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Usage: <tt class="docutils literal"><span class="pre">py.rest</span> <span class="pre">[PATHS]</span> <span class="pre">[options]</span></tt></p>
|
||||
<p>Loot recursively for .txt files starting from <tt class="docutils literal"><span class="pre">PATHS</span></tt> and convert them to
|
||||
html using docutils or to pdf files, if the <tt class="docutils literal"><span class="pre">--pdf</span></tt> option is used. For
|
||||
conversion to PDF you will need several command line tools, on Ubuntu Linux
|
||||
this is <strong>texlive</strong> and <strong>texlive-extra-utils</strong>.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">py.rest</span></tt> has some extra features over rst2html (which is shipped with
|
||||
docutils). Most of these are still experimental, the one which is most likely
|
||||
not going to change is the <a class="reference external" href="http://www.graphviz.org">graphviz</a> directive. With that you can embed .dot
|
||||
files into your document and have them be converted to png (when outputting
|
||||
html) and to eps (when outputting pdf). Otherwise the directive works mostly
|
||||
like the image directive:</p>
|
||||
<div class="highlight-python"><pre>.. graphviz:: example.dot
|
||||
:scale: 90</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">5. <tt class="docutils literal"><span class="pre">py/bin/</span></tt> scripts</a><ul>
|
||||
<li><a class="reference external" href="#py-test">5.1. <tt class="docutils literal"><span class="pre">py.test</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-cleanup">5.2. <tt class="docutils literal"><span class="pre">py.cleanup</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-countloc">5.3. <tt class="docutils literal"><span class="pre">py.countloc</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-lookup">5.4. <tt class="docutils literal"><span class="pre">py.lookup</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-rest">5.5. <tt class="docutils literal"><span class="pre">py.rest</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="code.html"
|
||||
title="previous chapter">4. py.code</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="xml.html"
|
||||
title="next chapter">6. 1 py.xml: Lightweight and flexible xml/html generation</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/bin.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="xml.html" title="6. 1 py.xml: Lightweight and flexible xml/html generation"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="code.html" title="4. py.code"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,247 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>4. py.code — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="5. py/bin/ scripts" href="bin.html" />
|
||||
<link rel="prev" title="3. py.path" href="path.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="bin.html" title="5. py/bin/ scripts"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="path.html" title="3. py.path"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-code">
|
||||
<h1>4. py.code<a class="headerlink" href="#py-code" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The <tt class="docutils literal"><span class="pre">py.code</span></tt> 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.</p>
|
||||
<p>The <tt class="docutils literal"><span class="pre">py.code</span></tt> 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.</p>
|
||||
<p>source: <tt class="docutils literal"><span class="pre">py/code/</span></tt></p>
|
||||
<div class="section" id="contents-of-the-library">
|
||||
<h2>4.1. Contents of the library<a class="headerlink" href="#contents-of-the-library" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Every object in the <tt class="docutils literal"><span class="pre">py.code</span></tt> library wraps a code Python object related
|
||||
to code objects, source code, frames and tracebacks: the <tt class="docutils literal"><span class="pre">py.code.Code</span></tt>
|
||||
class wraps code objects, <tt class="docutils literal"><span class="pre">py.code.Source</span></tt> source snippets,
|
||||
<tt class="docutils literal"><span class="pre">py.code.Traceback</span></tt> exception tracebacks, <tt class="docutils literal"><span class="pre">py.code.Frame</span></tt> frame
|
||||
objects (as found in e.g. tracebacks) and <tt class="docutils literal"><span class="pre">py.code.ExceptionInfo</span></tt> the
|
||||
tuple provided by sys.exc_info() (containing exception and traceback
|
||||
information when an exception occurs). Also in the library is a helper function
|
||||
<tt class="docutils literal"><span class="pre">py.code.compile()</span></tt> that provides the same functionality as Python’s
|
||||
built-in ‘compile()’ function, but returns a wrapped code object.</p>
|
||||
</div>
|
||||
<div class="section" id="the-wrappers">
|
||||
<h2>4.2. The wrappers<a class="headerlink" href="#the-wrappers" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="py-code-code">
|
||||
<h3>4.2.1. <tt class="docutils literal"><span class="pre">py.code.Code</span></tt><a class="headerlink" href="#py-code-code" title="Permalink to this headline">¶</a></h3>
|
||||
<p>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.</p>
|
||||
<p>A quick example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="n">c</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Code</span><span class="p">(</span><span class="n">py</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">read</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">c</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span>
|
||||
<span class="go">'common.py'</span>
|
||||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">source</span><span class="p">(),</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Source</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">c</span><span class="o">.</span><span class="n">source</span><span class="p">())</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)[</span><span class="mf">0</span><span class="p">]</span>
|
||||
<span class="go">"def read(self, mode='rb'):"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>source: <tt class="docutils literal"><span class="pre">py/code/code.py</span></tt></p>
|
||||
</div>
|
||||
<div class="section" id="py-code-source">
|
||||
<h3>4.2.2. <tt class="docutils literal"><span class="pre">py.code.Source</span></tt><a class="headerlink" href="#py-code-source" title="Permalink to this headline">¶</a></h3>
|
||||
<p>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.</p>
|
||||
<p>Example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Source</span><span class="p">(</span><span class="s">"""</span><span class="se">\</span>
|
||||
<span class="gp">... </span><span class="s"> def foo():</span>
|
||||
<span class="gp">... </span><span class="s"> print "foo"</span>
|
||||
<span class="gp">... </span><span class="s">"""</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'def'</span><span class="p">)</span> <span class="c"># automatic de-indentation!</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">isparseable</span><span class="p">()</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">sub</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">getstatement</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span> <span class="c"># get the statement starting at line 1</span>
|
||||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">sub</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="c"># XXX why is the strip() required?!?</span>
|
||||
<span class="go">'print "foo"'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>source: <tt class="docutils literal"><span class="pre">py/code/source.py</span></tt></p>
|
||||
</div>
|
||||
<div class="section" id="py-code-traceback">
|
||||
<h3>4.2.3. <tt class="docutils literal"><span class="pre">py.code.Traceback</span></tt><a class="headerlink" href="#py-code-traceback" title="Permalink to this headline">¶</a></h3>
|
||||
<p>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.</p>
|
||||
<p>Example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">sys</span>
|
||||
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="n">py</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="p">(</span><span class="mf">100</span><span class="p">)</span> <span class="c"># illegal argument</span>
|
||||
<span class="gp">... </span><span class="k">except</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="n">exc</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">tb</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">t</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Traceback</span><span class="p">(</span><span class="n">tb</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">first</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span> <span class="c"># get the second entry (first is in this doc)</span>
|
||||
<span class="gp">>>> </span><span class="n">first</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span> <span class="c"># second is in py/path/local.py</span>
|
||||
<span class="go">'local.py'</span>
|
||||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">first</span><span class="o">.</span><span class="n">statement</span><span class="p">,</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Source</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">first</span><span class="o">.</span><span class="n">statement</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'raise ValueError'</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>source: <tt class="docutils literal"><span class="pre">py/code/traceback2.py</span></tt></p>
|
||||
</div>
|
||||
<div class="section" id="py-code-frame">
|
||||
<h3>4.2.4. <tt class="docutils literal"><span class="pre">py.code.Frame</span></tt><a class="headerlink" href="#py-code-frame" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Frame wrappers are used in <tt class="docutils literal"><span class="pre">py.code.Traceback</span></tt> 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 <tt class="docutils literal"><span class="pre">py.code.Code</span></tt> object)
|
||||
and examine the arguments.</p>
|
||||
<p>Example (using the ‘first’ TracebackItem instance created above):</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">frame</span> <span class="o">=</span> <span class="n">first</span><span class="o">.</span><span class="n">frame</span>
|
||||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">frame</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Code</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">frame</span><span class="o">.</span><span class="n">eval</span><span class="p">(</span><span class="s">'self'</span><span class="p">),</span> <span class="n">py</span><span class="o">.</span><span class="n">__</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">LocalPath</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="p">[</span><span class="n">namevalue</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">namevalue</span> <span class="ow">in</span> <span class="n">frame</span><span class="o">.</span><span class="n">getargs</span><span class="p">()]</span>
|
||||
<span class="go">['cls', 'path']</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="py-code-exceptioninfo">
|
||||
<h3>4.2.5. <tt class="docutils literal"><span class="pre">py.code.ExceptionInfo</span></tt><a class="headerlink" href="#py-code-exceptioninfo" title="Permalink to this headline">¶</a></h3>
|
||||
<p>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.</p>
|
||||
<p>Example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">sys</span>
|
||||
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="n">foobar</span><span class="p">()</span>
|
||||
<span class="gp">... </span><span class="k">except</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="n">excinfo</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">ExceptionInfo</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">excinfo</span><span class="o">.</span><span class="n">typename</span>
|
||||
<span class="go">'NameError'</span>
|
||||
<span class="gp">>>> </span><span class="nb">isinstance</span><span class="p">(</span><span class="n">excinfo</span><span class="o">.</span><span class="n">traceback</span><span class="p">,</span> <span class="n">py</span><span class="o">.</span><span class="n">code</span><span class="o">.</span><span class="n">Traceback</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">excinfo</span><span class="o">.</span><span class="n">exconly</span><span class="p">()</span>
|
||||
<span class="go">"NameError: name 'foobar' is not defined"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">4. py.code</a><ul>
|
||||
<li><a class="reference external" href="#contents-of-the-library">4.1. Contents of the library</a></li>
|
||||
<li><a class="reference external" href="#the-wrappers">4.2. The wrappers</a><ul>
|
||||
<li><a class="reference external" href="#py-code-code">4.2.1. <tt class="docutils literal"><span class="pre">py.code.Code</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-code-source">4.2.2. <tt class="docutils literal"><span class="pre">py.code.Source</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-code-traceback">4.2.3. <tt class="docutils literal"><span class="pre">py.code.Traceback</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-code-frame">4.2.4. <tt class="docutils literal"><span class="pre">py.code.Frame</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-code-exceptioninfo">4.2.5. <tt class="docutils literal"><span class="pre">py.code.ExceptionInfo</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="path.html"
|
||||
title="previous chapter">3. py.path</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="bin.html"
|
||||
title="next chapter">5. <tt class="docutils literal"><span class="pre">py/bin/</span></tt> scripts</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/code.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="bin.html" title="5. py/bin/ scripts"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="path.html" title="3. py.path"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,153 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>12. Coding Style for the Py lib and friendly applications — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="coding-style-for-the-py-lib-and-friendly-applications">
|
||||
<h1>12. Coding Style for the Py lib and friendly applications<a class="headerlink" href="#coding-style-for-the-py-lib-and-friendly-applications" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="honour-pep-8-style-guide-for-python-code">
|
||||
<h2>12.1. Honour PEP 8: Style Guide for Python Code<a class="headerlink" href="#honour-pep-8-style-guide-for-python-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>First of all, if you haven’t already read it, read the <a class="reference external" href="http://www.python.org/peps/pep-0008.html">PEP 8
|
||||
Style Guide for Python Code</a> which, if in doubt, serves as
|
||||
the default coding-style for the py lib.</p>
|
||||
</div>
|
||||
<div class="section" id="documentation-and-testing">
|
||||
<h2>12.2. Documentation and Testing<a class="headerlink" href="#documentation-and-testing" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>generally we want to drive and interweave coding of
|
||||
documentation, tests and real code as much as possible.
|
||||
Without good documentation others may never know about
|
||||
your latest and greatest feature.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="naming">
|
||||
<h2>12.3. naming<a class="headerlink" href="#naming" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>directories, modules and namespaces are always <strong>lowercase</strong></li>
|
||||
<li>classes and especially Exceptions are most often <strong>CamelCase</strong></li>
|
||||
<li>types, i.e. very widely usable classes like the <tt class="docutils literal"><span class="pre">py.path</span></tt>
|
||||
family are all lower case.</li>
|
||||
<li>never use plural names in directory and file names</li>
|
||||
<li>functions/methods are lowercase and <tt class="docutils literal"><span class="pre">_</span></tt> - separated if
|
||||
you really need to separate at all</li>
|
||||
<li>it’s appreciated if you manage to name files in a directory
|
||||
so that tab-completion on the shell level is as easy as possible.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="committing">
|
||||
<h2>12.4. committing<a class="headerlink" href="#committing" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>adding features requires adding appropriate tests.</li>
|
||||
<li>bug fixes should be encoded in a test before being fixed.</li>
|
||||
<li>write telling log messages because several people
|
||||
will read your diffs, and we plan to have a search facility
|
||||
over the py lib’s subversion repository.</li>
|
||||
<li>if you add <tt class="docutils literal"><span class="pre">.txt</span></tt> or <tt class="docutils literal"><span class="pre">.py</span></tt> files to the repository then
|
||||
please make sure you have <tt class="docutils literal"><span class="pre">svn:eol-style</span></tt> set to native.
|
||||
which allows checkin/checkout in native line-ending format.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="miscellaneous">
|
||||
<h2>12.5. Miscellaneous<a class="headerlink" href="#miscellaneous" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Tests are the insurance that your code will be maintained
|
||||
further and survives major releases.</li>
|
||||
<li>Try to put the tests close to the tested code, don’t
|
||||
overload directories with names.</li>
|
||||
<li>If you think of exporting new py lib APIs, discuss it first on the
|
||||
<a class="reference external" href="http://codespeak.net/mailman/listinfo/py-dev">py-dev mailing list</a> and possibly write a chapter in our
|
||||
<cite>future_</cite> book. Communication is considered a key here to make
|
||||
sure that the py lib develops in a consistent way.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">12. Coding Style for the Py lib and friendly applications</a><ul>
|
||||
<li><a class="reference external" href="#honour-pep-8-style-guide-for-python-code">12.1. Honour PEP 8: Style Guide for Python Code</a></li>
|
||||
<li><a class="reference external" href="#documentation-and-testing">12.2. Documentation and Testing</a></li>
|
||||
<li><a class="reference external" href="#naming">12.3. naming</a></li>
|
||||
<li><a class="reference external" href="#committing">12.4. committing</a></li>
|
||||
<li><a class="reference external" href="#miscellaneous">12.5. Miscellaneous</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/coding-style.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,115 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>14. Contact and communication — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="15. Downloading" href="download.html" />
|
||||
<link rel="prev" title="13. Links" href="links.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="download.html" title="15. Downloading"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="links.html" title="13. Links"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="contact-and-communication">
|
||||
<h1>14. Contact and communication<a class="headerlink" href="#contact-and-communication" title="Permalink to this headline">¶</a></h1>
|
||||
<ul class="simple">
|
||||
<li><strong>#pylib on irc.freenode.net</strong>: you are welcome to lurk or ask questions!</li>
|
||||
<li><a class="reference external" href="http://codespeak.net/mailman/listinfo/py-dev">py-dev developers list</a> development mailing list.</li>
|
||||
<li><a class="reference external" href="http://tetamap.wordpress.com">tetamap</a>: Holger Krekel’s blog, often about testing and py.test related news.</li>
|
||||
<li><a class="reference external" href="http://codespeak.net/mailman/listinfo/py-svn">py-svn general commit mailing list</a> to follow all development commits.</li>
|
||||
<li><a class="reference external" href="https://codespeak.net/issue/py-dev/">development bug/feature tracker</a> this roundup instance serves to file bugs and track issues.
|
||||
(soon to be substitued by a google-code or other hosted one).</li>
|
||||
<li><a class="reference external" href="http://merlinux.eu">merlinux.eu</a> offers teaching and consulting services.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="links.html"
|
||||
title="previous chapter">13. Links</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="download.html"
|
||||
title="next chapter">15. Downloading</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/contact.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="download.html" title="15. Downloading"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="links.html" title="13. Links"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,184 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title> — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<p>Contents:</p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference external" href="test.html">1. py.test</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-quickstart.html">1.1. Quickstart</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-features.html">1.2. Features</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-plugins.html">1.3. Included plugins</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-ext.html">1.4. Writing plugins</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-dist.html">1.5. Distributed testing</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-config.html">1.6. Test configuration</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-examples.html">1.7. Working Examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="impl-test.html">1.8. Implementation and Customization of <tt class="docutils literal"><span class="pre">py.test</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="execnet.html">2. py.execnet</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#gateways-immediately-spawn-local-or-remote-process">2.1. Gateways: immediately spawn local or remote process</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#remote-exec-execute-source-code-remotely">2.2. remote_exec: execute source code remotely</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#channels-bidirectionally-exchange-data-between-hosts">2.3. Channels: bidirectionally exchange data between hosts</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#xspec-string-specification-for-gateway-type-and-configuration">2.4. XSpec: string specification for gateway type and configuration</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#examples-of-py-execnet-usage">2.5. Examples of py.execnet usage</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="path.html">3. py.path</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#path-implementations-provided-by-py-path">3.1. Path implementations provided by <tt class="docutils literal"><span class="pre">py.path</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#common-vs-specific-api">3.2. Common vs. specific API</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#known-problems-limitations">3.3. Known problems / limitations</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#future-plans">3.4. Future plans</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="code.html">4. py.code</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="code.html#contents-of-the-library">4.1. Contents of the library</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="code.html#the-wrappers">4.2. The wrappers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="bin.html">5. <tt class="docutils literal"><span class="pre">py/bin/</span></tt> scripts</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-test">5.1. <tt class="docutils literal"><span class="pre">py.test</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-cleanup">5.2. <tt class="docutils literal"><span class="pre">py.cleanup</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-countloc">5.3. <tt class="docutils literal"><span class="pre">py.countloc</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-lookup">5.4. <tt class="docutils literal"><span class="pre">py.lookup</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-rest">5.5. <tt class="docutils literal"><span class="pre">py.rest</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="xml.html">6. py.xml: Lightweight and flexible xml/html generation</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="xml.html#motivation">6.1. Motivation</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="xml.html#a-pythonic-object-model-please">6.2. a pythonic object model , please</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="io.html">7. py.io</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="io.html#io-capturing-examples">7.1. IO Capturing examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="log.html">8. py.log documentation and musings</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="log.html#foreword">8.1. Foreword</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="log.html#logging-organisation">8.2. Logging organisation</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="log.html#using-the-py-log-library">8.3. Using the py.log library</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="misc.html">9. Miscellaneous features of the py lib</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="misc.html#mapping-the-standard-python-library-into-py">9.1. Mapping the standard python library into py</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="misc.html#support-for-interaction-with-system-utilities-binaries">9.2. Support for interaction with system utilities/binaries</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="misc.html#cross-python-version-compatibility-helpers">9.3. Cross-Python Version compatibility helpers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="why_py.html">10. Why, who, what and how do you do <em>the py lib</em>?</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#why-did-we-start-the-py-lib">10.1. Why did we start the py lib?</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#what-is-the-py-libs-current-focus">10.2. What is the py libs current focus?</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#how-does-py-development-work">10.3. How does py development work?</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#who-is-we">10.4. Who is “we”?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="future.html">11. Visions and ideas for further development of the py lib</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#distribute-tests-ad-hoc-across-multiple-platforms">11.1. Distribute tests ad-hoc across multiple platforms</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#make-apigen-useful-for-more-projects">11.2. Make APIGEN useful for more projects</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#consider-apigen-and-pdb-integration">11.3. Consider APIGEN and pdb integration</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#distribute-channels-programs-across-networks">11.4. Distribute channels/programs across networks</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#benchmarking-and-persistent-storage">11.5. Benchmarking and persistent storage</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#refactor-path-implementations-to-use-a-filesystem-abstraction">11.6. Refactor path implementations to use a Filesystem Abstraction</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#integrate-interactive-completion">11.7. Integrate interactive completion</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#consider-more-features">11.8. Consider more features</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="coding-style.html">12. Coding Style for the Py lib and friendly applications</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#honour-pep-8-style-guide-for-python-code">12.1. Honour PEP 8: Style Guide for Python Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#documentation-and-testing">12.2. Documentation and Testing</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#naming">12.3. naming</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#committing">12.4. committing</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#miscellaneous">12.5. Miscellaneous</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="download.html">13. “easy_install py”</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="download.html#installing-on-debian-or-fedora">14. Installing on Debian or Fedora</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="download.html#downloading-a-tar-zip-archive-and-installing-that">15. Downloading a tar/zip archive and installing that</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="download.html#installing-from-subversion-develop-mode">16. Installing from subversion / develop mode</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="download.html#working-with-multiple-py-lib-versions-svn-externals">17. Working with multiple py lib versions / svn externals</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="links.html">18. Links</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="contact.html">19. py lib contact and communication</a></li>
|
||||
</ul>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="genindex.html"><em>Index</em></a></li>
|
||||
<li><a class="reference external" href="modindex.html"><em>Module Index</em></a></li>
|
||||
<li><a class="reference external" href="search.html"><em>Search Page</em></a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/contents.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,203 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>15. Downloading — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="16. Release notes" href="releases.html" />
|
||||
<link rel="prev" title="14. Contact and communication" href="contact.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="releases.html" title="16. Release notes"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="contact.html" title="14. Contact and communication"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="downloading">
|
||||
<h1>15. Downloading<a class="headerlink" href="#downloading" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="easy-install-py">
|
||||
<h2>15.1. “easy_install py”<a class="headerlink" href="#easy-install-py" title="Permalink to this headline">¶</a></h2>
|
||||
<p>With a working <a class="reference external" href="http://pypi.python.org/pypi/setuptools">setuptools installation</a> you can install from the command line:</p>
|
||||
<div class="highlight-python"><pre>easy_install -U py</pre>
|
||||
</div>
|
||||
<p>to get the latest release of the py lib. The <tt class="docutils literal"><span class="pre">-U</span></tt> switch
|
||||
will trigger an upgrade if you already have an older version installed.
|
||||
The py lib and its tools are expected to work well on Linux,
|
||||
Windows and OSX, Python versions 2.3, 2.4, 2.5 and 2.6.</p>
|
||||
<p>We provide binary eggs for Windows machines.</p>
|
||||
<p>On other systems you need a working C-compiler in order to
|
||||
install the full py lib. If you don’t have a compiler available
|
||||
you can still install the py lib but without greenlets - look
|
||||
below for the <tt class="docutils literal"><span class="pre">install_lib</span></tt> target.</p>
|
||||
<p><strong>IMPORTANT NOTE</strong>: if you are using Windows and have previous
|
||||
installations of the py lib on your system, please download
|
||||
and execute <a class="reference external" href="http://codespeak.net/svn/py/build/winpathclean.py">http://codespeak.net/svn/py/build/winpathclean.py</a>
|
||||
This will check that no previous files are getting in the way.
|
||||
(Unfortunately we don’t know about a way to execute this
|
||||
code automatically during the above install).</p>
|
||||
</div>
|
||||
<div class="section" id="installing-on-debian-or-fedora">
|
||||
<h2>15.2. Installing on Debian or Fedora<a class="headerlink" href="#installing-on-debian-or-fedora" title="Permalink to this headline">¶</a></h2>
|
||||
<p>On Debian systems look for <tt class="docutils literal"><span class="pre">python-codespeak-lib</span></tt>.
|
||||
<em>This package is probably outdated - if somebody
|
||||
can help with bringing this up to date,
|
||||
that would be very much appreciated.</em></p>
|
||||
<p>Dwayne Bailey has thankfully put together a Fedora <a class="reference external" href="http://translate.sourceforge.net/releases/testing/fedora/pylib-0.9.2-1.fc9.noarch.rpm">RPM</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="downloading-a-tar-zip-archive-and-installing-that">
|
||||
<h2>15.3. Downloading a tar/zip archive and installing that<a class="headerlink" href="#downloading-a-tar-zip-archive-and-installing-that" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Go to the python package index (pypi) and download a tar or zip file:</p>
|
||||
<blockquote>
|
||||
<a class="reference external" href="http://pypi.python.org/pypi/py/">http://pypi.python.org/pypi/py/</a></blockquote>
|
||||
<p>and unpack it to a directory, where you then type:</p>
|
||||
<div class="highlight-python"><pre>python setup.py install</pre>
|
||||
</div>
|
||||
<p>If you don’t have a working C-compiler you can do:</p>
|
||||
<div class="highlight-python"><pre>python setup.py install_lib</pre>
|
||||
</div>
|
||||
<p>You will then not be able to use greenlets but otherwise
|
||||
<tt class="docutils literal"><span class="pre">py.test</span></tt> and all tools and APIs are fine to use.</p>
|
||||
</div>
|
||||
<div class="section" id="installing-from-subversion-develop-mode">
|
||||
<h2>15.4. Installing from subversion / develop mode<a class="headerlink" href="#installing-from-subversion-develop-mode" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To follow development or help with fixing things
|
||||
for the next release, checkout the complete code
|
||||
and documentation source:</p>
|
||||
<div class="highlight-python"><pre>svn co http://codespeak.net/svn/py/release/0.9.x py-0.9.x</pre>
|
||||
</div>
|
||||
<p>You can then issue:</p>
|
||||
<div class="highlight-python"><pre>python setup.py develop</pre>
|
||||
</div>
|
||||
<p>in order to work with your checkout version.</p>
|
||||
<p>other interesting svn checkout points:</p>
|
||||
<div class="highlight-python"><pre>http://codespeak.net/
|
||||
svn/py/release # release tags and branches
|
||||
svn/py/dist # latest stable (may or may not be a release)
|
||||
svn/py/trunk # head development / merge point</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="working-with-multiple-py-lib-versions-svn-externals">
|
||||
<h2>15.5. Working with multiple py lib versions / svn externals<a class="headerlink" href="#working-with-multiple-py-lib-versions-svn-externals" title="Permalink to this headline">¶</a></h2>
|
||||
<p>If you happen to have multiple versions of the py lib
|
||||
around or you ship the py lib as an svn-external to
|
||||
then you might want to use py lib scripts more directly.
|
||||
For example if you have a project layout like this:</p>
|
||||
<div class="highlight-python"><pre>mypkg/
|
||||
subpkg1/
|
||||
tests/
|
||||
tests/
|
||||
py/ # as svn-external, could be specific tag/version</pre>
|
||||
</div>
|
||||
<p>then you want to make sure that the actual local py lib is used
|
||||
and not another system-wide version. For this you need to add
|
||||
<tt class="docutils literal"><span class="pre">py/bin</span></tt> or <tt class="docutils literal"><span class="pre">py\bin\win32</span></tt> respectively to your system’s PATH settings.</p>
|
||||
<p>You can do this by executing (on windows) a script to set the environment:</p>
|
||||
<div class="highlight-python"><pre>c:\\path\to\checkout\py\env.cmd</pre>
|
||||
</div>
|
||||
<p>or on linux/osx you can add something like this to your shell
|
||||
initialization:</p>
|
||||
<div class="highlight-python"><pre>eval `python ~/path/to/checkout/py/env.py`</pre>
|
||||
</div>
|
||||
<p>to get good settings for PYTHONPATH and PATH.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">15. Downloading</a><ul>
|
||||
<li><a class="reference external" href="#easy-install-py">15.1. “easy_install py”</a></li>
|
||||
<li><a class="reference external" href="#installing-on-debian-or-fedora">15.2. Installing on Debian or Fedora</a></li>
|
||||
<li><a class="reference external" href="#downloading-a-tar-zip-archive-and-installing-that">15.3. Downloading a tar/zip archive and installing that</a></li>
|
||||
<li><a class="reference external" href="#installing-from-subversion-develop-mode">15.4. Installing from subversion / develop mode</a></li>
|
||||
<li><a class="reference external" href="#working-with-multiple-py-lib-versions-svn-externals">15.5. Working with multiple py lib versions / svn externals</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="contact.html"
|
||||
title="previous chapter">14. Contact and communication</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="releases.html"
|
||||
title="next chapter">16. Release notes</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/download.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="releases.html" title="16. Release notes"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="contact.html" title="14. Contact and communication"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,340 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>2. py.execnet — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="3. py.path" href="path.html" />
|
||||
<link rel="prev" title="1.7. Working Examples" href="test-examples.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="path.html" title="3. py.path"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-examples.html" title="1.7. Working Examples"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-execnet">
|
||||
<h1>2. py.execnet<a class="headerlink" href="#py-execnet" title="Permalink to this headline">¶</a></h1>
|
||||
<p><tt class="docutils literal"><span class="pre">py.execnet</span></tt> allows to:</p>
|
||||
<ul class="simple">
|
||||
<li>instantiate local or remote Python Processes</li>
|
||||
<li>send code for execution in one or many processes</li>
|
||||
<li>asynchronously send and receive data between processes through channels</li>
|
||||
<li>completely avoid manual installation steps on remote places</li>
|
||||
</ul>
|
||||
<div class="section" id="gateways-immediately-spawn-local-or-remote-process">
|
||||
<h2>2.1. Gateways: immediately spawn local or remote process<a class="headerlink" href="#gateways-immediately-spawn-local-or-remote-process" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In order to send code to a remote place or a subprocess
|
||||
you need to instantiate a so-called Gateway object.
|
||||
There are currently three Gateway classes:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">py.execnet.PopenGateway</span></tt> to open a subprocess
|
||||
on the local machine. Useful for making use
|
||||
of multiple processors to to contain code execution
|
||||
in a separated environment.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">py.execnet.SshGateway</span></tt> to connect to
|
||||
a remote ssh server and distribute execution to it.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">py.execnet.SocketGateway</span></tt> a way to connect to
|
||||
a remote Socket based server. <em>Note</em> that this method
|
||||
requires a manually started
|
||||
:source:py/execnet/script/socketserver.py
|
||||
script. You can run this “server script” without
|
||||
having the py lib installed on the remote system
|
||||
and you can setup it up as permanent service.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="remote-exec-execute-source-code-remotely">
|
||||
<h2>2.2. remote_exec: execute source code remotely<a class="headerlink" href="#remote-exec-execute-source-code-remotely" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All gateways offer remote code execution via this high level function:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">remote_exec</span><span class="p">(</span><span class="n">source</span><span class="p">):</span>
|
||||
<span class="sd">"""return channel object for communicating with the asynchronously</span>
|
||||
<span class="sd"> executing 'source' code which will have a corresponding 'channel'</span>
|
||||
<span class="sd"> object in its executing namespace."""</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>With <cite>remote_exec</cite> you send source code to the other
|
||||
side and get both a local and a remote <a class="reference internal" href="#channel">Channel</a> object,
|
||||
which you can use to have the local and remote site
|
||||
communicate data in a structured way. Here is
|
||||
an example for reading the PID:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="n">gw</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">channel</span> <span class="o">=</span> <span class="n">gw</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"""</span>
|
||||
<span class="gp">... </span><span class="s"> import os</span>
|
||||
<span class="gp">... </span><span class="s"> channel.send(os.getpid())</span>
|
||||
<span class="gp">... </span><span class="s">"""</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">remote_pid</span> <span class="o">=</span> <span class="n">channel</span><span class="o">.</span><span class="n">receive</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">remote_pid</span> <span class="o">!=</span> <span class="n">py</span><span class="o">.</span><span class="n">std</span><span class="o">.</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="channels-bidirectionally-exchange-data-between-hosts">
|
||||
<span id="exchange-data"></span><span id="channel-api"></span><span id="channel"></span><h2>2.3. Channels: bidirectionally exchange data between hosts<a class="headerlink" href="#channels-bidirectionally-exchange-data-between-hosts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A channel object allows to send and receive data between
|
||||
two asynchronously running programs. When calling
|
||||
<cite>remote_exec</cite> you will get a channel object back and
|
||||
the code fragment running on the other side will
|
||||
see a channel object in its global namespace.</p>
|
||||
<p>Here is the interface of channel objects:</p>
|
||||
<div class="highlight-python"><pre>#
|
||||
# API for sending and receiving anonymous values
|
||||
#
|
||||
channel.send(item):
|
||||
sends the given item to the other side of the channel,
|
||||
possibly blocking if the sender queue is full.
|
||||
Note that items need to be marshallable (all basic
|
||||
python types are).
|
||||
|
||||
channel.receive():
|
||||
receives an item that was sent from the other side,
|
||||
possibly blocking if there is none.
|
||||
Note that exceptions from the other side will be
|
||||
reraised as gateway.RemoteError exceptions containing
|
||||
a textual representation of the remote traceback.
|
||||
|
||||
channel.waitclose(timeout=None):
|
||||
wait until this channel is closed. Note that a closed
|
||||
channel may still hold items that will be received or
|
||||
send. Note that exceptions from the other side will be
|
||||
reraised as gateway.RemoteError exceptions containing
|
||||
a textual representation of the remote traceback.
|
||||
|
||||
channel.close():
|
||||
close this channel on both the local and the remote side.
|
||||
A remote side blocking on receive() on this channel
|
||||
will get woken up and see an EOFError exception.</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="xspec-string-specification-for-gateway-type-and-configuration">
|
||||
<span id="xspec"></span><h2>2.4. XSpec: string specification for gateway type and configuration<a class="headerlink" href="#xspec-string-specification-for-gateway-type-and-configuration" title="Permalink to this headline">¶</a></h2>
|
||||
<p><tt class="docutils literal"><span class="pre">py.execnet</span></tt> supports a simple extensible format for
|
||||
specifying and configuring Gateways for remote execution.
|
||||
You can use a string specification to instantiate a new gateway,
|
||||
for example a new SshGateway:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">gateway</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">makegateway</span><span class="p">(</span><span class="s">"ssh=myhost"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s look at some examples for valid specifications.
|
||||
Specification for an ssh connection to <cite>wyvern</cite>, running on python2.4 in the (newly created) ‘mycache’ subdirectory:</p>
|
||||
<div class="highlight-python"><pre>ssh=wyvern//python=python2.4//chdir=mycache</pre>
|
||||
</div>
|
||||
<p>Specification of a python2.5 subprocess; with a low CPU priority (“nice” level). Current dir will be the current dir of the instantiator (that’s true for all ‘popen’ specifications unless they specify ‘chdir’):</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">popen</span><span class="o">//</span><span class="n">python</span><span class="o">=</span><span class="mf">2.5</span><span class="o">//</span><span class="n">nice</span><span class="o">=</span><span class="mf">20</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Specification of a Python Socket server process that listens on 192.168.1.4:8888; current dir will be the ‘pyexecnet-cache’ sub directory which is used a default for all remote processes:</p>
|
||||
<div class="highlight-python"><pre>socket=192.168.1.4:8888</pre>
|
||||
</div>
|
||||
<p>More generally, a specification string has this general format:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">key1</span><span class="o">=</span><span class="n">value1</span><span class="o">//</span><span class="n">key2</span><span class="o">=</span><span class="n">value2</span><span class="o">//</span><span class="n">key3</span><span class="o">=</span><span class="n">value3</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you omit a value, a boolean true value is assumed. Currently
|
||||
the following key/values are supported:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">popen</span></tt> for a PopenGateway</li>
|
||||
<li><tt class="docutils literal"><span class="pre">ssh=host</span></tt> for a SshGateway</li>
|
||||
<li><tt class="docutils literal"><span class="pre">socket=address:port</span></tt> for a SocketGateway</li>
|
||||
<li><tt class="docutils literal"><span class="pre">python=executable</span></tt> for specifying Python executables</li>
|
||||
<li><tt class="docutils literal"><span class="pre">chdir=path</span></tt> change remote working dir to given relative or absolute path</li>
|
||||
<li><tt class="docutils literal"><span class="pre">nice=value</span></tt> decrease remote nice level if platforms supports it</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="examples-of-py-execnet-usage">
|
||||
<h2>2.5. Examples of py.execnet usage<a class="headerlink" href="#examples-of-py-execnet-usage" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="compare-cwd-of-popen-gateways">
|
||||
<h3>2.5.1. Compare cwd() of Popen Gateways<a class="headerlink" href="#compare-cwd-of-popen-gateways" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A PopenGateway has the same working directory as the instantiatior:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span><span class="o">,</span> <span class="nn">os</span>
|
||||
<span class="gp">>>> </span><span class="n">gw</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">ch</span> <span class="o">=</span> <span class="n">gw</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"import os; channel.send(os.getcwd())"</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">res</span> <span class="o">=</span> <span class="n">ch</span><span class="o">.</span><span class="n">receive</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">res</span> <span class="o">==</span> <span class="n">os</span><span class="o">.</span><span class="n">getcwd</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">gw</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="synchronously-receive-results-from-two-sub-processes">
|
||||
<h3>2.5.2. Synchronously receive results from two sub processes<a class="headerlink" href="#synchronously-receive-results-from-two-sub-processes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Use MultiChannels for receiving multiple results from remote code:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="n">ch1</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"channel.send(1)"</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">ch2</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"channel.send(2)"</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">mch</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">MultiChannel</span><span class="p">([</span><span class="n">ch1</span><span class="p">,</span> <span class="n">ch2</span><span class="p">])</span>
|
||||
<span class="gp">>>> </span><span class="n">l</span> <span class="o">=</span> <span class="n">mch</span><span class="o">.</span><span class="n">receive_each</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="o">==</span> <span class="mf">2</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="mf">1</span> <span class="ow">in</span> <span class="n">l</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="mf">2</span> <span class="ow">in</span> <span class="n">l</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="asynchronously-receive-results-from-two-sub-processes">
|
||||
<h3>2.5.3. Asynchronously receive results from two sub processes<a class="headerlink" href="#asynchronously-receive-results-from-two-sub-processes" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Use <tt class="docutils literal"><span class="pre">MultiChannel.make_receive_queue()</span></tt> for asynchronously receiving
|
||||
multiple results from remote code. This standard Queue provides
|
||||
<tt class="docutils literal"><span class="pre">(channel,</span> <span class="pre">result)</span></tt> tuples which allows to determine where
|
||||
a result comes from:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="n">ch1</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"channel.send(1)"</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">ch2</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"channel.send(2)"</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">mch</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">MultiChannel</span><span class="p">([</span><span class="n">ch1</span><span class="p">,</span> <span class="n">ch2</span><span class="p">])</span>
|
||||
<span class="gp">>>> </span><span class="n">queue</span> <span class="o">=</span> <span class="n">mch</span><span class="o">.</span><span class="n">make_receive_queue</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">chan1</span><span class="p">,</span> <span class="n">res1</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="c"># you may also specify a timeout</span>
|
||||
<span class="gp">>>> </span><span class="n">chan2</span><span class="p">,</span> <span class="n">res2</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">res1</span> <span class="o">+</span> <span class="n">res2</span>
|
||||
<span class="go">3</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">chan1</span> <span class="ow">in</span> <span class="p">(</span><span class="n">ch1</span><span class="p">,</span> <span class="n">ch2</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">chan2</span> <span class="ow">in</span> <span class="p">(</span><span class="n">ch1</span><span class="p">,</span> <span class="n">ch2</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">chan1</span> <span class="o">!=</span> <span class="n">chan2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="receive-file-contents-from-remote-ssh-account">
|
||||
<h3>2.5.4. Receive file contents from remote SSH account<a class="headerlink" href="#receive-file-contents-from-remote-ssh-account" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Here is a small program that you can use to retrieve
|
||||
contents of remote files:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="c"># open a gateway to a fresh child process</span>
|
||||
<span class="n">gw</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">SshGateway</span><span class="p">(</span><span class="s">'codespeak.net'</span><span class="p">)</span>
|
||||
<span class="n">channel</span> <span class="o">=</span> <span class="n">gw</span><span class="o">.</span><span class="n">remote_exec</span><span class="p">(</span><span class="s">"""</span>
|
||||
<span class="s"> for fn in channel:</span>
|
||||
<span class="s"> f = open(fn, 'rb')</span>
|
||||
<span class="s"> channel.send(f.read())</span>
|
||||
<span class="s"> f.close()</span>
|
||||
<span class="s">"""</span><span class="p">)</span>
|
||||
|
||||
<span class="k">for</span> <span class="n">fn</span> <span class="ow">in</span> <span class="n">somefilelist</span><span class="p">:</span>
|
||||
<span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span>
|
||||
<span class="n">content</span> <span class="o">=</span> <span class="n">channel</span><span class="o">.</span><span class="n">receive</span><span class="p">()</span>
|
||||
<span class="c"># process content</span>
|
||||
|
||||
<span class="c"># later you can exit / close down the gateway</span>
|
||||
<span class="n">gw</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="instantiate-a-socket-server-in-a-new-subprocess">
|
||||
<h3>2.5.5. Instantiate a socket server in a new subprocess<a class="headerlink" href="#instantiate-a-socket-server-in-a-new-subprocess" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The following example opens a PopenGateway, i.e. a python
|
||||
child process, and starts a socket server within that process
|
||||
and then opens a second gateway to the freshly started
|
||||
socketserver:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">py</span>
|
||||
|
||||
<span class="n">popengw</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">PopenGateway</span><span class="p">()</span>
|
||||
<span class="n">socketgw</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">execnet</span><span class="o">.</span><span class="n">SocketGateway</span><span class="o">.</span><span class="n">new_remote</span><span class="p">(</span><span class="n">popengw</span><span class="p">,</span> <span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span> <span class="mf">0</span><span class="p">))</span>
|
||||
|
||||
<span class="k">print</span> <span class="n">socketgw</span><span class="o">.</span><span class="n">_rinfo</span><span class="p">()</span> <span class="c"># print some info about the remote environment</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">2. py.execnet</a><ul>
|
||||
<li><a class="reference external" href="#gateways-immediately-spawn-local-or-remote-process">2.1. Gateways: immediately spawn local or remote process</a></li>
|
||||
<li><a class="reference external" href="#remote-exec-execute-source-code-remotely">2.2. remote_exec: execute source code remotely</a></li>
|
||||
<li><a class="reference external" href="#channels-bidirectionally-exchange-data-between-hosts">2.3. Channels: bidirectionally exchange data between hosts</a></li>
|
||||
<li><a class="reference external" href="#xspec-string-specification-for-gateway-type-and-configuration">2.4. XSpec: string specification for gateway type and configuration</a></li>
|
||||
<li><a class="reference external" href="#examples-of-py-execnet-usage">2.5. Examples of py.execnet usage</a><ul>
|
||||
<li><a class="reference external" href="#compare-cwd-of-popen-gateways">2.5.1. Compare cwd() of Popen Gateways</a></li>
|
||||
<li><a class="reference external" href="#synchronously-receive-results-from-two-sub-processes">2.5.2. Synchronously receive results from two sub processes</a></li>
|
||||
<li><a class="reference external" href="#asynchronously-receive-results-from-two-sub-processes">2.5.3. Asynchronously receive results from two sub processes</a></li>
|
||||
<li><a class="reference external" href="#receive-file-contents-from-remote-ssh-account">2.5.4. Receive file contents from remote SSH account</a></li>
|
||||
<li><a class="reference external" href="#instantiate-a-socket-server-in-a-new-subprocess">2.5.5. Instantiate a socket server in a new subprocess</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-examples.html"
|
||||
title="previous chapter">1.7. Working Examples</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="path.html"
|
||||
title="next chapter">3. py.path</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/execnet.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="path.html" title="3. py.path"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-examples.html" title="1.7. Working Examples"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,197 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>11. Visions and ideas for further development of the py lib — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="visions-and-ideas-for-further-development-of-the-py-lib">
|
||||
<h1>11. Visions and ideas for further development of the py lib<a class="headerlink" href="#visions-and-ideas-for-further-development-of-the-py-lib" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This document tries to describe directions and guiding ideas
|
||||
for the near-future development of the py lib. <em>Note that all
|
||||
statements within this document - even if they sound factual -
|
||||
mostly just express thoughts and ideas. They not always refer to
|
||||
real code so read with some caution.</em></p>
|
||||
<div class="section" id="distribute-tests-ad-hoc-across-multiple-platforms">
|
||||
<h2>11.1. Distribute tests ad-hoc across multiple platforms<a class="headerlink" href="#distribute-tests-ad-hoc-across-multiple-platforms" title="Permalink to this headline">¶</a></h2>
|
||||
<p>After some more refactoring and unification of
|
||||
the current testing and distribution support code
|
||||
we’d like to be able to run tests on multiple
|
||||
platforms simultanously and allow for interaction
|
||||
and introspection into the (remote) failures.</p>
|
||||
</div>
|
||||
<div class="section" id="make-apigen-useful-for-more-projects">
|
||||
<h2>11.2. Make APIGEN useful for more projects<a class="headerlink" href="#make-apigen-useful-for-more-projects" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The new APIGEN tool offers rich information
|
||||
derived from running tests against an application:
|
||||
argument types and callsites, i.e. it shows
|
||||
the places where a particular API is used.
|
||||
In its first incarnation, there are still
|
||||
some specialties that likely prevent it
|
||||
from documenting APIs for other projects.
|
||||
We’d like to evolve to a <cite>py.apigen</cite> tool
|
||||
that can make use of information provided
|
||||
by a py.test run.</p>
|
||||
</div>
|
||||
<div class="section" id="consider-apigen-and-pdb-integration">
|
||||
<h2>11.3. Consider APIGEN and pdb integration<a class="headerlink" href="#consider-apigen-and-pdb-integration" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The information provided by APIGEN can be used in many
|
||||
different ways. An example of this could be to write
|
||||
an extension to pdb which makes it available.
|
||||
Imagine you could issue a pdb command
|
||||
“info <function name>” and get information
|
||||
regarding incoming, and outgoing types, possible
|
||||
exceptions, field types and call sites.</p>
|
||||
</div>
|
||||
<div class="section" id="distribute-channels-programs-across-networks">
|
||||
<h2>11.4. Distribute channels/programs across networks<a class="headerlink" href="#distribute-channels-programs-across-networks" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Apart from stabilizing setup/teardown procedures
|
||||
for <a class="reference external" href="execnet.html">py.execnet</a>, we’d like to generalize its
|
||||
implementation to allow connecting two programs
|
||||
across multiple hosts, i.e. we’d like to arbitrarily
|
||||
send “channels” across the network. Likely this
|
||||
will be done by using the “pipe” model, i.e.
|
||||
that each channel is actually a pair of endpoints,
|
||||
both of which can be independently transported
|
||||
across the network. The programs who “own”
|
||||
these endpoints remain connected.</p>
|
||||
</div>
|
||||
<div class="section" id="benchmarking-and-persistent-storage">
|
||||
<h2>11.5. Benchmarking and persistent storage<a class="headerlink" href="#benchmarking-and-persistent-storage" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For storing test results, but also benchmarking
|
||||
and other information, we need a solid way
|
||||
to store all kinds of information from test runs.
|
||||
We’d like to generate statistics or html-overview
|
||||
out of it, but also use such information to determine when
|
||||
a certain test broke, or when its performance
|
||||
decreased considerably.</p>
|
||||
</div>
|
||||
<div class="section" id="refactor-path-implementations-to-use-a-filesystem-abstraction">
|
||||
<span id="a-more-general-view-on-path-objects"></span><span id="general-path"></span><h2>11.6. Refactor path implementations to use a Filesystem Abstraction<a class="headerlink" href="#refactor-path-implementations-to-use-a-filesystem-abstraction" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It seems like a good idea to refactor all <a class="reference external" href="http://codespeak.net/py/dist/path.html">py.path</a> Path implementations to
|
||||
use an internal Filesystem abstraction. The current code base
|
||||
would be transformed to have Filesystem implementations for e.g.
|
||||
local, subversion and subversion “working copy” filesystems. Today
|
||||
the according code is scattered through path-handling code.</p>
|
||||
<p>On a related note, Armin Rigo has hacked <a class="reference external" href="http://codespeak.net/svn/user/arigo/hack/pylufs/">pylufs</a> and more recently has
|
||||
written <a class="reference external" href="http://codespeak.net/svn/user/arigo/hack/pyfuse/">pyfuse</a> which allow to
|
||||
implement kernel-level linux filesystems with pure python. Now
|
||||
the idea is that the mentioned filesystem implementations would
|
||||
be directly usable for such linux-filesystem glue code.</p>
|
||||
<p>In other words, implementing a <a class="reference external" href="http://codespeak.net/svn/user/arigo/hack/pyfuse/memoryfs.py">memoryfs</a> or a <a class="reference external" href="http://codespeak.net/pipermail/py-dev/2005-January/000191.html">dictfs</a> would
|
||||
give you two things for free: a filesystem mountable at kernel level
|
||||
as well as a uniform “path” object allowing you to access your
|
||||
filesystem in convenient ways.</p>
|
||||
<p>Also interesting to check out is Will McGugan’s work on
|
||||
his <a class="reference external" href="http://www.willmcgugan.com/2008/09/21/announcing-fs-010-a-python-file-system/#comment-60276">fs package</a>.</p>
|
||||
<p>I think the main question is what the very fundamental
|
||||
filesystem API should look like. Here are some doctests
|
||||
on how a <a class="reference external" href="draft_pyfs">draft py.fs</a> could look like. There also
|
||||
is Matthew Scotts <a class="reference external" href="http://codespeak.net/pipermail/py-dev/attachments/20050128/d9595512/virtual1-0001.bin">dictproxy patch</a> which adds
|
||||
<tt class="docutils literal"><span class="pre">py.path.dict</span></tt> and <tt class="docutils literal"><span class="pre">py.path.proxy</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="integrate-interactive-completion">
|
||||
<h2>11.7. Integrate interactive completion<a class="headerlink" href="#integrate-interactive-completion" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It’d be nice to integrate the bash-like
|
||||
<a class="reference external" href="http://codespeak.net/rlcompleter2/">rlcompleter2</a> python command line completer
|
||||
into the py lib, and making it work remotely
|
||||
and with pdb.</p>
|
||||
</div>
|
||||
<div class="section" id="consider-more-features">
|
||||
<h2>11.8. Consider more features<a class="headerlink" href="#consider-more-features" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are many more features and useful classes
|
||||
that might be nice to integrate. For example, we might put
|
||||
Armin’s <a class="reference external" href="http://codespeak.net/svn/user/arigo/hack/misc/collect.py">lazy list</a> implementation into the py lib.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">11. Visions and ideas for further development of the py lib</a><ul>
|
||||
<li><a class="reference external" href="#distribute-tests-ad-hoc-across-multiple-platforms">11.1. Distribute tests ad-hoc across multiple platforms</a></li>
|
||||
<li><a class="reference external" href="#make-apigen-useful-for-more-projects">11.2. Make APIGEN useful for more projects</a></li>
|
||||
<li><a class="reference external" href="#consider-apigen-and-pdb-integration">11.3. Consider APIGEN and pdb integration</a></li>
|
||||
<li><a class="reference external" href="#distribute-channels-programs-across-networks">11.4. Distribute channels/programs across networks</a></li>
|
||||
<li><a class="reference external" href="#benchmarking-and-persistent-storage">11.5. Benchmarking and persistent storage</a></li>
|
||||
<li><a class="reference external" href="#refactor-path-implementations-to-use-a-filesystem-abstraction">11.6. Refactor path implementations to use a Filesystem Abstraction</a></li>
|
||||
<li><a class="reference external" href="#integrate-interactive-completion">11.7. Integrate interactive completion</a></li>
|
||||
<li><a class="reference external" href="#consider-more-features">11.8. Consider more features</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/future.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Index — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
|
||||
<h1 id="index">Index</h1>
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
|
||||
|
||||
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,342 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.8. Implementation and Customization of py.test — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="2. py.execnet" href="execnet.html" />
|
||||
<link rel="prev" title="1.7. Working Examples" href="test-examples.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="execnet.html" title="2. py.execnet"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-examples.html" title="1.7. Working Examples"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="implementation-and-customization-of-py-test">
|
||||
<h1>1.8. Implementation and Customization of <tt class="docutils literal"><span class="pre">py.test</span></tt><a class="headerlink" href="#implementation-and-customization-of-py-test" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="collecting-and-running-tests-implementation-remarks">
|
||||
<span id="basicpicture"></span><h2>1.8.1. Collecting and running tests / implementation remarks<a class="headerlink" href="#collecting-and-running-tests-implementation-remarks" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In order to customize <tt class="docutils literal"><span class="pre">py.test</span></tt> it’s good to understand
|
||||
its basic architure (WARNING: these are not guaranteed
|
||||
yet to stay the way they are now!):</p>
|
||||
<div class="highlight-python"><pre> ___________________
|
||||
| |
|
||||
| Collector |
|
||||
|___________________|
|
||||
/ \
|
||||
| Item.run()
|
||||
| ^
|
||||
receive test Items /
|
||||
| /execute test Item
|
||||
| /
|
||||
___________________/
|
||||
| |
|
||||
| Session |
|
||||
|___________________|
|
||||
|
||||
.............................
|
||||
. conftest.py configuration .
|
||||
. cmdline options .
|
||||
.............................</pre>
|
||||
</div>
|
||||
<p>The <em>Session</em> basically receives test <em>Items</em> from a <em>Collector</em>,
|
||||
and executes them via the <tt class="docutils literal"><span class="pre">Item.run()</span></tt> method. It monitors
|
||||
the outcome of the test and reports about failures and successes.</p>
|
||||
<div class="section" id="collectors-and-the-test-collection-process">
|
||||
<span id="collection-process"></span><h3>1.8.1.1. Collectors and the test collection process<a class="headerlink" href="#collectors-and-the-test-collection-process" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The collecting process is iterative, i.e. the session
|
||||
traverses and generates a <em>collector tree</em>. Here is an example of such
|
||||
a tree, generated with the command <tt class="docutils literal"><span class="pre">py.test</span> <span class="pre">--collectonly</span> <span class="pre">py/xmlobj</span></tt>:</p>
|
||||
<div class="highlight-python"><pre><Directory 'xmlobj'>
|
||||
<Directory 'testing'>
|
||||
<Module 'test_html.py' (py.__.xmlobj.testing.test_html)>
|
||||
<Function 'test_html_name_stickyness'>
|
||||
<Function 'test_stylenames'>
|
||||
<Function 'test_class_None'>
|
||||
<Function 'test_alternating_style'>
|
||||
<Module 'test_xml.py' (py.__.xmlobj.testing.test_xml)>
|
||||
<Function 'test_tag_with_text'>
|
||||
<Function 'test_class_identity'>
|
||||
<Function 'test_tag_with_text_and_attributes'>
|
||||
<Function 'test_tag_with_subclassed_attr_simple'>
|
||||
<Function 'test_tag_nested'>
|
||||
<Function 'test_tag_xmlname'></pre>
|
||||
</div>
|
||||
<p>By default all directories not starting with a dot are traversed,
|
||||
looking for <tt class="docutils literal"><span class="pre">test_*.py</span></tt> and <tt class="docutils literal"><span class="pre">*_test.py</span></tt> files. Those files
|
||||
are imported under their <a class="reference internal" href="#package-name">package name</a>.</p>
|
||||
<p>The Module collector looks for test functions
|
||||
and test classes and methods. Test functions and methods
|
||||
are prefixed <tt class="docutils literal"><span class="pre">test</span></tt> by default. Test classes must
|
||||
start with a capitalized <tt class="docutils literal"><span class="pre">Test</span></tt> prefix.</p>
|
||||
</div>
|
||||
<div class="section" id="test-items-are-collectors-as-well">
|
||||
<span id="collector-api"></span><h3>1.8.1.2. test items are collectors as well<a class="headerlink" href="#test-items-are-collectors-as-well" title="Permalink to this headline">¶</a></h3>
|
||||
<p>To make the reporting life simple for the session object
|
||||
items offer a <tt class="docutils literal"><span class="pre">run()</span></tt> method as well. In fact the session
|
||||
distinguishes “collectors” from “items” solely by interpreting
|
||||
their return value. If it is a list, then we recurse into
|
||||
it, otherwise we consider the “test” as passed.</p>
|
||||
</div>
|
||||
<div class="section" id="constructing-the-package-name-for-test-modules">
|
||||
<span id="package-name"></span><h3>1.8.1.3. constructing the package name for test modules<a class="headerlink" href="#constructing-the-package-name-for-test-modules" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Test modules are imported under their fully qualified
|
||||
name. Given a filesystem <tt class="docutils literal"><span class="pre">fspath</span></tt> it is constructed as follows:</p>
|
||||
<ul class="simple">
|
||||
<li>walk the directories up to the last one that contains
|
||||
an <tt class="docutils literal"><span class="pre">__init__.py</span></tt> file.</li>
|
||||
<li>perform <tt class="docutils literal"><span class="pre">sys.path.insert(0,</span> <span class="pre">basedir)</span></tt>.</li>
|
||||
<li>import the root package as <tt class="docutils literal"><span class="pre">root</span></tt></li>
|
||||
<li>determine the fully qualified name for <tt class="docutils literal"><span class="pre">fspath</span></tt> by either:<ul>
|
||||
<li>calling <tt class="docutils literal"><span class="pre">root.__pkg__.getimportname(fspath)</span></tt> if the
|
||||
<tt class="docutils literal"><span class="pre">__pkg__</span></tt> exists.` or</li>
|
||||
<li>otherwise use the relative path of the module path to
|
||||
the base dir and turn slashes into dots and strike
|
||||
the trailing <tt class="docutils literal"><span class="pre">.py</span></tt>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="customizing-the-testing-process">
|
||||
<h2>1.8.2. Customizing the testing process<a class="headerlink" href="#customizing-the-testing-process" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="writing-conftest-py-files">
|
||||
<h3>1.8.2.1. writing conftest.py files<a class="headerlink" href="#writing-conftest-py-files" title="Permalink to this headline">¶</a></h3>
|
||||
<p>You may put conftest.py files containing project-specific
|
||||
configuration in your project’s root directory, it’s usually
|
||||
best to put it just into the same directory level as your
|
||||
topmost <tt class="docutils literal"><span class="pre">__init__.py</span></tt>. In fact, <tt class="docutils literal"><span class="pre">py.test</span></tt> performs
|
||||
an “upwards” search starting from the directory that you specify
|
||||
to be tested and will lookup configuration values right-to-left.
|
||||
You may have options that reside e.g. in your home directory
|
||||
but note that project specific settings will be considered
|
||||
first. There is a flag that helps you debugging your
|
||||
conftest.py configurations:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">--</span><span class="n">traceconfig</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="customizing-the-collecting-and-running-process">
|
||||
<h3>1.8.2.2. customizing the collecting and running process<a class="headerlink" href="#customizing-the-collecting-and-running-process" title="Permalink to this headline">¶</a></h3>
|
||||
<p>To introduce different test items you can create
|
||||
one or more <tt class="docutils literal"><span class="pre">conftest.py</span></tt> files in your project.
|
||||
When the collection process traverses directories
|
||||
and modules the default collectors will produce
|
||||
custom Collectors and Items if they are found
|
||||
in a local <tt class="docutils literal"><span class="pre">conftest.py</span></tt> file.</p>
|
||||
<div class="section" id="example-perform-additional-rest-checks">
|
||||
<h4>1.8.2.2.1. example: perform additional ReST checks<a class="headerlink" href="#example-perform-additional-rest-checks" title="Permalink to this headline">¶</a></h4>
|
||||
<p>With your custom collectors or items you can completely
|
||||
derive from the standard way of collecting and running
|
||||
tests in a localized manner. Let’s look at an example.
|
||||
If you invoke <tt class="docutils literal"><span class="pre">py.test</span> <span class="pre">--collectonly</span> <span class="pre">py/documentation</span></tt>
|
||||
then you get:</p>
|
||||
<div class="highlight-python"><pre><DocDirectory 'documentation'>
|
||||
<DocDirectory 'example'>
|
||||
<DocDirectory 'pytest'>
|
||||
<Module 'test_setup_flow_example.py' (test_setup_flow_example)>
|
||||
<Class 'TestStateFullThing'>
|
||||
<Instance '()'>
|
||||
<Function 'test_42'>
|
||||
<Function 'test_23'>
|
||||
<ReSTChecker 'TODO.txt'>
|
||||
<ReSTSyntaxTest 'TODO.txt'>
|
||||
<LinkCheckerMaker 'checklinks'>
|
||||
<ReSTChecker 'api.txt'>
|
||||
<ReSTSyntaxTest 'api.txt'>
|
||||
<LinkCheckerMaker 'checklinks'>
|
||||
<CheckLink 'getting-started.html'>
|
||||
...</pre>
|
||||
</div>
|
||||
<p>In <tt class="docutils literal"><span class="pre">py/documentation/conftest.py</span></tt> you find the following
|
||||
customization:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">DocDirectory</span><span class="p">(</span><span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">collect</span><span class="o">.</span><span class="n">Directory</span><span class="p">):</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">results</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">DocDirectory</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
|
||||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">fspath</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="s">'*.txt'</span><span class="p">,</span> <span class="n">sort</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
|
||||
<span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">basename</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">results</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">join</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">'.txt'</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="nb">super</span><span class="p">(</span><span class="n">DocDirectory</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
||||
<span class="n">p</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fspath</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="mf">1</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="n">ReSTChecker</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
||||
|
||||
<span class="n">Directory</span> <span class="o">=</span> <span class="n">DocDirectory</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The existence of the ‘Directory’ name in the
|
||||
<tt class="docutils literal"><span class="pre">pypy/documentation/conftest.py</span></tt> module makes the collection
|
||||
process defer to our custom “DocDirectory” collector. We extend
|
||||
the set of collected test items by <tt class="docutils literal"><span class="pre">ReSTChecker</span></tt> instances
|
||||
which themselves create <tt class="docutils literal"><span class="pre">ReSTSyntaxTest</span></tt> and <tt class="docutils literal"><span class="pre">LinkCheckerMaker</span></tt>
|
||||
items. All of this instances (need to) follow the <a class="reference internal" href="#collector-api">collector API</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="customizing-the-reporting-of-test-failures">
|
||||
<h3>1.8.2.3. Customizing the reporting of Test Failures<a class="headerlink" href="#customizing-the-reporting-of-test-failures" title="Permalink to this headline">¶</a></h3>
|
||||
<p>XXX implement Item.repr_run and Item.repr_path for your test items</p>
|
||||
</div>
|
||||
<div class="section" id="writing-new-assertion-methods">
|
||||
<h3>1.8.2.4. Writing new assertion methods<a class="headerlink" href="#writing-new-assertion-methods" title="Permalink to this headline">¶</a></h3>
|
||||
<p>XXX __tracebackhide__, and use “print”</p>
|
||||
</div>
|
||||
<div class="section" id="customizing-the-collection-process-in-a-module">
|
||||
<h3>1.8.2.5. Customizing the collection process in a module<a class="headerlink" href="#customizing-the-collection-process-in-a-module" title="Permalink to this headline">¶</a></h3>
|
||||
<blockquote>
|
||||
REPEATED WARNING: details of the collection and running process are
|
||||
still subject to refactorings and thus details will change.
|
||||
If you are customizing py.test at “Item” level then you
|
||||
definitely want to be subscribed to the <a class="reference external" href="http://codespeak.net/mailman/listinfo/py-dev">py-dev mailing list</a>
|
||||
to follow ongoing development.</blockquote>
|
||||
<p>If you have a module where you want to take responsibility for
|
||||
collecting your own test Items and possibly even for executing
|
||||
a test then you can provide <a class="reference external" href="test-features.html#generative-tests">generative tests</a> that yield
|
||||
callables and possibly arguments as a tuple. This is especially
|
||||
useful for calling application test machinery with different
|
||||
parameter sets but counting each of the calls as a separate
|
||||
tests.</p>
|
||||
<p>The other extension possibility is about
|
||||
specifying a custom test <tt class="docutils literal"><span class="pre">Item</span></tt> class which
|
||||
is responsible for setting up and executing an underlying
|
||||
test. Or you can extend the collection process for a whole
|
||||
directory tree by putting Items in a <tt class="docutils literal"><span class="pre">conftest.py</span></tt> configuration file.
|
||||
The collection process dynamically consults the <em>chain of conftest.py</em>
|
||||
modules to determine collectors and items at <tt class="docutils literal"><span class="pre">Directory</span></tt>, <tt class="docutils literal"><span class="pre">Module</span></tt>,
|
||||
<tt class="docutils literal"><span class="pre">Class</span></tt>, <tt class="docutils literal"><span class="pre">Function</span></tt> or <tt class="docutils literal"><span class="pre">Generator</span></tt> level respectively.</p>
|
||||
</div>
|
||||
<div class="section" id="customizing-execution-of-functions">
|
||||
<h3>1.8.2.6. Customizing execution of Functions<a class="headerlink" href="#customizing-execution-of-functions" title="Permalink to this headline">¶</a></h3>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">py.test.collect.Function</span></tt> test items control execution
|
||||
of a test function. <tt class="docutils literal"><span class="pre">function.run()</span></tt> will get called by the
|
||||
session in order to actually run a test. The method is responsible
|
||||
for performing proper setup/teardown (“Test Fixtures”) for a
|
||||
Function test.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">Function.execute(target,</span> <span class="pre">*args)</span></tt> methods are invoked by
|
||||
the default <tt class="docutils literal"><span class="pre">Function.run()</span></tt> to actually execute a python
|
||||
function with the given (usually empty set of) arguments.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.8. Implementation and Customization of <tt class="docutils literal"><span class="pre">py.test</span></tt></a><ul>
|
||||
<li><a class="reference external" href="#collecting-and-running-tests-implementation-remarks">1.8.1. Collecting and running tests / implementation remarks</a><ul>
|
||||
<li><a class="reference external" href="#collectors-and-the-test-collection-process">1.8.1.1. Collectors and the test collection process</a></li>
|
||||
<li><a class="reference external" href="#test-items-are-collectors-as-well">1.8.1.2. test items are collectors as well</a></li>
|
||||
<li><a class="reference external" href="#constructing-the-package-name-for-test-modules">1.8.1.3. constructing the package name for test modules</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#customizing-the-testing-process">1.8.2. Customizing the testing process</a><ul>
|
||||
<li><a class="reference external" href="#writing-conftest-py-files">1.8.2.1. writing conftest.py files</a></li>
|
||||
<li><a class="reference external" href="#customizing-the-collecting-and-running-process">1.8.2.2. customizing the collecting and running process</a><ul>
|
||||
<li><a class="reference external" href="#example-perform-additional-rest-checks">1.8.2.2.1. example: perform additional ReST checks</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#customizing-the-reporting-of-test-failures">1.8.2.3. Customizing the reporting of Test Failures</a></li>
|
||||
<li><a class="reference external" href="#writing-new-assertion-methods">1.8.2.4. Writing new assertion methods</a></li>
|
||||
<li><a class="reference external" href="#customizing-the-collection-process-in-a-module">1.8.2.5. Customizing the collection process in a module</a></li>
|
||||
<li><a class="reference external" href="#customizing-execution-of-functions">1.8.2.6. Customizing execution of Functions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-examples.html"
|
||||
title="previous chapter">1.7. Working Examples</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="execnet.html"
|
||||
title="next chapter">2. py.execnet</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/impl-test.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="execnet.html" title="2. py.execnet"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-examples.html" title="1.7. Working Examples"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,229 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>py lib: Main tools and APIs — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="" />
|
||||
<link rel="next" title="1. py.test" href="test.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test.html" title="1. py.test"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li><a href="">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-lib-main-tools-and-apis">
|
||||
<h1>py lib: Main tools and APIs<a class="headerlink" href="#py-lib-main-tools-and-apis" title="Permalink to this headline">¶</a></h1>
|
||||
<p><a class="reference external" href="test.html">py.test</a> write and deploy unit- and functional tests to multiple machines.</p>
|
||||
<p><a class="reference external" href="execnet.html">py.execnet</a> rapidly deploy local or remote processes from your program.</p>
|
||||
<p><a class="reference external" href="path.html">py.path</a>: use path objects to transparently access local and svn filesystems.</p>
|
||||
<p><a class="reference external" href="code.html">py.code</a>: generate python code and use advanced introspection/traceback support.</p>
|
||||
</div>
|
||||
<div class="section" id="minor-support-functionality">
|
||||
<h1>Minor support functionality<a class="headerlink" href="#minor-support-functionality" title="Permalink to this headline">¶</a></h1>
|
||||
<p><a class="reference external" href="bin.html">py lib scripts</a> to make python development easier.</p>
|
||||
<p><a class="reference external" href="xml.html">py.xml</a> for generating in-memory xml/html object trees</p>
|
||||
<p><a class="reference external" href="io.html">py.io</a>: Helper Classes for Capturing of Input/Output</p>
|
||||
<p><a class="reference external" href="log.html">py.log</a>: an alpha document about the ad-hoc logging facilities</p>
|
||||
<p><a class="reference external" href="misc.html">miscellaneous features</a> describes some small but nice py lib features.</p>
|
||||
</div>
|
||||
<div class="section" id="full-contents">
|
||||
<h1>Full Contents<a class="headerlink" href="#full-contents" title="Permalink to this headline">¶</a></h1>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference external" href="test.html">1. py.test</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-quickstart.html">1.1. Quickstart</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-features.html">1.2. Features</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-plugins.html">1.3. Included plugins</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-ext.html">1.4. Writing plugins</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-dist.html">1.5. Distributed testing</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-config.html">1.6. Test configuration</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="test-examples.html">1.7. Working Examples</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="impl-test.html">1.8. Implementation and Customization of <tt class="docutils literal"><span class="pre">py.test</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="execnet.html">2. py.execnet</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#gateways-immediately-spawn-local-or-remote-process">2.1. Gateways: immediately spawn local or remote process</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#remote-exec-execute-source-code-remotely">2.2. remote_exec: execute source code remotely</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#channels-bidirectionally-exchange-data-between-hosts">2.3. Channels: bidirectionally exchange data between hosts</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#xspec-string-specification-for-gateway-type-and-configuration">2.4. XSpec: string specification for gateway type and configuration</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="execnet.html#examples-of-py-execnet-usage">2.5. Examples of py.execnet usage</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="path.html">3. py.path</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#path-implementations-provided-by-py-path">3.1. Path implementations provided by <tt class="docutils literal"><span class="pre">py.path</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#common-vs-specific-api">3.2. Common vs. specific API</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#known-problems-limitations">3.3. Known problems / limitations</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="path.html#future-plans">3.4. Future plans</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="code.html">4. py.code</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="code.html#contents-of-the-library">4.1. Contents of the library</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="code.html#the-wrappers">4.2. The wrappers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="bin.html">5. <tt class="docutils literal"><span class="pre">py/bin/</span></tt> scripts</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-test">5.1. <tt class="docutils literal"><span class="pre">py.test</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-cleanup">5.2. <tt class="docutils literal"><span class="pre">py.cleanup</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-countloc">5.3. <tt class="docutils literal"><span class="pre">py.countloc</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-lookup">5.4. <tt class="docutils literal"><span class="pre">py.lookup</span></tt></a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="bin.html#py-rest">5.5. <tt class="docutils literal"><span class="pre">py.rest</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="xml.html">6. py.xml: Lightweight and flexible xml/html generation</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="xml.html#motivation">6.1. Motivation</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="xml.html#a-pythonic-object-model-please">6.2. a pythonic object model , please</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="io.html">7. py.io</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="io.html#io-capturing-examples">7.1. IO Capturing examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="log.html">8. py.log documentation and musings</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="log.html#foreword">8.1. Foreword</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="log.html#logging-organisation">8.2. Logging organisation</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="log.html#using-the-py-log-library">8.3. Using the py.log library</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="misc.html">9. Miscellaneous features of the py lib</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="misc.html#mapping-the-standard-python-library-into-py">9.1. Mapping the standard python library into py</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="misc.html#support-for-interaction-with-system-utilities-binaries">9.2. Support for interaction with system utilities/binaries</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="misc.html#cross-python-version-compatibility-helpers">9.3. Cross-Python Version compatibility helpers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="why_py.html">10. Why, who, what and how do you do <em>the py lib</em>?</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#why-did-we-start-the-py-lib">10.1. Why did we start the py lib?</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#what-is-the-py-libs-current-focus">10.2. What is the py libs current focus?</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#how-does-py-development-work">10.3. How does py development work?</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="why_py.html#who-is-we">10.4. Who is “we”?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="future.html">11. Visions and ideas for further development of the py lib</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#distribute-tests-ad-hoc-across-multiple-platforms">11.1. Distribute tests ad-hoc across multiple platforms</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#make-apigen-useful-for-more-projects">11.2. Make APIGEN useful for more projects</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#consider-apigen-and-pdb-integration">11.3. Consider APIGEN and pdb integration</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#distribute-channels-programs-across-networks">11.4. Distribute channels/programs across networks</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#benchmarking-and-persistent-storage">11.5. Benchmarking and persistent storage</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#refactor-path-implementations-to-use-a-filesystem-abstraction">11.6. Refactor path implementations to use a Filesystem Abstraction</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#integrate-interactive-completion">11.7. Integrate interactive completion</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="future.html#consider-more-features">11.8. Consider more features</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="coding-style.html">12. Coding Style for the Py lib and friendly applications</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#honour-pep-8-style-guide-for-python-code">12.1. Honour PEP 8: Style Guide for Python Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#documentation-and-testing">12.2. Documentation and Testing</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#naming">12.3. naming</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#committing">12.4. committing</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="coding-style.html#miscellaneous">12.5. Miscellaneous</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="links.html">13. Links</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="contact.html">14. Contact and communication</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="download.html">15. Downloading</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="download.html#easy-install-py">15.1. “easy_install py”</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="download.html#installing-on-debian-or-fedora">15.2. Installing on Debian or Fedora</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="download.html#downloading-a-tar-zip-archive-and-installing-that">15.3. Downloading a tar/zip archive and installing that</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="download.html#installing-from-subversion-develop-mode">15.4. Installing from subversion / develop mode</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="download.html#working-with-multiple-py-lib-versions-svn-externals">15.5. Working with multiple py lib versions / svn externals</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference external" href="releases.html">16. Release notes</a><ul>
|
||||
<li class="toctree-l2"><a class="reference external" href="release-1.0.0.html">16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="release-0.9.2.html">16.2. py lib 0.9.2: bugfix release</a></li>
|
||||
<li class="toctree-l2"><a class="reference external" href="release-0.9.0.html">16.3. py lib 1.0.0: XXX</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="genindex.html"><em>Index</em></a></li>
|
||||
<li><a class="reference external" href="modindex.html"><em>Module Index</em></a></li>
|
||||
<li><a class="reference external" href="search.html"><em>Search Page</em></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">py lib: Main tools and APIs</a></li>
|
||||
<li><a class="reference external" href="#minor-support-functionality">Minor support functionality</a></li>
|
||||
<li><a class="reference external" href="#full-contents">Full Contents</a><ul>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test.html"
|
||||
title="next chapter">1. py.test</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/index.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test.html" title="1. py.test"
|
||||
>next</a> |</li>
|
||||
<li><a href="">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,156 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>7. py.io — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="8. 1 py.log documentation and musings" href="log.html" />
|
||||
<link rel="prev" title="6. py.xml: Lightweight and flexible xml/html generation" href="xml.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="log.html" title="8. 1 py.log documentation and musings"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="xml.html" title="6. py.xml: Lightweight and flexible xml/html generation"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-io">
|
||||
<h1>7. py.io<a class="headerlink" href="#py-io" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The ‘py’ lib provides helper classes for capturing IO during
|
||||
execution of a program.</p>
|
||||
<div class="section" id="io-capturing-examples">
|
||||
<h2>7.1. IO Capturing examples<a class="headerlink" href="#io-capturing-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="py-io-stdcapture">
|
||||
<h3>7.1.1. <tt class="docutils literal"><span class="pre">py.io.StdCapture</span></tt><a class="headerlink" href="#py-io-stdcapture" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Basic Example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="n">capture</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">StdCapture</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="k">print</span> <span class="s">"hello"</span>
|
||||
<span class="gp">>>> </span><span class="n">out</span><span class="p">,</span><span class="n">err</span> <span class="o">=</span> <span class="n">capture</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">out</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">==</span> <span class="s">"hello"</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>For calling functions you may use a shortcut:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">f</span><span class="p">():</span> <span class="k">print</span> <span class="s">"hello"</span>
|
||||
<span class="gp">>>> </span><span class="n">res</span><span class="p">,</span> <span class="n">out</span><span class="p">,</span> <span class="n">err</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">StdCapture</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">out</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">==</span> <span class="s">"hello"</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="py-io-stdcapturefd">
|
||||
<h3>7.1.2. <tt class="docutils literal"><span class="pre">py.io.StdCaptureFD</span></tt><a class="headerlink" href="#py-io-stdcapturefd" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you also want to capture writes to the stdout/stderr
|
||||
filedescriptors you may invoke:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span><span class="o">,</span> <span class="nn">sys</span>
|
||||
<span class="gp">>>> </span><span class="n">capture</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">io</span><span class="o">.</span><span class="n">StdCaptureFD</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"world"</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">out</span><span class="p">,</span><span class="n">err</span> <span class="o">=</span> <span class="n">capture</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">err</span>
|
||||
<span class="go">'world'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">7. py.io</a><ul>
|
||||
<li><a class="reference external" href="#io-capturing-examples">7.1. IO Capturing examples</a><ul>
|
||||
<li><a class="reference external" href="#py-io-stdcapture">7.1.1. <tt class="docutils literal"><span class="pre">py.io.StdCapture</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-io-stdcapturefd">7.1.2. <tt class="docutils literal"><span class="pre">py.io.StdCaptureFD</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="xml.html"
|
||||
title="previous chapter">6. py.xml: Lightweight and flexible xml/html generation</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="log.html"
|
||||
title="next chapter">8. 1 <strong class="code">py.log</strong> documentation and musings</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/io.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="log.html" title="8. 1 py.log documentation and musings"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="xml.html" title="6. py.xml: Lightweight and flexible xml/html generation"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>13. Links — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="14. Contact and communication" href="contact.html" />
|
||||
<link rel="prev" title="12. Coding Style for the Py lib and friendly applications" href="coding-style.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="contact.html" title="14. Contact and communication"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="coding-style.html" title="12. Coding Style for the Py lib and friendly applications"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="links">
|
||||
<h1>13. Links<a class="headerlink" href="#links" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Some links to ongoing discussions and comments about pylib and technics/concepts pylib uses.</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference external" href="http://blog.ianbicking.org/site-packages-considered-harmful.html">Discussion</a>
|
||||
about site-packages. That’s why pylib autopath and py.__.misc.dynpkg are a good idea ;-)</li>
|
||||
<li><a class="reference external" href="http://pyinotify.sourceforge.net/">Pyinotify</a> uses code from pypy autopath functions.</li>
|
||||
<li><a class="reference external" href="http://pythonpaste.org/testing-applications.html#the-test-environment">Testing (WSGI) Applications with Paste</a> and py.test. “This has been written with py.test in mind.” Paste uses py.test.</li>
|
||||
<li><a class="reference external" href="http://agiletesting.blogspot.com/">Agile Testing</a> by Grig Gheorghiu<ul>
|
||||
<li><a class="reference external" href="http://agiletesting.blogspot.com/2005/07/slides-from-py-library-overview.html">Slides from ‘py library overview’ presentation at SoCal Piggies meeting</a></li>
|
||||
<li><a class="reference external" href="http://agiletesting.blogspot.com/2005/01/python-unit-testing-part-3-pytest-tool.html">Python unit testing part 3: the py.test tool and library</a></li>
|
||||
<li><a class="reference external" href="http://agiletesting.blogspot.com/2005/07/py-lib-gems-greenlets-and-pyxml.html">greenlets and py.xml</a></li>
|
||||
<li><a class="reference external" href="http://agiletesting.blogspot.com/2005/06/keyword-based-logging-with-py-library.html">Keyword-based logging with the py library</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="coding-style.html"
|
||||
title="previous chapter">12. Coding Style for the Py lib and friendly applications</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="contact.html"
|
||||
title="next chapter">14. Contact and communication</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/links.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="contact.html" title="14. Contact and communication"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="coding-style.html" title="12. Coding Style for the Py lib and friendly applications"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,298 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>8. py.log documentation and musings — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="9. 1 Miscellaneous features of the py lib" href="misc.html" />
|
||||
<link rel="prev" title="7. py.io" href="io.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="misc.html" title="9. 1 Miscellaneous features of the py lib"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="io.html" title="7. py.io"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-log-documentation-and-musings">
|
||||
<h1>8. py.log documentation and musings<a class="headerlink" href="#py-log-documentation-and-musings" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="foreword">
|
||||
<h2>8.1. Foreword<a class="headerlink" href="#foreword" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This document is an attempt to briefly state the actual specification of the
|
||||
<tt class="code docutils literal"><span class="pre">py.log</span></tt> module. It was written by Francois Pinard and also contains
|
||||
some ideas for enhancing the py.log facilities.</p>
|
||||
<p>NOTE that <tt class="code docutils literal"><span class="pre">py.log</span></tt> is subject to refactorings, it may change with
|
||||
the next release.</p>
|
||||
<p>This document is meant to trigger or facilitate discussions. It shamelessly
|
||||
steals from the <a class="reference external" href="http://agiletesting.blogspot.com/2005/06/keyword-based-logging-with-py-library.html">Agile Testing</a> comments, and from other sources as well,
|
||||
without really trying to sort them out.</p>
|
||||
</div>
|
||||
<div class="section" id="logging-organisation">
|
||||
<h2>8.2. Logging organisation<a class="headerlink" href="#logging-organisation" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <tt class="code docutils literal"><span class="pre">py.log</span></tt> module aims a niche comparable to the one of the
|
||||
<a class="reference external" href="http://www.python.org/doc/2.4.2/lib/module-logging.html">logging module</a> found within the standard Python distributions, yet
|
||||
with much simpler paradigms for configuration and usage.</p>
|
||||
<p>Holger Krekel, the main <tt class="code docutils literal"><span class="pre">py</span></tt> library developer, introduced
|
||||
the idea of keyword-based logging and the idea of logging <em>producers</em> and
|
||||
<em>consumers</em>. A log producer is an object used by the application code
|
||||
to send messages to various log consumers. When you create a log
|
||||
producer, you define a set of keywords that are then used to both route
|
||||
the logging messages to consumers, and to prefix those messages.</p>
|
||||
<p>In fact, each log producer has a few keywords associated with it for
|
||||
identification purposes. These keywords form a tuple of strings, and
|
||||
may be used to later retrieve a particular log producer.</p>
|
||||
<p>A log producer may (or may not) be associated with a log consumer, meant
|
||||
to handle log messages in particular ways. The log consumers can be
|
||||
<tt class="docutils literal"><span class="pre">STDOUT</span></tt>, <tt class="docutils literal"><span class="pre">STDERR</span></tt>, log files, syslog, the Windows Event Log, user
|
||||
defined functions, etc. (Yet, logging to syslog or to the Windows Event
|
||||
Log is only future plans for now). A log producer has never more than
|
||||
one consumer at a given time, but it is possible to dynamically switch
|
||||
a producer to use another consumer. On the other hand, a single log
|
||||
consumer may be associated with many producers.</p>
|
||||
<p>Note that creating and associating a producer and a consumer is done
|
||||
automatically when not otherwise overriden, so using <tt class="code docutils literal"><span class="pre">py</span></tt> logging
|
||||
is quite comfortable even in the smallest programs. More typically,
|
||||
the application programmer will likely design a hierarchy of producers,
|
||||
and will select keywords appropriately for marking the hierarchy tree.
|
||||
If a node of the hierarchical tree of producers has to be divided in
|
||||
sub-trees, all producers in the sub-trees share, as a common prefix, the
|
||||
keywords of the node being divided. In other words, we go further down
|
||||
in the hierarchy of producers merely by adding keywords.</p>
|
||||
</div>
|
||||
<div class="section" id="using-the-py-log-library">
|
||||
<h2>8.3. Using the py.log library<a class="headerlink" href="#using-the-py-log-library" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To use the <tt class="code docutils literal"><span class="pre">py.log</span></tt> library, the user must import it into a Python
|
||||
application, create at least one log producer and one log consumer, have
|
||||
producers and consumers associated, and finally call the log producers
|
||||
as needed, giving them log messages.</p>
|
||||
<div class="section" id="importing">
|
||||
<h3>8.3.1. Importing<a class="headerlink" href="#importing" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Once the <tt class="code docutils literal"><span class="pre">py</span></tt> library is installed on your system, a mere:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">py</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>holds enough magic for lazily importing the various facilities of the
|
||||
<tt class="code docutils literal"><span class="pre">py</span></tt> library when they are first needed. This is really how
|
||||
<tt class="code docutils literal"><span class="pre">py.log</span></tt> is made available to the application. For example, after
|
||||
the above <tt class="docutils literal"><span class="pre">import</span> <span class="pre">py</span></tt>, one may directly write <tt class="docutils literal"><span class="pre">py.log.Producer(...)</span></tt>
|
||||
and everything should work fine, the user does not have to worry about
|
||||
specifically importing more modules.</p>
|
||||
</div>
|
||||
<div class="section" id="creating-a-producer">
|
||||
<h3>8.3.2. Creating a producer<a class="headerlink" href="#creating-a-producer" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There are three ways for creating a log producer instance:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>As soon as <tt class="docutils literal"><span class="pre">py.log</span></tt> is first evaluated within an application
|
||||
program, a default log producer is created, and made available under
|
||||
the name <tt class="docutils literal"><span class="pre">py.log.default</span></tt>. The keyword <tt class="docutils literal"><span class="pre">default</span></tt> is associated
|
||||
with that producer.</li>
|
||||
<li>The <tt class="docutils literal"><span class="pre">py.log.Producer()</span></tt> constructor may be explicitly called
|
||||
for creating a new instance of a log producer. That constructor
|
||||
accepts, as an argument, the keywords that should be associated with
|
||||
that producer. Keywords may be given either as a tuple of keyword
|
||||
strings, or as a single space-separated string of keywords.</li>
|
||||
<li>Whenever an attribute is <em>taken</em> out of a log producer instance,
|
||||
for the first time that attribute is taken, a new log producer is
|
||||
created. The keywords associated with that new producer are those
|
||||
of the initial producer instance, to which is appended the name of
|
||||
the attribute being taken.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>The last point is especially useful, as it allows using log producers
|
||||
without further declarations, merely creating them <em>on-the-fly</em>.</p>
|
||||
</div>
|
||||
<div class="section" id="creating-a-consumer">
|
||||
<h3>8.3.3. Creating a consumer<a class="headerlink" href="#creating-a-consumer" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There are many ways for creating or denoting a log consumer:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><p class="first">A default consumer exists within the <tt class="docutils literal"><span class="pre">py.log</span></tt> facilities, which
|
||||
has the effect of writing log messages on the Python standard output
|
||||
stream. That consumer is associated at the very top of the producer
|
||||
hierarchy, and as such, is called whenever no other consumer is
|
||||
found.</p>
|
||||
</li>
|
||||
<li><p class="first">The notation <tt class="docutils literal"><span class="pre">py.log.STDOUT</span></tt> accesses a log consumer which writes
|
||||
log messages on the Python standard output stream.</p>
|
||||
</li>
|
||||
<li><p class="first">The notation <tt class="docutils literal"><span class="pre">py.log.STDERR</span></tt> accesses a log consumer which writes
|
||||
log messages on the Python standard error stream.</p>
|
||||
</li>
|
||||
<li><p class="first">The <tt class="docutils literal"><span class="pre">py.log.File()</span></tt> constructor accepts, as argument, either a file
|
||||
already opened in write mode or any similar file-like object, and
|
||||
creates a log consumer able to write log messages onto that file.</p>
|
||||
</li>
|
||||
<li><p class="first">The <tt class="docutils literal"><span class="pre">py.log.Path()</span></tt> constructor accepts a file name for its first
|
||||
argument, and creates a log consumer able to write log messages into
|
||||
that file. The constructor call accepts a few keyword parameters:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">append</span></tt>, which is <tt class="xref docutils literal"><span class="pre">False</span></tt> by default, may be used for
|
||||
opening the file in append mode instead of write mode.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">delayed_create</span></tt>, which is <tt class="xref docutils literal"><span class="pre">False</span></tt> by default, maybe be used
|
||||
for opening the file at the latest possible time. Consequently,
|
||||
the file will not be created if it did not exist, and no actual
|
||||
log message gets written to it.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">buffering</span></tt>, which is 1 by default, is used when opening the
|
||||
file. Buffering can be turned off by specifying a 0 value. The
|
||||
buffer size may also be selected through this argument.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">Any user defined function may be used for a log consumer. Such a
|
||||
function should accept a single argument, which is the message to
|
||||
write, and do whatever is deemed appropriate by the programmer.
|
||||
When the need arises, this may be an especially useful and flexible
|
||||
feature.</p>
|
||||
</li>
|
||||
<li><p class="first">The special value <tt class="xref docutils literal"><span class="pre">None</span></tt> means no consumer at all. This acts just
|
||||
like if there was a consumer which would silently discard all log
|
||||
messages sent to it.</p>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</div>
|
||||
<div class="section" id="associating-producers-and-consumers">
|
||||
<h3>8.3.4. Associating producers and consumers<a class="headerlink" href="#associating-producers-and-consumers" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Each log producer may have at most one log consumer associated with
|
||||
it. A log producer gets associated with a log consumer through a
|
||||
<tt class="docutils literal"><span class="pre">py.log.set_consumer()</span></tt> call. That function accepts two arguments,
|
||||
the first identifying a producer (a tuple of keyword strings or a single
|
||||
space-separated string of keywords), the second specifying the precise
|
||||
consumer to use for that producer. Until this function is called for a
|
||||
producer, that producer does not have any explicit consumer associated
|
||||
with it.</p>
|
||||
<p>Now, the hierarchy of log producers establishes which consumer gets used
|
||||
whenever a producer has no explicit consumer. When a log producer
|
||||
has no consumer explicitly associated with it, it dynamically and
|
||||
recursively inherits the consumer of its parent node, that is, that node
|
||||
being a bit closer to the root of the hierarchy. In other words, the
|
||||
rightmost keywords of that producer are dropped until another producer
|
||||
is found which has an explicit consumer. A nice side-effect is that,
|
||||
by explicitly associating a consumer with a producer, all consumer-less
|
||||
producers which appear under that producer, in the hierarchy tree,
|
||||
automatically <em>inherits</em> that consumer.</p>
|
||||
</div>
|
||||
<div class="section" id="writing-log-messages">
|
||||
<h3>8.3.5. Writing log messages<a class="headerlink" href="#writing-log-messages" title="Permalink to this headline">¶</a></h3>
|
||||
<p>All log producer instances are also functions, and this is by calling
|
||||
them that log messages are generated. Each call to a producer object
|
||||
produces the text for one log entry, which in turn, is sent to the log
|
||||
consumer for that producer.</p>
|
||||
<p>The log entry displays, after a prefix identifying the log producer
|
||||
being used, all arguments given in the call, converted to strings and
|
||||
space-separated. (This is meant by design to be fairly similar to what
|
||||
the <tt class="docutils literal"><span class="pre">print</span></tt> statement does in Python). The prefix itself is made up
|
||||
of a colon-separated list of keywords associated with the producer, the
|
||||
whole being set within square brackets.</p>
|
||||
<p>Note that the consumer is responsible for adding the newline at the end
|
||||
of the log entry. That final newline is not part of the text for the
|
||||
log entry.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">8. py.log documentation and musings</a><ul>
|
||||
<li><a class="reference external" href="#foreword">8.1. Foreword</a></li>
|
||||
<li><a class="reference external" href="#logging-organisation">8.2. Logging organisation</a></li>
|
||||
<li><a class="reference external" href="#using-the-py-log-library">8.3. Using the py.log library</a><ul>
|
||||
<li><a class="reference external" href="#importing">8.3.1. Importing</a></li>
|
||||
<li><a class="reference external" href="#creating-a-producer">8.3.2. Creating a producer</a></li>
|
||||
<li><a class="reference external" href="#creating-a-consumer">8.3.3. Creating a consumer</a></li>
|
||||
<li><a class="reference external" href="#associating-producers-and-consumers">8.3.4. Associating producers and consumers</a></li>
|
||||
<li><a class="reference external" href="#writing-log-messages">8.3.5. Writing log messages</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="io.html"
|
||||
title="previous chapter">7. py.io</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="misc.html"
|
||||
title="next chapter">9. 1 Miscellaneous features of the py lib</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/log.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="misc.html" title="9. 1 Miscellaneous features of the py lib"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="io.html" title="7. py.io"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,321 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>9. Miscellaneous features of the py lib — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="10. 1 Why, who, what and how do you do the py lib?" href="why_py.html" />
|
||||
<link rel="prev" title="8. py.log documentation and musings" href="log.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="why_py.html" title="10. 1 Why, who, what and how do you do the py lib?"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="log.html" title="8. py.log documentation and musings"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="miscellaneous-features-of-the-py-lib">
|
||||
<h1>9. Miscellaneous features of the py lib<a class="headerlink" href="#miscellaneous-features-of-the-py-lib" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="mapping-the-standard-python-library-into-py">
|
||||
<h2>9.1. Mapping the standard python library into py<a class="headerlink" href="#mapping-the-standard-python-library-into-py" title="Permalink to this headline">¶</a></h2>
|
||||
<blockquote>
|
||||
Warning: This feature is very young and thus experimental.
|
||||
Be prepared to adapt your code later if you use it.</blockquote>
|
||||
<p>After you have worked with the py lib a bit, you might enjoy
|
||||
the lazy importing, i.e. you only have to do <tt class="docutils literal"><span class="pre">import</span> <span class="pre">py</span></tt> and
|
||||
work your way to your desired object. Using the full path
|
||||
also ensures that there remains a focus on getting short paths
|
||||
to objects.</p>
|
||||
<div class="section" id="the-py-std-hook">
|
||||
<h3>9.1.1. The <tt class="docutils literal"><span class="pre">py.std</span></tt> hook<a class="headerlink" href="#the-py-std-hook" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Of course, no matter what, everybody will continue to use the
|
||||
python standard library because it is a very usable code base.
|
||||
However, to properly support lazyness the py lib offers a way
|
||||
to get to many standard modules without requiring “import”
|
||||
statements. For example, to get to the print-exception
|
||||
functionality of the standard library you can write:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">std</span><span class="o">.</span><span class="n">traceback</span><span class="o">.</span><span class="n">print_exc</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>without having to do anything else than the usual <tt class="docutils literal"><span class="pre">import</span> <span class="pre">py</span></tt>
|
||||
at the beginning. Note that not having imports for the
|
||||
<cite>python standard library</cite> obviously gets rid of the <em>unused
|
||||
import</em> problem. Modules only get imported when you actually
|
||||
need them.</p>
|
||||
<p>Moreover, this approach resolves some of the issues stated in
|
||||
<a class="reference external" href="http://www.python.org/peps/pep-0328.html">the relative/absolute import PEP-328</a>, as with the above
|
||||
approach you never have ambiguity problems. The above
|
||||
traceback-usage is an absolute path that will not be
|
||||
accidentally get confused with local names. (Well, never put
|
||||
a file <tt class="docutils literal"><span class="pre">py.py</span></tt> in an importable path, btw, mind you :-)</p>
|
||||
</div>
|
||||
<div class="section" id="automagically-accessing-sub-packages-doesn-t-work-yet">
|
||||
<h3>9.1.2. Automagically accessing sub packages doesn’t work (yet?)<a class="headerlink" href="#automagically-accessing-sub-packages-doesn-t-work-yet" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you use the <tt class="docutils literal"><span class="pre">py.std</span></tt> hook you currently cannot magically
|
||||
import nested packages which otherwise need explicit imports of
|
||||
their sub-packages. For example, the suversion bindings
|
||||
require you to do something like:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">svn.client</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you just do the naive thing with the py lib, i.e. write
|
||||
<tt class="docutils literal"><span class="pre">py.std.svn.client</span></tt> it will not work unless you previously
|
||||
imported it already. The py lib currently doesn’t try to
|
||||
magically make this work. The <tt class="docutils literal"><span class="pre">py.std</span></tt> hook really is
|
||||
intended for Python standard modules which very seldomly (if
|
||||
at all) provide such nested packages.</p>
|
||||
<p><strong>Note that you may never rely</strong> on module identity, i.e.
|
||||
that <tt class="docutils literal"><span class="pre">X</span> <span class="pre">is</span> <span class="pre">py.std.X</span></tt> for any <tt class="docutils literal"><span class="pre">X</span></tt>. This is to allow
|
||||
us later to lazyly import nested packages. Yes, lazyness
|
||||
is hard to resist :-)</p>
|
||||
</div>
|
||||
<div class="section" id="note-you-get-an-attributeerror-not-an-importerror">
|
||||
<h3>9.1.3. Note: you get an AttributeError, not an ImportError<a class="headerlink" href="#note-you-get-an-attributeerror-not-an-importerror" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you say <tt class="docutils literal"><span class="pre">py.std.XYZ</span></tt> and importing <tt class="docutils literal"><span class="pre">XYZ</span></tt> produces an
|
||||
<tt class="docutils literal"><span class="pre">ImportError</span></tt> , it will actually show up as an
|
||||
<tt class="docutils literal"><span class="pre">AttributeError</span></tt>. It is deemed more important to adhere to
|
||||
the standard <tt class="docutils literal"><span class="pre">__getattr__</span></tt> protocol than to let the
|
||||
<tt class="docutils literal"><span class="pre">ImportError</span></tt> pass through. For example, you might want to
|
||||
do:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="nb">getattr</span><span class="p">(</span><span class="n">py</span><span class="o">.</span><span class="n">std</span><span class="o">.</span><span class="n">cStringIO</span><span class="p">,</span> <span class="s">'StringIO'</span><span class="p">,</span> <span class="n">py</span><span class="o">.</span><span class="n">std</span><span class="o">.</span><span class="n">StringIO</span><span class="o">.</span><span class="n">StringIO</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>and you would expect that it works. It does work although it will
|
||||
take away some lazyness because <tt class="docutils literal"><span class="pre">py.std.StringIO.StringIO</span></tt> will
|
||||
be imported in any case.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="support-for-interaction-with-system-utilities-binaries">
|
||||
<h2>9.2. Support for interaction with system utilities/binaries<a class="headerlink" href="#support-for-interaction-with-system-utilities-binaries" title="Permalink to this headline">¶</a></h2>
|
||||
<p>sources:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">py/process/</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">py/path/local/</span></tt></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Currently, the py lib offers two ways to interact with
|
||||
system executables. <tt class="docutils literal"><span class="pre">py.process.cmdexec()</span></tt> invokes
|
||||
the shell in order to execute a string. The other
|
||||
one, <tt class="docutils literal"><span class="pre">py.path.local</span></tt>‘s ‘sysexec()’ method lets you
|
||||
directly execute a binary.</p>
|
||||
<p>Both approaches will raise an exception in case of a return-
|
||||
code other than 0 and otherwise return the stdout-output
|
||||
of the child process.</p>
|
||||
<div class="section" id="the-shell-based-approach">
|
||||
<h3>9.2.1. The shell based approach<a class="headerlink" href="#the-shell-based-approach" title="Permalink to this headline">¶</a></h3>
|
||||
<p>You can execute a command via your system shell
|
||||
by doing something like:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">out</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">process</span><span class="o">.</span><span class="n">cmdexec</span><span class="p">(</span><span class="s">'ls -v'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>However, the <tt class="docutils literal"><span class="pre">cmdexec</span></tt> approach has a few shortcomings:</p>
|
||||
<ul class="simple">
|
||||
<li>it relies on the underlying system shell</li>
|
||||
<li>it neccessitates shell-escaping for expressing arguments</li>
|
||||
<li>it does not easily allow to “fix” the binary you want to run.</li>
|
||||
<li>it only allows to execute executables from the local
|
||||
filesystem</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="local-paths-have-sysexec">
|
||||
<span id="sysexec"></span><h3>9.2.2. local paths have <tt class="docutils literal"><span class="pre">sysexec</span></tt><a class="headerlink" href="#local-paths-have-sysexec" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The py lib currently offers a stripped down functionality of what
|
||||
the new <a class="reference external" href="http://www.python.org/peps/pep-0324.html">PEP-324 subprocess module</a> offers. The main functionality
|
||||
of synchronously executing a system executable has a straightforward API:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">binsvn</span><span class="o">.</span><span class="n">sysexec</span><span class="p">(</span><span class="s">'ls'</span><span class="p">,</span> <span class="s">'http://codespeak.net/svn'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>where <tt class="docutils literal"><span class="pre">binsvn</span></tt> is a path that points to the <tt class="docutils literal"><span class="pre">svn</span></tt> commandline
|
||||
binary. Note that this function would not offer any shell-escaping
|
||||
so you really have to pass in separated arguments. This idea
|
||||
fits nicely into <a class="reference external" href="future.html#general-path">a more general view on path objects</a>.</p>
|
||||
<p>For a first go, we are just reusing the existing <a class="reference external" href="http://www.lysator.liu.se/~astrand/popen5/">subprocess
|
||||
implementation</a> but don’t expose any of its API apart
|
||||
from the above <tt class="docutils literal"><span class="pre">sysexec()</span></tt> method.</p>
|
||||
<p>Note, however, that currently the support for the <tt class="docutils literal"><span class="pre">sysexec</span></tt> interface on
|
||||
win32 is not thoroughly tested. If you run into problems with it, we are
|
||||
interested to hear about them. If you are running a Python older than 2.4 you
|
||||
will have to install the <a class="reference external" href="http://pywin32.sourceforge.net/">pywin32 package</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="finding-an-executable-local-path">
|
||||
<h3>9.2.3. finding an executable local path<a class="headerlink" href="#finding-an-executable-local-path" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Finding an executable is quite different on multiple platforms.
|
||||
Currently, the <tt class="docutils literal"><span class="pre">PATH</span></tt> environment variable based search on
|
||||
unix platforms is supported:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">sysfind</span><span class="p">(</span><span class="s">'svn'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>which returns the first path whose <tt class="docutils literal"><span class="pre">basename</span></tt> matches <tt class="docutils literal"><span class="pre">svn</span></tt>.
|
||||
In principle, <cite>sysfind</cite> deploys platform specific algorithms
|
||||
to perform the search. On Windows, for example, it may look
|
||||
at the registry (XXX).</p>
|
||||
<p>To make the story complete, we allow to pass in a second <tt class="docutils literal"><span class="pre">checker</span></tt>
|
||||
argument that is called for each found executable. For example, if
|
||||
you have multiple binaries available you may want to select the
|
||||
right version:</p>
|
||||
<div class="highlight-python"><pre>def mysvn(p):
|
||||
""" check that the given svn binary has version 1.1. """
|
||||
line = p.execute('--version'').readlines()[0]
|
||||
if line.find('version 1.1'):
|
||||
return p
|
||||
binsvn = py.path.local.sysfind('svn', checker=mysvn)</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="cross-python-version-compatibility-helpers">
|
||||
<h2>9.3. Cross-Python Version compatibility helpers<a class="headerlink" href="#cross-python-version-compatibility-helpers" title="Permalink to this headline">¶</a></h2>
|
||||
<p>sources:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">py/compat/</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">py/builtin/</span></tt></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>The compat and builtin namespaces help to write code using newer python features on older python interpreters.</p>
|
||||
<div class="section" id="py-compat">
|
||||
<h3>9.3.1. <tt class="docutils literal"><span class="pre">py.compat</span></tt><a class="headerlink" href="#py-compat" title="Permalink to this headline">¶</a></h3>
|
||||
<p><tt class="docutils literal"><span class="pre">py.compat</span></tt> provides fixed versions (currently taken from Python 2.4.4) of
|
||||
a few selected modules to be able to use them across python versions. Currently these are:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>doctest</li>
|
||||
<li>optparse</li>
|
||||
<li>subprocess</li>
|
||||
<li>textwrap</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Note that for example <tt class="docutils literal"><span class="pre">import</span> <span class="pre">doctest</span></tt> and <tt class="docutils literal"><span class="pre">from</span> <span class="pre">py.compat</span> <span class="pre">import</span> <span class="pre">doctest</span></tt> result
|
||||
into two different module objects no matter what Python version you are using.
|
||||
So you should only use exactly one of these to avoid confusion in your program.</p>
|
||||
</div>
|
||||
<div class="section" id="py-builtin">
|
||||
<h3>9.3.2. <tt class="docutils literal"><span class="pre">py.builtin</span></tt><a class="headerlink" href="#py-builtin" title="Permalink to this headline">¶</a></h3>
|
||||
<p><tt class="docutils literal"><span class="pre">py.builtin</span></tt> provides builtin functions/types that were added in later Python
|
||||
versions. If the used Python version used does not provide these builtins the
|
||||
py lib provides some reimplementations. These currently are:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>enumerate</li>
|
||||
<li>reversed</li>
|
||||
<li>sorted</li>
|
||||
<li>BaseException</li>
|
||||
<li>set and frozenset (using either the builtin, if available, or the sets
|
||||
module)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p><tt class="docutils literal"><span class="pre">py.builtin.BaseException</span></tt> is just <tt class="docutils literal"><span class="pre">Exception</span></tt> before Python 2.5.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">9. Miscellaneous features of the py lib</a><ul>
|
||||
<li><a class="reference external" href="#mapping-the-standard-python-library-into-py">9.1. Mapping the standard python library into py</a><ul>
|
||||
<li><a class="reference external" href="#the-py-std-hook">9.1.1. The <tt class="docutils literal"><span class="pre">py.std</span></tt> hook</a></li>
|
||||
<li><a class="reference external" href="#automagically-accessing-sub-packages-doesn-t-work-yet">9.1.2. Automagically accessing sub packages doesn’t work (yet?)</a></li>
|
||||
<li><a class="reference external" href="#note-you-get-an-attributeerror-not-an-importerror">9.1.3. Note: you get an AttributeError, not an ImportError</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#support-for-interaction-with-system-utilities-binaries">9.2. Support for interaction with system utilities/binaries</a><ul>
|
||||
<li><a class="reference external" href="#the-shell-based-approach">9.2.1. The shell based approach</a></li>
|
||||
<li><a class="reference external" href="#local-paths-have-sysexec">9.2.2. local paths have <tt class="docutils literal"><span class="pre">sysexec</span></tt></a></li>
|
||||
<li><a class="reference external" href="#finding-an-executable-local-path">9.2.3. finding an executable local path</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#cross-python-version-compatibility-helpers">9.3. Cross-Python Version compatibility helpers</a><ul>
|
||||
<li><a class="reference external" href="#py-compat">9.3.1. <tt class="docutils literal"><span class="pre">py.compat</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-builtin">9.3.2. <tt class="docutils literal"><span class="pre">py.builtin</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="log.html"
|
||||
title="previous chapter">8. py.log documentation and musings</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="why_py.html"
|
||||
title="next chapter">10. 1 Why, who, what and how do you do <em>the py lib</em>?</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/misc.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="why_py.html" title="10. 1 Why, who, what and how do you do the py lib?"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="log.html" title="8. py.log documentation and musings"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
# Sphinx inventory version 1
|
||||
# Project: py lib
|
||||
# Version: 1.0
|
|
@ -0,0 +1,366 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>3. py.path — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="4. py.code" href="code.html" />
|
||||
<link rel="prev" title="2. py.execnet" href="execnet.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="code.html" title="4. py.code"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="execnet.html" title="2. py.execnet"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-path">
|
||||
<h1>3. py.path<a class="headerlink" href="#py-path" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The ‘py’ lib provides a uniform high-level api to deal with filesystems
|
||||
and filesystem-like interfaces: <tt class="docutils literal"><span class="pre">py.path</span></tt>. It aims to offer a central
|
||||
object to fs-like object trees (reading from and writing to files, adding
|
||||
files/directories, examining the types and structure, etc.), and out-of-the-box
|
||||
provides a number of implementations of this API.</p>
|
||||
<div class="section" id="path-implementations-provided-by-py-path">
|
||||
<h2>3.1. Path implementations provided by <tt class="docutils literal"><span class="pre">py.path</span></tt><a class="headerlink" href="#path-implementations-provided-by-py-path" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="py-path-local">
|
||||
<h3>3.1.1. <tt class="docutils literal"><span class="pre">py.path.local</span></tt><a class="headerlink" href="#py-path-local" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The first and most obvious of the implementations is a wrapper around a local
|
||||
filesystem. It’s just a bit nicer in usage than the regular Python APIs, and
|
||||
of course all the functionality is bundled together rather than spread over a
|
||||
number of modules.</p>
|
||||
<p>Example usage, here we use the <tt class="docutils literal"><span class="pre">py.test.ensuretemp()</span></tt> function to create
|
||||
a <tt class="docutils literal"><span class="pre">py.path.local</span></tt> object for us (which wraps a directory):</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">py</span>
|
||||
<span class="gp">>>> </span><span class="n">temppath</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">ensuretemp</span><span class="p">(</span><span class="s">'py.path_documentation'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">foopath</span> <span class="o">=</span> <span class="n">temppath</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'foo'</span><span class="p">)</span> <span class="c"># get child 'foo' (lazily)</span>
|
||||
<span class="gp">>>> </span><span class="n">foopath</span><span class="o">.</span><span class="n">check</span><span class="p">()</span> <span class="c"># check if child 'foo' exists</span>
|
||||
<span class="go">False</span>
|
||||
<span class="gp">>>> </span><span class="n">foopath</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'bar'</span><span class="p">)</span> <span class="c"># write some data to it</span>
|
||||
<span class="gp">>>> </span><span class="n">foopath</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">foopath</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||||
<span class="go">'bar'</span>
|
||||
<span class="gp">>>> </span><span class="n">foofile</span> <span class="o">=</span> <span class="n">foopath</span><span class="o">.</span><span class="n">open</span><span class="p">()</span> <span class="c"># return a 'real' file object</span>
|
||||
<span class="gp">>>> </span><span class="n">foofile</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span>
|
||||
<span class="go">'b'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="py-path-svnurl-and-py-path-svnwc">
|
||||
<h3>3.1.2. <tt class="docutils literal"><span class="pre">py.path.svnurl</span></tt> and <tt class="docutils literal"><span class="pre">py.path.svnwc</span></tt><a class="headerlink" href="#py-path-svnurl-and-py-path-svnwc" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Two other <tt class="docutils literal"><span class="pre">py.path</span></tt> implementations that the py lib provides wrap the
|
||||
popular <a class="reference external" href="http://subversion.tigris.org/">Subversion</a> revision control system: the first (called ‘svnurl’)
|
||||
by interfacing with a remote server, the second by wrapping a local checkout.
|
||||
Both allow you to access relatively advanced features such as metadata and
|
||||
versioning, and both in a way more user-friendly manner than existing other
|
||||
solutions.</p>
|
||||
<p>Some example usage of <tt class="docutils literal"><span class="pre">py.path.svnurl</span></tt>:</p>
|
||||
<div class="highlight-python"><pre>.. >>> import py
|
||||
.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> url = py.path.svnurl('http://codespeak.net/svn/py')
|
||||
>>> info = url.info()
|
||||
>>> info.kind
|
||||
'dir'
|
||||
>>> firstentry = url.log()[-1]
|
||||
>>> import time
|
||||
>>> time.strftime('%Y-%m-%d', time.gmtime(firstentry.date))
|
||||
'2004-10-02'</pre>
|
||||
</div>
|
||||
<p>Example usage of <tt class="docutils literal"><span class="pre">py.path.svnwc</span></tt>:</p>
|
||||
<div class="highlight-python"><pre>.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> temp = py.test.ensuretemp('py.path_documentation')
|
||||
>>> wc = py.path.svnwc(temp.join('svnwc'))
|
||||
>>> wc.checkout('http://codespeak.net/svn/py/dist/py/path/local')
|
||||
>>> wc.join('local.py').check()
|
||||
True</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="common-vs-specific-api">
|
||||
<h2>3.2. Common vs. specific API<a class="headerlink" href="#common-vs-specific-api" title="Permalink to this headline">¶</a></h2>
|
||||
<p>All Path objects support a common set of operations, suitable
|
||||
for many use cases and allowing to transparently switch the
|
||||
path object within an application (e.g. from “local” to “svnwc”).
|
||||
The common set includes functions such as <cite>path.read()</cite> to read all data
|
||||
from a file, <cite>path.write()</cite> to write data, <cite>path.listdir()</cite> to get a list
|
||||
of directory entries, <cite>path.check()</cite> to check if a node exists
|
||||
and is of a particular type, <cite>path.join()</cite> to get
|
||||
to a (grand)child, <cite>path.visit()</cite> to recursively walk through a node’s
|
||||
children, etc. Only things that are not common on ‘normal’ filesystems (yet),
|
||||
such as handling metadata (e.g. the Subversion “properties”) require
|
||||
using specific APIs.</p>
|
||||
<div class="section" id="examples">
|
||||
<h3>3.2.1. Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A quick ‘cookbook’ of small examples that will be useful ‘in real life’,
|
||||
which also presents parts of the ‘common’ API, and shows some non-common
|
||||
methods:</p>
|
||||
<div class="section" id="searching-txt-files">
|
||||
<h4>3.2.1.1. Searching <cite>.txt</cite> files<a class="headerlink" href="#searching-txt-files" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Search for a particular string inside all files with a .txt extension in a
|
||||
specific directory.</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">dirpath</span> <span class="o">=</span> <span class="n">temppath</span><span class="o">.</span><span class="n">ensure</span><span class="p">(</span><span class="s">'testdir'</span><span class="p">,</span> <span class="nb">dir</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">dirpath</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'textfile1.txt'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'foo bar baz'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">dirpath</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'textfile2.txt'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'frob bar spam eggs'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">subdir</span> <span class="o">=</span> <span class="n">dirpath</span><span class="o">.</span><span class="n">ensure</span><span class="p">(</span><span class="s">'subdir'</span><span class="p">,</span> <span class="nb">dir</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">subdir</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'textfile1.txt'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'foo baz'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">subdir</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'textfile2.txt'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'spam eggs spam foo bar spam'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="gp">>>> </span><span class="k">for</span> <span class="n">fpath</span> <span class="ow">in</span> <span class="n">dirpath</span><span class="o">.</span><span class="n">visit</span><span class="p">(</span><span class="s">'*.txt'</span><span class="p">):</span>
|
||||
<span class="gp">... </span> <span class="k">if</span> <span class="s">'bar'</span> <span class="ow">in</span> <span class="n">fpath</span><span class="o">.</span><span class="n">read</span><span class="p">():</span>
|
||||
<span class="gp">... </span> <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fpath</span><span class="o">.</span><span class="n">basename</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">results</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">results</span>
|
||||
<span class="go">['textfile1.txt', 'textfile2.txt', 'textfile2.txt']</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="working-with-paths">
|
||||
<h4>3.2.1.2. Working with Paths<a class="headerlink" href="#working-with-paths" title="Permalink to this headline">¶</a></h4>
|
||||
<p>This example shows the <tt class="docutils literal"><span class="pre">py.path</span></tt> features to deal with
|
||||
filesystem paths Note that the filesystem is never touched,
|
||||
all operations are performed on a string level (so the paths
|
||||
don’t have to exist, either):</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">p1</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="p">(</span><span class="s">'/foo/bar'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">p2</span> <span class="o">=</span> <span class="n">p1</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'baz/qux'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">p2</span> <span class="o">==</span> <span class="n">py</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="p">(</span><span class="s">'/foo/bar/baz/qux'</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">sep</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">sep</span>
|
||||
<span class="gp">>>> </span><span class="n">p2</span><span class="o">.</span><span class="n">relto</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">sep</span><span class="p">,</span> <span class="s">'/'</span><span class="p">)</span> <span class="c"># os-specific path sep in the string</span>
|
||||
<span class="go">'baz/qux'</span>
|
||||
<span class="gp">>>> </span><span class="n">p2</span><span class="o">.</span><span class="n">bestrelpath</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">sep</span><span class="p">,</span> <span class="s">'/'</span><span class="p">)</span>
|
||||
<span class="go">'../..'</span>
|
||||
<span class="gp">>>> </span><span class="n">p2</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">p2</span><span class="o">.</span><span class="n">bestrelpath</span><span class="p">(</span><span class="n">p1</span><span class="p">))</span> <span class="o">==</span> <span class="n">p1</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">p3</span> <span class="o">=</span> <span class="n">p1</span> <span class="o">/</span> <span class="s">'baz/qux'</span> <span class="c"># the / operator allows joining, too</span>
|
||||
<span class="gp">>>> </span><span class="n">p2</span> <span class="o">==</span> <span class="n">p3</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">p4</span> <span class="o">=</span> <span class="n">p1</span> <span class="o">+</span> <span class="s">".py"</span>
|
||||
<span class="gp">>>> </span><span class="n">p4</span><span class="o">.</span><span class="n">basename</span> <span class="o">==</span> <span class="s">"bar.py"</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">p4</span><span class="o">.</span><span class="n">ext</span> <span class="o">==</span> <span class="s">".py"</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">p4</span><span class="o">.</span><span class="n">purebasename</span> <span class="o">==</span> <span class="s">"bar"</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This should be possible on every implementation of <tt class="docutils literal"><span class="pre">py.path</span></tt>, so
|
||||
regardless of whether the implementation wraps a UNIX filesystem, a Windows
|
||||
one, or a database or object tree, these functions should be available (each
|
||||
with their own notion of path seperators and dealing with conversions, etc.).</p>
|
||||
</div>
|
||||
<div class="section" id="checking-path-types">
|
||||
<h4>3.2.1.3. Checking path types<a class="headerlink" href="#checking-path-types" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Now we will show a bit about the powerful ‘check()’ method on paths, which
|
||||
allows you to check whether a file exists, what type it is, etc.:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">file1</span> <span class="o">=</span> <span class="n">temppath</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s">'file1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span><span class="o">.</span><span class="n">check</span><span class="p">()</span> <span class="c"># does it exist?</span>
|
||||
<span class="go">False</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span> <span class="o">=</span> <span class="n">file1</span><span class="o">.</span><span class="n">ensure</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="c"># 'touch' the file</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="nb">dir</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="c"># is it a dir?</span>
|
||||
<span class="go">False</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="c"># or a file?</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">ext</span><span class="o">=</span><span class="s">'.txt'</span><span class="p">)</span> <span class="c"># check the extension</span>
|
||||
<span class="go">False</span>
|
||||
<span class="gp">>>> </span><span class="n">textfile</span> <span class="o">=</span> <span class="n">temppath</span><span class="o">.</span><span class="n">ensure</span><span class="p">(</span><span class="s">'text.txt'</span><span class="p">,</span> <span class="nb">file</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">textfile</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">ext</span><span class="o">=</span><span class="s">'.txt'</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">file1</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="n">basename</span><span class="o">=</span><span class="s">'file1'</span><span class="p">)</span> <span class="c"># we can use all the path's properties here</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="setting-svn-properties">
|
||||
<h4>3.2.1.4. Setting svn-properties<a class="headerlink" href="#setting-svn-properties" title="Permalink to this headline">¶</a></h4>
|
||||
<p>As an example of ‘uncommon’ methods, we’ll show how to read and write
|
||||
properties in an <tt class="docutils literal"><span class="pre">py.path.svnwc</span></tt> instance:</p>
|
||||
<div class="highlight-python"><pre>.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> wc.propget('foo')
|
||||
''
|
||||
>>> wc.propset('foo', 'bar')
|
||||
>>> wc.propget('foo')
|
||||
'bar'
|
||||
>>> len(wc.status().prop_modified) # our own props
|
||||
1
|
||||
>>> msg = wc.revert() # roll back our changes
|
||||
>>> len(wc.status().prop_modified)
|
||||
0</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="svn-authentication">
|
||||
<h4>3.2.1.5. SVN authentication<a class="headerlink" href="#svn-authentication" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Some uncommon functionality can also be provided as extensions, such as SVN
|
||||
authentication:</p>
|
||||
<div class="highlight-python"><pre>.. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
|
||||
>>> auth = py.path.SvnAuth('anonymous', 'user', cache_auth=False,
|
||||
... interactive=False)
|
||||
>>> wc.auth = auth
|
||||
>>> wc.update() # this should work
|
||||
>>> path = wc.ensure('thisshouldnotexist.txt')
|
||||
>>> try:
|
||||
... path.commit('testing')
|
||||
... except py.process.cmdexec.Error, e:
|
||||
... pass
|
||||
>>> 'authorization failed' in str(e)
|
||||
True</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="known-problems-limitations">
|
||||
<h2>3.3. Known problems / limitations<a class="headerlink" href="#known-problems-limitations" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li>The SVN path objects require the “svn” command line,
|
||||
there is currently no support for python bindings.
|
||||
Parsing the svn output can lead to problems, particularly
|
||||
regarding if you have a non-english “locales” setting.</li>
|
||||
<li>While the path objects basically work on windows,
|
||||
there is no attention yet on making unicode paths
|
||||
work or deal with the famous “8.3” filename issues.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="future-plans">
|
||||
<h2>3.4. Future plans<a class="headerlink" href="#future-plans" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The Subversion path implementations are based
|
||||
on the <cite>svn</cite> command line, not on the bindings.
|
||||
It makes sense now to directly use the bindings.</p>
|
||||
<p>Moreover, it would be good, also considering
|
||||
<a class="reference external" href="execnet.html">py.execnet</a> distribution of programs, to
|
||||
be able to manipulate Windows Paths on Linux
|
||||
and vice versa. So we’d like to consider
|
||||
refactoring the path implementations
|
||||
to provide this choice (and getting rid
|
||||
of platform-dependencies as much as possible).</p>
|
||||
<p>There is some experimental small approach
|
||||
(<tt class="docutils literal"><span class="pre">py/path/gateway/</span></tt>) aiming at having
|
||||
a convenient Remote Path implementation
|
||||
and some considerations about future
|
||||
works in the according <tt class="docutils literal"><span class="pre">py/path/gateway/TODO.txt</span></tt></p>
|
||||
<p>There are various hacks out there to have
|
||||
Memory-Filesystems and even path objects
|
||||
being directly mountable under Linux (via <cite>fuse</cite>).
|
||||
However, the Path object implementations
|
||||
do not internally have a clean abstraction
|
||||
of going to the filesystem - so with some
|
||||
refactoring it should become easier to
|
||||
have very custom Path objects, still offering
|
||||
the quite full interface without requiring
|
||||
to know about all details of the full path
|
||||
implementation.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">3. py.path</a><ul>
|
||||
<li><a class="reference external" href="#path-implementations-provided-by-py-path">3.1. Path implementations provided by <tt class="docutils literal"><span class="pre">py.path</span></tt></a><ul>
|
||||
<li><a class="reference external" href="#py-path-local">3.1.1. <tt class="docutils literal"><span class="pre">py.path.local</span></tt></a></li>
|
||||
<li><a class="reference external" href="#py-path-svnurl-and-py-path-svnwc">3.1.2. <tt class="docutils literal"><span class="pre">py.path.svnurl</span></tt> and <tt class="docutils literal"><span class="pre">py.path.svnwc</span></tt></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#common-vs-specific-api">3.2. Common vs. specific API</a><ul>
|
||||
<li><a class="reference external" href="#examples">3.2.1. Examples</a><ul>
|
||||
<li><a class="reference external" href="#searching-txt-files">3.2.1.1. Searching <cite>.txt</cite> files</a></li>
|
||||
<li><a class="reference external" href="#working-with-paths">3.2.1.2. Working with Paths</a></li>
|
||||
<li><a class="reference external" href="#checking-path-types">3.2.1.3. Checking path types</a></li>
|
||||
<li><a class="reference external" href="#setting-svn-properties">3.2.1.4. Setting svn-properties</a></li>
|
||||
<li><a class="reference external" href="#svn-authentication">3.2.1.5. SVN authentication</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#known-problems-limitations">3.3. Known problems / limitations</a></li>
|
||||
<li><a class="reference external" href="#future-plans">3.4. Future plans</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="execnet.html"
|
||||
title="previous chapter">2. py.execnet</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="code.html"
|
||||
title="next chapter">4. py.code</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/path.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="code.html" title="4. py.code"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="execnet.html" title="2. py.execnet"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>16.3. py lib 1.0.0: XXX — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="16. Release notes" href="releases.html" />
|
||||
<link rel="prev" title="16.2. py lib 0.9.2: bugfix release" href="release-0.9.2.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-0.9.2.html" title="16.2. py lib 0.9.2: bugfix release"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="releases.html" accesskey="U">16. Release notes</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-lib-1-0-0-xxx">
|
||||
<h1>16.3. py lib 1.0.0: XXX<a class="headerlink" href="#py-lib-1-0-0-xxx" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Welcome to the 1.0.0 py lib release - a library aiming to
|
||||
support agile and test-driven python development on various levels.</p>
|
||||
<p>XXX</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="release-0.9.2.html"
|
||||
title="previous chapter">16.2. py lib 0.9.2: bugfix release</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/release-0.9.0.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-0.9.2.html" title="16.2. py lib 0.9.2: bugfix release"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="releases.html" >16. Release notes</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,127 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>16.2. py lib 0.9.2: bugfix release — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="16. Release notes" href="releases.html" />
|
||||
<link rel="next" title="16.3. py lib 1.0.0: XXX" href="release-0.9.0.html" />
|
||||
<link rel="prev" title="16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more" href="release-1.0.0.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-0.9.0.html" title="16.3. py lib 1.0.0: XXX"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="release-1.0.0.html" title="16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="releases.html" accesskey="U">16. Release notes</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-lib-0-9-2-bugfix-release">
|
||||
<h1>16.2. py lib 0.9.2: bugfix release<a class="headerlink" href="#py-lib-0-9-2-bugfix-release" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Welcome to the 0.9.2 py lib and py.test release -
|
||||
mainly fixing Windows issues, providing better
|
||||
packaging and integration with setuptools.</p>
|
||||
<p>Here is a quick summary of what the py lib provides:</p>
|
||||
<ul class="simple">
|
||||
<li>py.test: cross-project testing tool with many advanced features</li>
|
||||
<li>py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes</li>
|
||||
<li>py.magic.greenlet: micro-threads on standard CPython (“stackless-light”)</li>
|
||||
<li>py.path: path abstractions over local and subversion files</li>
|
||||
<li>rich documentation of py’s exported API</li>
|
||||
<li>tested against Linux, Win32, OSX, works on python 2.3-2.6</li>
|
||||
</ul>
|
||||
<p>See here for more information:</p>
|
||||
<p>Pypi pages: <a class="reference external" href="http://pypi.python.org/pypi/py/">http://pypi.python.org/pypi/py/</a></p>
|
||||
<p>Download/Install: <a class="reference external" href="http://codespeak.net/py/0.9.2/download.html">http://codespeak.net/py/0.9.2/download.html</a></p>
|
||||
<p>Documentation/API: <a class="reference external" href="http://codespeak.net/py/0.9.2/index.html">http://codespeak.net/py/0.9.2/index.html</a></p>
|
||||
<p>best and have fun,</p>
|
||||
<p>holger krekel</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="release-1.0.0.html"
|
||||
title="previous chapter">16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="release-0.9.0.html"
|
||||
title="next chapter">16.3. py lib 1.0.0: XXX</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/release-0.9.2.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-0.9.0.html" title="16.3. py lib 1.0.0: XXX"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="release-1.0.0.html" title="16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="releases.html" >16. Release notes</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,131 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="16. Release notes" href="releases.html" />
|
||||
<link rel="next" title="16.2. py lib 0.9.2: bugfix release" href="release-0.9.2.html" />
|
||||
<link rel="prev" title="16. Release notes" href="releases.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-0.9.2.html" title="16.2. py lib 0.9.2: bugfix release"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="releases.html" title="16. Release notes"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="releases.html" accesskey="U">16. Release notes</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="py-lib-0-9-0-py-test-distributed-execution-greenlets-and-more">
|
||||
<h1>16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more<a class="headerlink" href="#py-lib-0-9-0-py-test-distributed-execution-greenlets-and-more" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Welcome to the 0.9.0 py lib release - a library aiming to
|
||||
support agile and test-driven python development on various levels.</p>
|
||||
<p>Main API/Tool Features:</p>
|
||||
<ul class="simple">
|
||||
<li>py.test: cross-project testing tool with many advanced features</li>
|
||||
<li>py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes</li>
|
||||
<li>py.magic.greenlet: micro-threads on standard CPython (“stackless-light”)</li>
|
||||
<li>py.path: path abstractions over local and subversion files</li>
|
||||
<li>rich documentation of py’s exported API</li>
|
||||
<li>tested against Linux, OSX and partly against Win32, python 2.3-2.5</li>
|
||||
</ul>
|
||||
<p>All these features and their API have extensive documentation,
|
||||
generated with the new “apigen”, which we intend to make accessible
|
||||
for other python projects as well.</p>
|
||||
<p>Download/Install: <a class="reference external" href="http://codespeak.net/py/0.9.0/download.html">http://codespeak.net/py/0.9.0/download.html</a>
|
||||
Documentation/API: <a class="reference external" href="http://codespeak.net/py/0.9.0/index.html">http://codespeak.net/py/0.9.0/index.html</a></p>
|
||||
<p>Work on the py lib has been partially funded by the
|
||||
European Union IST programme and by <a class="reference external" href="http://merlinux.de">http://merlinux.de</a>
|
||||
within the PyPy project.</p>
|
||||
<p>best, have fun and let us know what you think!</p>
|
||||
<p>holger krekel, Maciej Fijalkowski,
|
||||
Guido Wesdorp, Carl Friedrich Bolz</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="releases.html"
|
||||
title="previous chapter">16. Release notes</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="release-0.9.2.html"
|
||||
title="next chapter">16.2. py lib 0.9.2: bugfix release</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/release-1.0.0.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-0.9.2.html" title="16.2. py lib 0.9.2: bugfix release"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="releases.html" title="16. Release notes"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="releases.html" >16. Release notes</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,112 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>16. Release notes — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="next" title="16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more" href="release-1.0.0.html" />
|
||||
<link rel="prev" title="15. Downloading" href="download.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-1.0.0.html" title="16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="download.html" title="15. Downloading"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="release-notes">
|
||||
<h1>16. Release notes<a class="headerlink" href="#release-notes" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Contents:</p>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference external" href="release-1.0.0.html">16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="release-0.9.2.html">16.2. py lib 0.9.2: bugfix release</a></li>
|
||||
<li class="toctree-l1"><a class="reference external" href="release-0.9.0.html">16.3. py lib 1.0.0: XXX</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="download.html"
|
||||
title="previous chapter">15. Downloading</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="release-1.0.0.html"
|
||||
title="next chapter">16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/releases.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="release-1.0.0.html" title="16.1. py lib 0.9.0: py.test, distributed execution, greenlets and more"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="download.html" title="15. Downloading"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,91 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Search — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<script type="text/javascript" src="_static/searchtools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<h1 id="search-documentation">Search</h1>
|
||||
<div id="fallback" class="admonition warning">
|
||||
<script type="text/javascript">$('#fallback').hide();</script>
|
||||
<p>
|
||||
Please activate JavaScript to enable the search
|
||||
functionality.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
From here you can search these documents. Enter your search
|
||||
words into the box below and click "search". Note that the search
|
||||
function will automatically search for all of the words. Pages
|
||||
containing fewer words won't appear in the result list.
|
||||
</p>
|
||||
<form action="" method="get">
|
||||
<input type="text" name="q" value="" />
|
||||
<input type="submit" value="search" />
|
||||
<span id="search-progress" style="padding-left: 10px"></span>
|
||||
</form>
|
||||
|
||||
<div id="search-results">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
<script type="text/javascript" src="searchindex.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.6. Test configuration — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="1.7. Working Examples" href="test-examples.html" />
|
||||
<link rel="prev" title="1.5. Distributed testing" href="test-dist.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-examples.html" title="1.7. Working Examples"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-dist.html" title="1.5. Distributed testing"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="test-configuration">
|
||||
<h1>1.6. Test configuration<a class="headerlink" href="#test-configuration" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="test-options-and-values">
|
||||
<h2>1.6.1. test options and values<a class="headerlink" href="#test-options-and-values" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can see all available command line options by running:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">-</span><span class="n">h</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>py.test will lookup values of options in this order:</p>
|
||||
<ul class="simple">
|
||||
<li>option value supplied at command line</li>
|
||||
<li>content of environment variable <tt class="docutils literal"><span class="pre">PYTEST_OPTION_NAME=...</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">name</span> <span class="pre">=</span> <span class="pre">...</span></tt> setting in the nearest <tt class="docutils literal"><span class="pre">conftest.py</span></tt> file.</li>
|
||||
</ul>
|
||||
<p>The name of an option usually is the one you find
|
||||
in the longform of the option, i.e. the name
|
||||
behind the <tt class="docutils literal"><span class="pre">--</span></tt> double-dash.</p>
|
||||
<p>IOW, you can set default values for options per project, per
|
||||
home-directoray, per shell session or per test-run.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.6. Test configuration</a><ul>
|
||||
<li><a class="reference external" href="#test-options-and-values">1.6.1. test options and values</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-dist.html"
|
||||
title="previous chapter">1.5. Distributed testing</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test-examples.html"
|
||||
title="next chapter">1.7. Working Examples</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-config.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-examples.html" title="1.7. Working Examples"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-dist.html" title="1.5. Distributed testing"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,216 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.5. Distributed testing — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="1.6. Test configuration" href="test-config.html" />
|
||||
<link rel="prev" title="1.4. Writing plugins" href="test-ext.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-config.html" title="1.6. Test configuration"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-ext.html" title="1.4. Writing plugins"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="distributed-testing">
|
||||
<span id="distribute-tests-across-machines"></span><h1>1.5. Distributed testing<a class="headerlink" href="#distributed-testing" title="Permalink to this headline">¶</a></h1>
|
||||
<p><tt class="docutils literal"><span class="pre">py.test</span></tt> can ad-hoc distribute test runs to multiple CPUs or remote
|
||||
machines. This allows to speed up development or to use special resources
|
||||
of remote machines. Before running tests remotely, <tt class="docutils literal"><span class="pre">py.test</span></tt> efficiently
|
||||
synchronizes your program source code to the remote place. All test results
|
||||
are reported back and displayed to your local test session. You may
|
||||
specify different Python versions and interpreters.</p>
|
||||
<p>Synchronisation and running of tests only requires
|
||||
a bare Python installation on the remote side. No
|
||||
special software is installed - this is realized
|
||||
by use of the <strong>zero installation</strong> <a class="reference external" href="execnet.html">py.execnet</a> mechanisms.</p>
|
||||
<div class="section" id="speed-up-test-runs-by-sending-tests-to-multiple-cpus">
|
||||
<h2>1.5.1. Speed up test runs by sending tests to multiple CPUs<a class="headerlink" href="#speed-up-test-runs-by-sending-tests-to-multiple-cpus" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To send tests to multiple CPUs, type:</p>
|
||||
<div class="highlight-python"><pre>py.test -n NUM</pre>
|
||||
</div>
|
||||
<p>Especially for longer running tests or tests requiring
|
||||
a lot of IO this can lead to considerable speed ups.</p>
|
||||
</div>
|
||||
<div class="section" id="running-tests-in-a-python-subprocess">
|
||||
<h2>1.5.2. Running tests in a Python subprocess<a class="headerlink" href="#running-tests-in-a-python-subprocess" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To instantiate a python2.4 sub process and send tests to it, you may type:</p>
|
||||
<div class="highlight-python"><pre>py.test -d --tx popen//python=python2.4</pre>
|
||||
</div>
|
||||
<p>This will start a subprocess which is run with the “python2.4”
|
||||
Python interpreter, found in your system binary lookup path.</p>
|
||||
<p>If you prefix the –tx option value like this:</p>
|
||||
<div class="highlight-python"><pre>--tx 3*popen//python=python2.4</pre>
|
||||
</div>
|
||||
<p>then three subprocesses would be created and tests
|
||||
will be load-balanced across these three processes.</p>
|
||||
</div>
|
||||
<div class="section" id="sending-tests-to-remote-ssh-accounts">
|
||||
<h2>1.5.3. Sending tests to remote SSH accounts<a class="headerlink" href="#sending-tests-to-remote-ssh-accounts" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Suppose you have a package <tt class="docutils literal"><span class="pre">mypkg</span></tt> which contains some
|
||||
tests that you can successfully run locally. And you
|
||||
have a ssh-reachable machine <tt class="docutils literal"><span class="pre">myhost</span></tt>. Then
|
||||
you can ad-hoc distribute your tests by typing:</p>
|
||||
<div class="highlight-python"><pre>py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg</pre>
|
||||
</div>
|
||||
<p>This will synchronize your <tt class="docutils literal"><span class="pre">mypkg</span></tt> package directory
|
||||
to an remote ssh account and then locally collect tests
|
||||
and send them to remote places for execution.</p>
|
||||
<p>You can specify multiple <tt class="docutils literal"><span class="pre">--rsyncdir</span></tt> directories
|
||||
to be sent to the remote side.</p>
|
||||
</div>
|
||||
<div class="section" id="sending-tests-to-remote-socket-servers">
|
||||
<h2>1.5.4. Sending tests to remote Socket Servers<a class="headerlink" href="#sending-tests-to-remote-socket-servers" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Download the single-module <a class="reference external" href="http://codespeak.net/svn/py/dist/py/execnet/script/socketserver.py">socketserver.py</a> Python program
|
||||
and run it like this:</p>
|
||||
<div class="highlight-python"><pre>python socketserver.py</pre>
|
||||
</div>
|
||||
<p>It will tell you that it starts listening on the default
|
||||
port. You can now on your home machine specify this
|
||||
new socket host with something like this:</p>
|
||||
<div class="highlight-python"><pre>py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="running-tests-on-many-platforms-at-once">
|
||||
<span id="atonce"></span><h2>1.5.5. Running tests on many platforms at once<a class="headerlink" href="#running-tests-on-many-platforms-at-once" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The basic command to run tests on multiple platforms is:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">--</span><span class="n">dist</span><span class="o">=</span><span class="n">each</span> <span class="o">--</span><span class="n">tx</span><span class="o">=</span><span class="n">spec1</span> <span class="o">--</span><span class="n">tx</span><span class="o">=</span><span class="n">spec2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you specify a windows host, an OSX host and a Linux
|
||||
environment this command will send each tests to all
|
||||
platforms - and report back failures from all platforms
|
||||
at once. The provided specifications strings
|
||||
use the <a class="reference external" href="execnet.html#xspec">xspec syntax</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="specifying-test-exec-environments-in-a-conftest-py">
|
||||
<h2>1.5.6. Specifying test exec environments in a conftest.py<a class="headerlink" href="#specifying-test-exec-environments-in-a-conftest-py" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Instead of specifying command line options, you can
|
||||
put options values in a <tt class="docutils literal"><span class="pre">conftest.py</span></tt> file like this:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">pytest_option_tx</span> <span class="o">=</span> <span class="p">[</span><span class="s">'ssh=myhost//python=python2.5'</span><span class="p">,</span> <span class="s">'popen//python=python2.5'</span><span class="p">]</span>
|
||||
<span class="n">pytest_option_dist</span> <span class="o">=</span> <span class="bp">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Any commandline <tt class="docutils literal"><span class="pre">--tx</span></tt> specifictions will add to the list of available execution
|
||||
environments.</p>
|
||||
</div>
|
||||
<div class="section" id="specifying-rsync-dirs-in-a-conftest-py">
|
||||
<h2>1.5.7. Specifying “rsync” dirs in a conftest.py<a class="headerlink" href="#specifying-rsync-dirs-in-a-conftest-py" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In your <tt class="docutils literal"><span class="pre">mypkg/conftest.py</span></tt> you may specify directories to synchronise
|
||||
or to exclude:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">rsyncdirs</span> <span class="o">=</span> <span class="p">[</span><span class="s">'.'</span><span class="p">,</span> <span class="s">'../plugins'</span><span class="p">]</span>
|
||||
<span class="n">rsyncignore</span> <span class="o">=</span> <span class="p">[</span><span class="s">'_cache'</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>These directory specifications are relative to the directory
|
||||
where the <tt class="docutils literal"><span class="pre">conftest.py</span></tt> is found.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.5. Distributed testing</a><ul>
|
||||
<li><a class="reference external" href="#speed-up-test-runs-by-sending-tests-to-multiple-cpus">1.5.1. Speed up test runs by sending tests to multiple CPUs</a></li>
|
||||
<li><a class="reference external" href="#running-tests-in-a-python-subprocess">1.5.2. Running tests in a Python subprocess</a></li>
|
||||
<li><a class="reference external" href="#sending-tests-to-remote-ssh-accounts">1.5.3. Sending tests to remote SSH accounts</a></li>
|
||||
<li><a class="reference external" href="#sending-tests-to-remote-socket-servers">1.5.4. Sending tests to remote Socket Servers</a></li>
|
||||
<li><a class="reference external" href="#running-tests-on-many-platforms-at-once">1.5.5. Running tests on many platforms at once</a></li>
|
||||
<li><a class="reference external" href="#specifying-test-exec-environments-in-a-conftest-py">1.5.6. Specifying test exec environments in a conftest.py</a></li>
|
||||
<li><a class="reference external" href="#specifying-rsync-dirs-in-a-conftest-py">1.5.7. Specifying “rsync” dirs in a conftest.py</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-ext.html"
|
||||
title="previous chapter">1.4. Writing plugins</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test-config.html"
|
||||
title="next chapter">1.6. Test configuration</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-dist.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-config.html" title="1.6. Test configuration"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-ext.html" title="1.4. Writing plugins"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,168 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.7. Working Examples — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="2. py.execnet" href="execnet.html" />
|
||||
<link rel="prev" title="1.6. Test configuration" href="test-config.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="execnet.html" title="2. py.execnet"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-config.html" title="1.6. Test configuration"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="working-examples">
|
||||
<h1>1.7. Working Examples<a class="headerlink" href="#working-examples" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="managing-state-at-module-class-and-method-level">
|
||||
<h2>1.7.1. managing state at module, class and method level<a class="headerlink" href="#managing-state-at-module-class-and-method-level" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Here is a working example for what goes on when you setup modules,
|
||||
classes and methods:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="c"># [[from py/documentation/example/pytest/test_setup_flow_example.py]]</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">setup_module</span><span class="p">(</span><span class="n">module</span><span class="p">):</span>
|
||||
<span class="n">module</span><span class="o">.</span><span class="n">TestStateFullThing</span><span class="o">.</span><span class="n">classcount</span> <span class="o">=</span> <span class="mf">0</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">TestStateFullThing</span><span class="p">:</span>
|
||||
<span class="k">def</span> <span class="nf">setup_class</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
|
||||
<span class="n">cls</span><span class="o">.</span><span class="n">classcount</span> <span class="o">+=</span> <span class="mf">1</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">teardown_class</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
|
||||
<span class="n">cls</span><span class="o">.</span><span class="n">classcount</span> <span class="o">-=</span> <span class="mf">1</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">setup_method</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">method</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">method</span><span class="o">.</span><span class="n">func_name</span><span class="p">[</span><span class="mf">5</span><span class="p">:])</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">test_42</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">classcount</span> <span class="o">==</span> <span class="mf">1</span>
|
||||
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mf">42</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">test_23</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">classcount</span> <span class="o">==</span> <span class="mf">1</span>
|
||||
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mf">23</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">teardown_module</span><span class="p">(</span><span class="n">module</span><span class="p">):</span>
|
||||
<span class="k">assert</span> <span class="n">module</span><span class="o">.</span><span class="n">TestStateFullThing</span><span class="o">.</span><span class="n">classcount</span> <span class="o">==</span> <span class="mf">0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>For this example the control flow happens as follows:</p>
|
||||
<div class="highlight-python"><pre>import test_setup_flow_example
|
||||
setup_module(test_setup_flow_example)
|
||||
setup_class(TestStateFullThing)
|
||||
instance = TestStateFullThing()
|
||||
setup_method(instance, instance.test_42)
|
||||
instance.test_42()
|
||||
setup_method(instance, instance.test_23)
|
||||
instance.test_23()
|
||||
teardown_class(TestStateFullThing)
|
||||
teardown_module(test_setup_flow_example)</pre>
|
||||
</div>
|
||||
<p>Note that <tt class="docutils literal"><span class="pre">setup_class(TestStateFullThing)</span></tt> is called and not
|
||||
<tt class="docutils literal"><span class="pre">TestStateFullThing.setup_class()</span></tt> which would require you
|
||||
to insert <tt class="docutils literal"><span class="pre">setup_class</span> <span class="pre">=</span> <span class="pre">classmethod(setup_class)</span></tt> to make
|
||||
your setup function callable. Did we mention that lazyness
|
||||
is a virtue?</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.7. Working Examples</a><ul>
|
||||
<li><a class="reference external" href="#managing-state-at-module-class-and-method-level">1.7.1. managing state at module, class and method level</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-config.html"
|
||||
title="previous chapter">1.6. Test configuration</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="execnet.html"
|
||||
title="next chapter">2. py.execnet</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-examples.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="execnet.html" title="2. py.execnet"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-config.html" title="1.6. Test configuration"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,172 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.4. Writing plugins — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="1.5. Speed up test runs by sending tests to multiple CPUs" href="test-dist.html" />
|
||||
<link rel="prev" title="1.3. Included plugins" href="test-plugins.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-dist.html" title="1.5. Speed up test runs by sending tests to multiple CPUs"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-plugins.html" title="1.3. Included plugins"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="writing-plugins">
|
||||
<h1>1.4. Writing plugins<a class="headerlink" href="#writing-plugins" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="learning-by-examples">
|
||||
<h2>1.4.1. Learning by examples<a class="headerlink" href="#learning-by-examples" title="Permalink to this headline">¶</a></h2>
|
||||
<p>XXX</p>
|
||||
<div class="section" id="adding-custom-options">
|
||||
<h3>1.4.1.1. adding custom options<a class="headerlink" href="#adding-custom-options" title="Permalink to this headline">¶</a></h3>
|
||||
<p>py.test supports adding of standard <a class="reference external" href="http://docs.python.org/library/optparse.html">optparse</a> Options.
|
||||
A plugin may implement the <tt class="docutils literal"><span class="pre">addoption</span></tt> hook for registering
|
||||
custom options:</p>
|
||||
<div class="highlight-python"><pre>class ConftestPlugin:
|
||||
def pytest_addoption(self, parser):
|
||||
parser.addoption("-M", "--myopt", action="store",
|
||||
help="specify string to set myopt")
|
||||
|
||||
def pytest_configure(self, config):
|
||||
if config.option.myopt:
|
||||
# do action based on option value</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="setting-default-values-for-test-options">
|
||||
<h2>1.4.2. Setting default values for test options<a class="headerlink" href="#setting-default-values-for-test-options" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can see all available command line options by running:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">-</span><span class="n">h</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>py.test will lookup values of options in this order:</p>
|
||||
<ul class="simple">
|
||||
<li>option value supplied at command line</li>
|
||||
<li>content of environment variable <tt class="docutils literal"><span class="pre">PYTEST_OPTION_NAME=...</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">name</span> <span class="pre">=</span> <span class="pre">...</span></tt> setting in the nearest <tt class="docutils literal"><span class="pre">conftest.py</span></tt> file.</li>
|
||||
</ul>
|
||||
<p>The name of an option usually is the one you find
|
||||
in the longform of the option, i.e. the name
|
||||
behind the <tt class="docutils literal"><span class="pre">--</span></tt> double-dash.</p>
|
||||
<p>IOW, you can set default values for options per project, per
|
||||
home-directoray, per shell session or per test-run.</p>
|
||||
</div>
|
||||
<div class="section" id="plugin-methods">
|
||||
<h2>1.4.3. Plugin methods<a class="headerlink" href="#plugin-methods" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A Plugin class may implement the following attributes and methods:</p>
|
||||
<p>XXX</p>
|
||||
<p><span class="target" id="pytest-event">pytest event</span>:</p>
|
||||
</div>
|
||||
<div class="section" id="pytest-events">
|
||||
<h2>1.4.4. Pytest Events<a class="headerlink" href="#pytest-events" title="Permalink to this headline">¶</a></h2>
|
||||
<p>XXX</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.4. Writing plugins</a><ul>
|
||||
<li><a class="reference external" href="#learning-by-examples">1.4.1. Learning by examples</a><ul>
|
||||
<li><a class="reference external" href="#adding-custom-options">1.4.1.1. adding custom options</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#setting-default-values-for-test-options">1.4.2. Setting default values for test options</a></li>
|
||||
<li><a class="reference external" href="#plugin-methods">1.4.3. Plugin methods</a></li>
|
||||
<li><a class="reference external" href="#pytest-events">1.4.4. Pytest Events</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-plugins.html"
|
||||
title="previous chapter">1.3. Included plugins</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test-dist.html"
|
||||
title="next chapter">1.5. Speed up test runs by sending tests to multiple CPUs</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-ext.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-dist.html" title="1.5. Speed up test runs by sending tests to multiple CPUs"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-plugins.html" title="1.3. Included plugins"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,371 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.2. Features — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="1.3. Included plugins" href="test-plugins.html" />
|
||||
<link rel="prev" title="1.1. Quickstart" href="test-quickstart.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-plugins.html" title="1.3. Included plugins"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-quickstart.html" title="1.1. Quickstart"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="features">
|
||||
<h1>1.2. Features<a class="headerlink" href="#features" title="Permalink to this headline">¶</a></h1>
|
||||
<p>py.test is a standalone-tool that collects and runs tests for
|
||||
your Python application and modules. py.test works across
|
||||
linux, windows and osx and on Python 2.3 - Python 2.6.</p>
|
||||
<p>It aims to support <em>unit-tests</em> and <em>functional tests</em> written
|
||||
in Python and is used in projects that run more than 10000
|
||||
tests regularly.</p>
|
||||
<p>py.test presents a clean and powerful command line interface
|
||||
and strives to generally make testing a fun effort.</p>
|
||||
<div class="section" id="automatically-collects-and-executes-tests">
|
||||
<h2>1.2.1. automatically collects and executes tests<a class="headerlink" href="#automatically-collects-and-executes-tests" title="Permalink to this headline">¶</a></h2>
|
||||
<p>py.test discovers tests automatically by inspect specified
|
||||
directories or files. By default, it collects all python
|
||||
modules a leading <tt class="docutils literal"><span class="pre">test_</span></tt> or trailing <tt class="docutils literal"><span class="pre">_test</span></tt> filename.
|
||||
From each test module every function with a leading <tt class="docutils literal"><span class="pre">test_</span></tt>
|
||||
or class with a leading <tt class="docutils literal"><span class="pre">Test</span></tt> name is collected.</p>
|
||||
</div>
|
||||
<div class="section" id="load-balance-tests-to-multiple-cpus">
|
||||
<h2>1.2.2. load-balance tests to multiple CPUs<a class="headerlink" href="#load-balance-tests-to-multiple-cpus" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For large test suites you can distribute your
|
||||
tests to multiple CPUs by issuing for example:</p>
|
||||
<div class="highlight-python"><pre>py.test -n 3</pre>
|
||||
</div>
|
||||
<p>Read more on <a class="reference external" href="test-dist.html">distributed testing</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="distribute-tests-across-machines">
|
||||
<h2>1.2.3. Distribute tests across machines<a class="headerlink" href="#distribute-tests-across-machines" title="Permalink to this headline">¶</a></h2>
|
||||
<p>py.test supports the sending of tests to
|
||||
remote ssh-accounts or socket servers.
|
||||
It can <cite>ad-hoc run your test on multiple
|
||||
platforms one a single test run</cite>. Ad-hoc
|
||||
means that there are <strong>no installation
|
||||
requirements whatsoever</strong> on the remote side.</p>
|
||||
</div>
|
||||
<div class="section" id="extensive-debugging-support">
|
||||
<h2>1.2.4. extensive debugging support<a class="headerlink" href="#extensive-debugging-support" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="testing-starts-immediately">
|
||||
<h3>1.2.4.1. testing starts immediately<a class="headerlink" href="#testing-starts-immediately" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Testing starts as soon as the first <tt class="docutils literal"><span class="pre">test</span> <span class="pre">item</span></tt>
|
||||
is collected. The collection process is iterative
|
||||
and does not need to complete before your first
|
||||
test items are executed.</p>
|
||||
</div>
|
||||
<div class="section" id="support-for-modules-containing-tests">
|
||||
<h3>1.2.4.2. support for modules containing tests<a class="headerlink" href="#support-for-modules-containing-tests" title="Permalink to this headline">¶</a></h3>
|
||||
<p>As <tt class="docutils literal"><span class="pre">py.test</span></tt> operates as a separate cmdline
|
||||
tool you can easily have a command line utility and
|
||||
some tests in the same file.</p>
|
||||
</div>
|
||||
<div class="section" id="debug-with-the-print-statement">
|
||||
<h3>1.2.4.3. debug with the <tt class="docutils literal"><span class="pre">print</span></tt> statement<a class="headerlink" href="#debug-with-the-print-statement" title="Permalink to this headline">¶</a></h3>
|
||||
<p>By default, <tt class="docutils literal"><span class="pre">py.test</span></tt> catches text written to stdout/stderr during
|
||||
the execution of each individual test. This output will only be
|
||||
displayed however if the test fails; you will not see it
|
||||
otherwise. This allows you to put debugging print statements in your
|
||||
code without being overwhelmed by all the output that might be
|
||||
generated by tests that do not fail.</p>
|
||||
<p>Each failing test that produced output during the running of the test
|
||||
will have its output displayed in the <tt class="docutils literal"><span class="pre">recorded</span> <span class="pre">stdout</span></tt> section.</p>
|
||||
<p>The catching of stdout/stderr output can be disabled using the
|
||||
<tt class="docutils literal"><span class="pre">--nocapture</span></tt> option to the <tt class="docutils literal"><span class="pre">py.test</span></tt> tool. Any output will
|
||||
in this case be displayed as soon as it is generated.</p>
|
||||
</div>
|
||||
<div class="section" id="test-execution-order">
|
||||
<h3>1.2.4.4. test execution order<a class="headerlink" href="#test-execution-order" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Tests usually run in the order in which they appear in the files.
|
||||
However, tests should not rely on running one after another, as
|
||||
this prevents more advanced usages: running tests
|
||||
distributedly or selectively, or in “looponfailing” mode,
|
||||
will cause them to run in random order.</p>
|
||||
</div>
|
||||
<div class="section" id="assert-with-the-assert-statement">
|
||||
<h3>1.2.4.5. assert with the <tt class="docutils literal"><span class="pre">assert</span></tt> statement<a class="headerlink" href="#assert-with-the-assert-statement" title="Permalink to this headline">¶</a></h3>
|
||||
<p><tt class="docutils literal"><span class="pre">py.test</span></tt> allows to use the standard python
|
||||
<tt class="docutils literal"><span class="pre">assert</span> <span class="pre">statement</span></tt> for verifying expectations
|
||||
and values in Python tests. For example, you can
|
||||
write the following in your tests:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">assert</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s">'attribute'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>to state that your object has a certain <tt class="docutils literal"><span class="pre">attribute</span></tt>. In case this
|
||||
assertion fails you will see the value of <tt class="docutils literal"><span class="pre">x</span></tt>. Intermediate
|
||||
values are computed by executing the assert expression a second time.
|
||||
If you execute code with side effects, e.g. read from a file like this:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">assert</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="o">!=</span> <span class="s">'...'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>then you may get a warning from pytest if that assertions
|
||||
first failed and then succeeded.</p>
|
||||
</div>
|
||||
<div class="section" id="asserting-expected-exceptions">
|
||||
<h3>1.2.4.6. asserting expected exceptions<a class="headerlink" href="#asserting-expected-exceptions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In order to write assertions about exceptions, you use
|
||||
one of two forms:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">raises</span><span class="p">(</span><span class="ne">Exception</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
<span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">raises</span><span class="p">(</span><span class="ne">Exception</span><span class="p">,</span> <span class="s">"func(*args, **kwargs)"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>both of which execute the given function with args and kwargs and
|
||||
asserts that the given <tt class="docutils literal"><span class="pre">Exception</span></tt> is raised. The reporter will
|
||||
provide you with helpful output in case of failures such as <em>no
|
||||
exception</em> or <em>wrong exception</em>.</p>
|
||||
</div>
|
||||
<div class="section" id="useful-tracebacks-recursion-detection">
|
||||
<h3>1.2.4.7. useful tracebacks, recursion detection<a class="headerlink" href="#useful-tracebacks-recursion-detection" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A lot of care is taken to present nice tracebacks in case of test
|
||||
failure. Try:</p>
|
||||
<div class="highlight-python"><pre>py.test py/doc/example/pytest/failure_demo.py</pre>
|
||||
</div>
|
||||
<p>to see a variety of tracebacks, each representing a different
|
||||
failure situation.</p>
|
||||
<p><tt class="docutils literal"><span class="pre">py.test</span></tt> uses the same order for presenting tracebacks as Python
|
||||
itself: the oldest function call is shown first, and the most recent call is
|
||||
shown last. A <tt class="docutils literal"><span class="pre">py.test</span></tt> reported traceback starts with your
|
||||
failing test function. If the maximum recursion depth has been
|
||||
exceeded during the running of a test, for instance because of
|
||||
infinite recursion, <tt class="docutils literal"><span class="pre">py.test</span></tt> will indicate where in the
|
||||
code the recursion was taking place. You can inhibit
|
||||
traceback “cutting” magic by supplying <tt class="docutils literal"><span class="pre">--fulltrace</span></tt>.</p>
|
||||
<p>There is also the possibility of using <tt class="docutils literal"><span class="pre">--tb=short</span></tt> to get regular CPython
|
||||
tracebacks. Or you can use <tt class="docutils literal"><span class="pre">--tb=no</span></tt> to not show any tracebacks at all.</p>
|
||||
</div>
|
||||
<div class="section" id="no-inheritance-requirement">
|
||||
<h3>1.2.4.8. no inheritance requirement<a class="headerlink" href="#no-inheritance-requirement" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Test classes are recognized by their leading <tt class="docutils literal"><span class="pre">Test</span></tt> name. Unlike
|
||||
<tt class="docutils literal"><span class="pre">unitest.py</span></tt>, you don’t need to inherit from some base class to make
|
||||
them be found by the test runner. Besides being easier, it also allows
|
||||
you to write test classes that subclass from application level
|
||||
classes.</p>
|
||||
</div>
|
||||
<div class="section" id="testing-for-deprecated-apis">
|
||||
<h3>1.2.4.9. testing for deprecated APIs<a class="headerlink" href="#testing-for-deprecated-apis" title="Permalink to this headline">¶</a></h3>
|
||||
<p>In your tests you can use <tt class="docutils literal"><span class="pre">py.test.deprecated_call(func,</span> <span class="pre">*args,</span> <span class="pre">**kwargs)</span></tt>
|
||||
to test that a particular function call triggers a DeprecationWarning.
|
||||
This is useful for testing phasing out of old APIs in your projects.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="advanced-test-selection-skipping">
|
||||
<h2>1.2.5. advanced test selection / skipping<a class="headerlink" href="#advanced-test-selection-skipping" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="dynamically-skipping-tests">
|
||||
<h3>1.2.5.1. dynamically skipping tests<a class="headerlink" href="#dynamically-skipping-tests" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you want to skip tests you can use <tt class="docutils literal"><span class="pre">py.test.skip</span></tt> within
|
||||
test or setup functions. Example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">skip</span><span class="p">(</span><span class="s">"message"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can also use a helper to skip on a failing import:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">docutils</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">importorskip</span><span class="p">(</span><span class="s">"docutils"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>or to skip if a library does not have the right version:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">docutils</span> <span class="o">=</span> <span class="n">py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">importorskip</span><span class="p">(</span><span class="s">"docutils"</span><span class="p">,</span> <span class="n">minversion</span><span class="o">=</span><span class="s">"0.3"</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The version will be read from the module’s <tt class="docutils literal"><span class="pre">__version__</span></tt> attribute.</p>
|
||||
</div>
|
||||
<div class="section" id="selecting-unselecting-tests-by-keyword">
|
||||
<span id="selection-by-keyword"></span><h3>1.2.5.2. selecting/unselecting tests by keyword<a class="headerlink" href="#selecting-unselecting-tests-by-keyword" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Pytest’s keyword mechanism provides a powerful way to
|
||||
group and selectively run tests in your test code base.
|
||||
You can selectively run tests by specifiying a keyword
|
||||
on the command line. Examples:</p>
|
||||
<div class="highlight-python"><pre>py.test -k test_simple
|
||||
py.test -k "-test_simple"</pre>
|
||||
</div>
|
||||
<p>will run all tests matching (or not matching) the
|
||||
“test_simple” keyword. Note that you need to quote
|
||||
the keyword if “-” is recognized as an indicator
|
||||
for a commandline option. Lastly, you may use:</p>
|
||||
<div class="highlight-python"><pre>py.test. -k "test_simple:"</pre>
|
||||
</div>
|
||||
<p>which will run all tests after the expression has <em>matched once</em>, i.e.
|
||||
all tests that are seen after a test that matches the “test_simple”
|
||||
keyword.</p>
|
||||
<p>By default, all filename parts and
|
||||
class/function names of a test function are put into the set
|
||||
of keywords for a given test. You may specify additional
|
||||
kewords like this:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="nd">@py</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">mark</span><span class="p">(</span><span class="n">webtest</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
|
||||
<span class="k">def</span> <span class="nf">test_send_http</span><span class="p">():</span>
|
||||
<span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="disabling-a-test-class">
|
||||
<h3>1.2.5.3. disabling a test class<a class="headerlink" href="#disabling-a-test-class" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you want to disable a complete test class you
|
||||
can set the class-level attribute <tt class="docutils literal"><span class="pre">disabled</span></tt>.
|
||||
For example, in order to avoid running some tests on Win32:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">TestPosixOnly</span><span class="p">:</span>
|
||||
<span class="n">disabled</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s">'win32'</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">test_xxx</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="generative-tests-yielding-parametrized-tests">
|
||||
<h2>1.2.6. generative tests: yielding parametrized tests<a class="headerlink" href="#generative-tests-yielding-parametrized-tests" title="Permalink to this headline">¶</a></h2>
|
||||
<p><em>Generative tests</em> are test methods that are <em>generator functions</em> which
|
||||
<tt class="docutils literal"><span class="pre">yield</span></tt> callables and their arguments. This is most useful for running a
|
||||
test function multiple times against different parameters. Example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">test_generative</span><span class="p">():</span>
|
||||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="mf">42</span><span class="p">,</span><span class="mf">17</span><span class="p">,</span><span class="mf">49</span><span class="p">):</span>
|
||||
<span class="k">yield</span> <span class="n">check</span><span class="p">,</span> <span class="n">x</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">arg</span><span class="p">):</span>
|
||||
<span class="k">assert</span> <span class="n">arg</span> <span class="o">%</span> <span class="mf">7</span> <span class="o">==</span> <span class="mf">0</span> <span class="c"># second generated tests fails!</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that <tt class="docutils literal"><span class="pre">test_generative()</span></tt> will cause three tests
|
||||
to get run, notably <tt class="docutils literal"><span class="pre">check(42)</span></tt>, <tt class="docutils literal"><span class="pre">check(17)</span></tt> and <tt class="docutils literal"><span class="pre">check(49)</span></tt>
|
||||
of which the middle one will obviously fail.</p>
|
||||
<p>To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">test_generative</span><span class="p">():</span>
|
||||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">(</span><span class="mf">42</span><span class="p">,</span><span class="mf">17</span><span class="p">,</span><span class="mf">49</span><span class="p">):</span>
|
||||
<span class="k">yield</span> <span class="s">"case </span><span class="si">%d</span><span class="s">"</span> <span class="o">%</span> <span class="n">x</span><span class="p">,</span> <span class="n">check</span><span class="p">,</span> <span class="n">x</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="extensible-plugin-system">
|
||||
<h2>1.2.7. extensible plugin system<a class="headerlink" href="#extensible-plugin-system" title="Permalink to this headline">¶</a></h2>
|
||||
<p>py.test itself consists of many plugins
|
||||
and you can easily write new <a class="reference external" href="test-plugins.html">py.test plugins</a>
|
||||
for these purposes:</p>
|
||||
<ul class="simple">
|
||||
<li>reporting extensions</li>
|
||||
<li>customizing collection and run of tests</li>
|
||||
<li>running non-python tests</li>
|
||||
<li>managing test state setup</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.2. Features</a><ul>
|
||||
<li><a class="reference external" href="#automatically-collects-and-executes-tests">1.2.1. automatically collects and executes tests</a></li>
|
||||
<li><a class="reference external" href="#load-balance-tests-to-multiple-cpus">1.2.2. load-balance tests to multiple CPUs</a></li>
|
||||
<li><a class="reference external" href="#distribute-tests-across-machines">1.2.3. Distribute tests across machines</a></li>
|
||||
<li><a class="reference external" href="#extensive-debugging-support">1.2.4. extensive debugging support</a><ul>
|
||||
<li><a class="reference external" href="#testing-starts-immediately">1.2.4.1. testing starts immediately</a></li>
|
||||
<li><a class="reference external" href="#support-for-modules-containing-tests">1.2.4.2. support for modules containing tests</a></li>
|
||||
<li><a class="reference external" href="#debug-with-the-print-statement">1.2.4.3. debug with the <tt class="docutils literal"><span class="pre">print</span></tt> statement</a></li>
|
||||
<li><a class="reference external" href="#test-execution-order">1.2.4.4. test execution order</a></li>
|
||||
<li><a class="reference external" href="#assert-with-the-assert-statement">1.2.4.5. assert with the <tt class="docutils literal"><span class="pre">assert</span></tt> statement</a></li>
|
||||
<li><a class="reference external" href="#asserting-expected-exceptions">1.2.4.6. asserting expected exceptions</a></li>
|
||||
<li><a class="reference external" href="#useful-tracebacks-recursion-detection">1.2.4.7. useful tracebacks, recursion detection</a></li>
|
||||
<li><a class="reference external" href="#no-inheritance-requirement">1.2.4.8. no inheritance requirement</a></li>
|
||||
<li><a class="reference external" href="#testing-for-deprecated-apis">1.2.4.9. testing for deprecated APIs</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#advanced-test-selection-skipping">1.2.5. advanced test selection / skipping</a><ul>
|
||||
<li><a class="reference external" href="#dynamically-skipping-tests">1.2.5.1. dynamically skipping tests</a></li>
|
||||
<li><a class="reference external" href="#selecting-unselecting-tests-by-keyword">1.2.5.2. selecting/unselecting tests by keyword</a></li>
|
||||
<li><a class="reference external" href="#disabling-a-test-class">1.2.5.3. disabling a test class</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#generative-tests-yielding-parametrized-tests">1.2.6. generative tests: yielding parametrized tests</a></li>
|
||||
<li><a class="reference external" href="#extensible-plugin-system">1.2.7. extensible plugin system</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-quickstart.html"
|
||||
title="previous chapter">1.1. Quickstart</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test-plugins.html"
|
||||
title="next chapter">1.3. Included plugins</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-features.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-plugins.html" title="1.3. Included plugins"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-quickstart.html" title="1.1. Quickstart"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,181 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.3. Included plugins — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="1.4. Learning by examples" href="test-ext.html" />
|
||||
<link rel="prev" title="1.2. Features" href="test-features.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-ext.html" title="1.4. Learning by examples"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-features.html" title="1.2. Features"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="included-plugins">
|
||||
<h1>1.3. Included plugins<a class="headerlink" href="#included-plugins" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Many of py.test’s features are implemented as a plugin.</p>
|
||||
<div class="section" id="id1">
|
||||
<h2>1.3.1. Included plugins<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can find the source code of all default plugins in
|
||||
<a class="reference external" href="http://codespeak.net/svn/py/trunk/py/test/plugin/">http://codespeak.net/svn/py/trunk/py/test/plugin/</a></p>
|
||||
<div class="section" id="plugins-that-add-reporting-asepcts">
|
||||
<h3>1.3.1.1. plugins that add reporting asepcts<a class="headerlink" href="#plugins-that-add-reporting-asepcts" title="Permalink to this headline">¶</a></h3>
|
||||
<p>pytest_terminal: default reporter for writing info to terminals</p>
|
||||
<p>pytest_resultlog: log test results in machine-readable form to a file</p>
|
||||
<p>pytest_eventlog: log all internal pytest events to a file</p>
|
||||
</div>
|
||||
<div class="section" id="plugins-for-adding-new-test-types">
|
||||
<h3>1.3.1.2. plugins for adding new test types<a class="headerlink" href="#plugins-for-adding-new-test-types" title="Permalink to this headline">¶</a></h3>
|
||||
<p>pytest_unittest: run traditional unittest TestCase instances</p>
|
||||
<p>pytest_doctest: run doctests in python modules or .txt files</p>
|
||||
<p>pytest_restdoc: provide RestructuredText syntax and link checking</p>
|
||||
</div>
|
||||
<div class="section" id="plugins-for-python-test-functions">
|
||||
<h3>1.3.1.3. plugins for python test functions<a class="headerlink" href="#plugins-for-python-test-functions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>pytest_xfail: provides “expected to fail” test marker</p>
|
||||
<p>pytest_tmpdir: provide temporary directories to test functions</p>
|
||||
<p>pytest_plugintester: generic plugin apichecks, support for functional plugin tests</p>
|
||||
<p>pytest_apigen: tracing values of function/method calls when running tests</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="loading-plugins-and-specifying-dependencies">
|
||||
<h2>1.3.2. Loading plugins and specifying dependencies<a class="headerlink" href="#loading-plugins-and-specifying-dependencies" title="Permalink to this headline">¶</a></h2>
|
||||
<p>py.test loads and configures plugins at tool startup:</p>
|
||||
<ul class="simple">
|
||||
<li>by reading the <tt class="docutils literal"><span class="pre">PYTEST_PLUGINS</span></tt> environment variable
|
||||
and importing the comma-separated list of plugin names.</li>
|
||||
<li>by loading all plugins specified via one or more <tt class="docutils literal"><span class="pre">-p</span> <span class="pre">name</span></tt>
|
||||
command line options.</li>
|
||||
<li>by loading all plugins specified via a <tt class="docutils literal"><span class="pre">pytest_plugins</span></tt>
|
||||
variable in <tt class="docutils literal"><span class="pre">conftest.py</span></tt> files or test modules.</li>
|
||||
</ul>
|
||||
<div class="section" id="example-ensure-a-plugin-is-loaded">
|
||||
<h3>1.3.2.1. example: ensure a plugin is loaded<a class="headerlink" href="#example-ensure-a-plugin-is-loaded" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you create a <tt class="docutils literal"><span class="pre">conftest.py</span></tt> file with the following content:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">pytest_plugins</span> <span class="o">=</span> <span class="s">"pytest_myextension"</span><span class="p">,</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>then all tests in that directory and below it will run with
|
||||
an instantiated “pytest_myextension”. Here is how instantiation
|
||||
takes place:</p>
|
||||
<ul class="simple">
|
||||
<li>the module <tt class="docutils literal"><span class="pre">pytest_extension</span></tt> will be imported and
|
||||
and its contained <cite>ExtensionPlugin`</cite> class will
|
||||
be instantiated. A plugin module may specify its
|
||||
dependencies via another <tt class="docutils literal"><span class="pre">pytest_plugins</span></tt> definition.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.3. Included plugins</a><ul>
|
||||
<li><a class="reference external" href="#id1">1.3.1. Included plugins</a><ul>
|
||||
<li><a class="reference external" href="#plugins-that-add-reporting-asepcts">1.3.1.1. plugins that add reporting asepcts</a></li>
|
||||
<li><a class="reference external" href="#plugins-for-adding-new-test-types">1.3.1.2. plugins for adding new test types</a></li>
|
||||
<li><a class="reference external" href="#plugins-for-python-test-functions">1.3.1.3. plugins for python test functions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="#loading-plugins-and-specifying-dependencies">1.3.2. Loading plugins and specifying dependencies</a><ul>
|
||||
<li><a class="reference external" href="#example-ensure-a-plugin-is-loaded">1.3.2.1. example: ensure a plugin is loaded</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test-features.html"
|
||||
title="previous chapter">1.2. Features</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test-ext.html"
|
||||
title="next chapter">1.4. Learning by examples</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-plugins.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-ext.html" title="1.4. Learning by examples"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test-features.html" title="1.2. Features"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="contents.html" >Contents</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,155 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>1.1. Quickstart — py lib v1.0.0b1 documentation</title>
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '1.0.0b1',
|
||||
COLLAPSE_MODINDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="py lib v1.0.0b1 documentation" href="index.html" />
|
||||
<link rel="up" title="1. py.test" href="test.html" />
|
||||
<link rel="next" title="1.2. Features" href="test-features.html" />
|
||||
<link rel="prev" title="1. py.test" href="test.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-features.html" title="1.2. Features"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test.html" title="1. py.test"
|
||||
accesskey="P">previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="test.html" accesskey="U">1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="quickstart">
|
||||
<h1>1.1. Quickstart<a class="headerlink" href="#quickstart" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This document assumes basic python knowledge. If you have a
|
||||
<a class="reference external" href="http://pypi.python.org/pypi/setuptools">setuptools installation</a>, install <tt class="docutils literal"><span class="pre">py.test</span></tt> by typing:</p>
|
||||
<div class="highlight-python"><pre>easy_install -U py</pre>
|
||||
</div>
|
||||
<p>For alternative installation methods please see the <a class="reference external" href="download.html">download</a> page.</p>
|
||||
<p>You should now have a <tt class="docutils literal"><span class="pre">py.test</span></tt> command line tool and can
|
||||
look at its documented cmdline options via this command:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">-</span><span class="n">h</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="section" id="writing-and-running-a-test">
|
||||
<h2>1.1.1. Writing and running a test<a class="headerlink" href="#writing-and-running-a-test" title="Permalink to this headline">¶</a></h2>
|
||||
<p><tt class="docutils literal"><span class="pre">py.test</span></tt> is the command line tool to run tests.
|
||||
Let’s write a first test module by putting the following
|
||||
test function into a <tt class="docutils literal"><span class="pre">test_sample.py</span></tt> file:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="c"># content of test_sample.py</span>
|
||||
<span class="k">def</span> <span class="nf">test_answer</span><span class="p">():</span>
|
||||
<span class="k">assert</span> <span class="mf">42</span> <span class="o">==</span> <span class="mf">43</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now you can run the test by passing it as an argument:</p>
|
||||
<div class="highlight-python"><pre>py.test test_sample.py</pre>
|
||||
</div>
|
||||
<p>What does happen here? <tt class="docutils literal"><span class="pre">py.test</span></tt> looks for functions and
|
||||
methods in the module that start with <tt class="docutils literal"><span class="pre">test_</span></tt>. It then
|
||||
executes those tests. Assertions about test outcomes are
|
||||
done via the standard <tt class="docutils literal"><span class="pre">assert</span></tt> statement.</p>
|
||||
<p>You can also use <tt class="docutils literal"><span class="pre">py.test</span></tt> to run all tests in a directory structure by
|
||||
invoking it without any arguments:</p>
|
||||
<div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will automatically collect and run any Python module whose filenames
|
||||
start with <tt class="docutils literal"><span class="pre">test_</span></tt> or ends with <tt class="docutils literal"><span class="pre">_test</span></tt> from the directory and any
|
||||
subdirectories, starting with the current directory, and run them. Each
|
||||
Python test module is inspected for test methods starting with <tt class="docutils literal"><span class="pre">test_</span></tt>.</p>
|
||||
<p>Please refer to <a class="reference external" href="test-features.html">features</a> for a walk through the basic features.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="index.html">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference external" href="">1.1. Quickstart</a><ul>
|
||||
<li><a class="reference external" href="#writing-and-running-a-test">1.1.1. Writing and running a test</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Previous topic</h4>
|
||||
<p class="topless"><a href="test.html"
|
||||
title="previous chapter">1. py.test</a></p>
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="test-features.html"
|
||||
title="next chapter">1.2. Features</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/test-quickstart.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="test-features.html" title="1.2. Features"
|
||||
>next</a> |</li>
|
||||
<li class="right" >
|
||||
<a href="test.html" title="1. py.test"
|
||||
>previous</a> |</li>
|
||||
<li><a href="index.html">py lib v1.0.0b1 documentation</a> »</li>
|
||||
<li><a href="test.html" >1. py.test</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2009, Holger Krekel.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.7.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue