2008-08-16 23:26:59 +08:00
|
|
|
====================================
|
|
|
|
Miscellaneous features of the py lib
|
|
|
|
====================================
|
|
|
|
|
|
|
|
Mapping the standard python library into py
|
|
|
|
===========================================
|
|
|
|
|
2009-04-02 15:52:32 +08:00
|
|
|
The :api:`py.std` object allows lazy access to
|
|
|
|
standard library modules. For example, to get to the print-exception
|
2008-08-16 23:26:59 +08:00
|
|
|
functionality of the standard library you can write::
|
|
|
|
|
|
|
|
py.std.traceback.print_exc()
|
|
|
|
|
|
|
|
without having to do anything else than the usual ``import py``
|
2009-04-02 15:52:32 +08:00
|
|
|
at the beginning. You can access any other top-level standard
|
|
|
|
library module this way. This means that you will only trigger
|
|
|
|
imports of modules that are actually needed. Note that no attempt
|
|
|
|
is made to import submodules.
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
Support for interaction with system utilities/binaries
|
|
|
|
======================================================
|
|
|
|
|
|
|
|
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``
|
|
|
|
----------------------------
|
|
|
|
|
2009-04-03 02:59:31 +08:00
|
|
|
In order to synchronously execute an executable file you
|
|
|
|
can use ``sysexec``::
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
binsvn.sysexec('ls', 'http://codespeak.net/svn')
|
|
|
|
|
|
|
|
where ``binsvn`` is a path that points to the ``svn`` commandline
|
2009-04-03 02:59:31 +08:00
|
|
|
binary. Note that this function does not offer any shell-escaping
|
|
|
|
so you have to pass in already separated arguments.
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
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/`
|
|
|
|
|
2008-10-01 17:24:24 +08:00
|
|
|
The compat and builtin namespaces help to write code using newer python features on older python interpreters.
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
:api:`py.compat`
|
|
|
|
----------------
|
|
|
|
|
2008-10-01 17:24:24 +08:00
|
|
|
: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:
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
* doctest
|
|
|
|
* optparse
|
|
|
|
* subprocess
|
|
|
|
* textwrap
|
|
|
|
|
2008-10-01 17:24:24 +08:00
|
|
|
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.
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
:api:`py.builtin`
|
|
|
|
-----------------
|
|
|
|
|
2008-10-01 17:24:24 +08:00
|
|
|
: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:
|
2008-08-16 23:26:59 +08:00
|
|
|
|
|
|
|
* 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.
|