sources for misc.html [rev. unknown]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <title>[misc] </title>
    <meta content="text/html;charset=ISO-8859-1" name="Content-Type"/>
    <link href="style.css" media="screen" rel="stylesheet" type="text/css"/></head>
  <body>
    <div><a href="http://codespeak.net"><img alt="py lib" height="114" id="pyimg" src="http://codespeak.net/img/pylib.png" width="154"/></a></div>
    <div id="metaspace">
      <div class="project_title">[misc] </div>
      <div id="menubar"><a class="menu" href="index.html">index</a> <a class="menu" href="../../apigen/api/index.html">api</a> <a class="menu" href="../../apigen/source/index.html">source</a> <a class="menu" href="contact.html">contact</a> <a class="menu" href="download.html">download</a></div></div>
    <div id="contentspace">
      <div id="docinfoline">
        <div style="float: right; font-style: italic;"> </div></div>
<div class="document" id="miscellaneous-features-of-the-py-lib">
<h1 class="title">Miscellaneous features of the py lib</h1>
<div class="contents topic">
<p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
<ul class="auto-toc simple">
<li><a class="reference" href="#mapping-the-standard-python-library-into-py" id="id1" name="id1">1&nbsp;&nbsp;&nbsp;Mapping the standard python library into py</a><ul class="auto-toc">
<li><a class="reference" href="#the-py-std-hook" id="id2" name="id2">1.1&nbsp;&nbsp;&nbsp;The py.std hook</a></li>
<li><a class="reference" href="#automagically-accessing-sub-packages-doesn-t-work-yet" id="id3" name="id3">1.2&nbsp;&nbsp;&nbsp;Automagically accessing sub packages doesn't work (yet?)</a></li>
<li><a class="reference" href="#note-you-get-an-attributeerror-not-an-importerror" id="id4" name="id4">1.3&nbsp;&nbsp;&nbsp;Note: you get an AttributeError, not an ImportError</a></li>
</ul>
</li>
<li><a class="reference" href="#support-for-interaction-with-system-utilities-binaries" id="id5" name="id5">2&nbsp;&nbsp;&nbsp;Support for interaction with system utilities/binaries</a><ul class="auto-toc">
<li><a class="reference" href="#the-shell-based-approach" id="id6" name="id6">2.1&nbsp;&nbsp;&nbsp;The shell based approach</a></li>
<li><a class="reference" href="#local-paths-have-sysexec" id="id7" name="id7">2.2&nbsp;&nbsp;&nbsp;local paths have <tt class="docutils literal"><span class="pre">sysexec</span></tt></a></li>
<li><a class="reference" href="#finding-an-executable-local-path" id="id8" name="id8">2.3&nbsp;&nbsp;&nbsp;finding an executable local path</a></li>
</ul>
</li>
<li><a class="reference" href="#cross-python-version-compatibility-helpers" id="id9" name="id9">3&nbsp;&nbsp;&nbsp;Cross-Python Version compatibility helpers</a><ul class="auto-toc">
<li><a class="reference" href="#py-compat" id="id10" name="id10">3.1&nbsp;&nbsp;&nbsp;py.compat</a></li>
<li><a class="reference" href="#py-builtin" id="id11" name="id11">3.2&nbsp;&nbsp;&nbsp;py.builtin</a></li>
</ul>
</li>
</ul>
</div>
<div class="section">
<h1><a class="toc-backref" href="#id1" id="mapping-the-standard-python-library-into-py" name="mapping-the-standard-python-library-into-py">1&nbsp;&nbsp;&nbsp;Mapping the standard python library into py</a></h1>
<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">
<h2><a id="the-py-std-hook" name="the-py-std-hook">1.1&nbsp;&nbsp;&nbsp;The <a class="reference" href="../../apigen/api/std.html">py.std</a> hook</a></h2>
<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 &quot;import&quot;
statements.  For example, to get to the print-exception
functionality of the standard library you can write:</p>
<pre class="literal-block">
py.std.traceback.print_exc()
</pre>
<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
<span class="incremental">python standard library</span> 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" 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">
<h2><a class="toc-backref" href="#id3" id="automagically-accessing-sub-packages-doesn-t-work-yet" name="automagically-accessing-sub-packages-doesn-t-work-yet">1.2&nbsp;&nbsp;&nbsp;Automagically accessing sub packages doesn't work (yet?)</a></h2>
<p>If you use the <a class="reference" href="../../apigen/api/std.html">py.std</a> 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>
<pre class="literal-block">
import svn.client
</pre>
<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 <a class="reference" href="../../apigen/api/std.html">py.std</a> 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">
<h2><a class="toc-backref" href="#id4" id="note-you-get-an-attributeerror-not-an-importerror" name="note-you-get-an-attributeerror-not-an-importerror">1.3&nbsp;&nbsp;&nbsp;Note: you get an AttributeError, not an ImportError</a></h2>
<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>
<pre class="literal-block">
getattr(py.std.cStringIO, 'StringIO', py.std.StringIO.StringIO)
</pre>
<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">
<h1><a class="toc-backref" href="#id5" id="support-for-interaction-with-system-utilities-binaries" name="support-for-interaction-with-system-utilities-binaries">2&nbsp;&nbsp;&nbsp;Support for interaction with system utilities/binaries</a></h1>
<p>sources:</p>
<blockquote>
<ul class="simple">
<li><a class="reference" href="../../apigen/source/process/index.html">py/process/</a></li>
<li><a class="reference" href="../../apigen/source/path/local/index.html">py/path/local/</a></li>
</ul>
</blockquote>
<p>Currently, the py lib offers two ways to interact with
system executables. <a class="reference" href="../../apigen/api/process.cmdexec.html">py.process.cmdexec()</a> invokes
the shell in order to execute a string.  The other
one, <a class="reference" href="../../apigen/api/path.local.html">py.path.local</a>'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">
<h2><a class="toc-backref" href="#id6" id="the-shell-based-approach" name="the-shell-based-approach">2.1&nbsp;&nbsp;&nbsp;The shell based approach</a></h2>
<p>You can execute a command via your system shell
by doing something like:</p>
<pre class="literal-block">
out = py.process.cmdexec('ls -v')
</pre>
<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 &quot;fix&quot; the binary you want to run.</li>
<li>it only allows to execute executables from the local
filesystem</li>
</ul>
</div>
<div class="section">
<h2><a class="toc-backref" href="#id7" id="local-paths-have-sysexec" name="local-paths-have-sysexec"><span id="sysexec"></span>2.2&nbsp;&nbsp;&nbsp;local paths have <tt class="docutils literal"><span class="pre">sysexec</span></tt></a></h2>
<p>The py lib currently offers a stripped down functionality of what
the new <a class="reference" 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>
<pre class="literal-block">
binsvn.sysexec('ls', 'http://codespeak.net/svn')
</pre>
<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" 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" 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" href="http://pywin32.sourceforge.net/">pywin32 package</a>.</p>
</div>
<div class="section">
<h2><a class="toc-backref" href="#id8" id="finding-an-executable-local-path" name="finding-an-executable-local-path">2.3&nbsp;&nbsp;&nbsp;finding an executable local path</a></h2>
<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>
<pre class="literal-block">
py.path.local.sysfind('svn')
</pre>
<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, <span class="incremental">sysfind</span> 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>
<pre class="literal-block">
def mysvn(p):
    &quot;&quot;&quot; check that the given svn binary has version 1.1. &quot;&quot;&quot;
    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 class="section">
<h1><a class="toc-backref" href="#id9" id="cross-python-version-compatibility-helpers" name="cross-python-version-compatibility-helpers">3&nbsp;&nbsp;&nbsp;Cross-Python Version compatibility helpers</a></h1>
<p>sources:</p>
<blockquote>
<ul class="simple">
<li><a class="reference" href="../../apigen/source/compat/index.html">py/compat/</a></li>
<li><a class="reference" href="../../apigen/source/builtin/index.html">py/builtin/</a></li>
</ul>
</blockquote>
<p>The py-lib contains some helpers that make writing scripts that work on various
Python versions easier.</p>
<div class="section">
<h2><a id="py-compat" name="py-compat">3.1&nbsp;&nbsp;&nbsp;<a class="reference" href="../../apigen/api/compat.html">py.compat</a></a></h2>
<p><a class="reference" href="../../apigen/api/compat.html">py.compat</a> provides fixed versions (currently from Python 2.4.4) of
various newer modules to be able to use them in various 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>They are used by replacing the normal <tt class="docutils literal"><span class="pre">import</span> <span class="pre">...</span></tt> byr
<tt class="docutils literal"><span class="pre">from</span> <span class="pre">py.compat</span> <span class="pre">import</span> <span class="pre">...</span></tt>.</p>
</div>
<div class="section">
<h2><a id="py-builtin" name="py-builtin">3.2&nbsp;&nbsp;&nbsp;<a class="reference" href="../../apigen/api/builtin.html">py.builtin</a></a></h2>
<p><a class="reference" href="../../apigen/api/builtin.html">py.builtin</a> provides various builtins that were added in later Python
versions. If the used Python version used does not provide these builtins, they
are pure-Python 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><a class="reference" href="../../apigen/api/builtin.BaseException.html">py.builtin.BaseException</a> is just <tt class="docutils literal"><span class="pre">Exception</span></tt> before Python 2.5.</p>
</div>
</div>
</div>
</div></body></html>