Changeset 759

Show
Ignore:
Timestamp:
07/21/07 00:49:41 (1 year ago)
Author:
robin
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pyrun/trunk/README.txt

    r754 r759  
    1616  ``python ~/pyrun.py  ~/my/python/libs ~/my/python/scripts/go.py`` 
    1717 
    18 Is all you need in order to run the `go.py' module with a sys.path automatically 
    19 discovered from directories under `~/my/python/libs`. You can list an arbitrary 
    20 number of directories or paths to actual python files. The order you list them 
    21 controls the order in which the path extension entries are built. The resulting 
    22 path will not contain any duplicates. Each entry in the path extension will b
    23 a legitimate import path; Ie., 
     18Is all you need in order to run the `go.py` module with a sys.path 
     19automatically discovered from directories under `~/my/python/libs`. You can 
     20list an arbitrary number of directories and paths to actual python files. The 
     21order you list them controls the order in which the path extension entries are 
     22built. The resulting path will not contain any duplicates. Each entry in th
     23path extension will be a legitimate import path; Ie., 
    2424 
    2525 * It is a directory on the file system with one or more child directories 
     
    2828 * OR It is an egg path 
    2929 
    30 If non of the non option arguments identify a python module file then pyrun 
    31 will simply print the path it has discovered and exit. If one or more 
    32 python module files are included in the arguments then pyrun will 'run' th
    33 last one listed. sys.path and sys.argv are adjusted so that your module is 
    34 the __main__ entry point upon execution and the discovered path is available 
    35 for resolving its imports. 
     30If none of the non option arguments identify a python module file then pyrun 
     31will simply print the path it has discovered and exit. If one or more python 
     32module files are included in the arguments then pyrun will 'run' the first on
     33listed. `sys.path` and `sys.argv` are adjusted so that your module is the 
     34__main__ entry point upon execution and the discovered path is available for 
     35resolving its imports. 
    3636 
    37 If the module you are running does not naturaly accept a non option argument 
     37If the module you are running does not naturally accept a non option argument 
    3838immediately after the module name then you can use `--` to explicitly delimit 
    3939the end of the arguments to pyrun. For example, the distribution 
     
    4949For egg paths only the *best* version of each egg is allowed onto the extended 
    5050path, and only if the egg is compatible with the current `sys.executable` 
    51 version. The measure of `best egg` uses the same algorithm as used by  
     51version. The measure of `best egg` uses the same algorithm as used by 
    5252the pkg_resources.py module distributed by the setuptools project. 
    5353 
    54 But, NOTE that the current version does not filter out incompatible 
    55 `platforms` for eggs that contain c extensions - see `pyrun.filter_best_eggs` 
    56 if you have time on your hands, its not to much work to add this check. 
     54NOTE: The current version does not filter out incompatible `platforms` for eggs 
     55that contain c extensions - see `pyrun.filter_best_eggs` if you have time on 
     56your hands, its not to much work to add this check. 
    5757 
    5858 
    5959The issue tracker for this package can be found at: 
    60 http://trac.wiretooth.com/open/. When opening a ticket please assign it to  
    61 the 'pyrun' component or mention pyrun in the summary. 
    62   
     60http://trac.wiretooth.com/open/. When opening a ticket please assign it to the 
     61'pyrun' component or mention pyrun in the summary. 
    6362 
    64 Provides facilities which are generally useful for implementing command line 
    65 interfaces and utilities. 
  • pyrun/trunk/examples/discover_and_run.html

    r758 r759  
    290290<h1 class="title">discover_and_run</h1> 
    291291 
     292<p>All of the command line programs provided by this package are essentially thin 
     293wrappers around the <cite>pyrun.discover_and_run</cite> function. This section provides 
     294<cite>doctest</cite> based discussion and examples. These examples are also part of the 
     295pyrun test suite.</p> 
    292296<p>Lets setup a fake set of python packages and use it to illustrate some basics.</p> 
    293297<blockquote> 
     
    295299&gt;&gt;&gt; import os, sys 
    296300&gt;&gt;&gt; from os.path import join 
    297 &gt;&gt;&gt; from tempfile import mkdtemp 
    298 &gt;&gt;&gt; from distutils.dir_util import mkpath 
    299301&gt;&gt;&gt; import pyrun 
    300 &gt;&gt;&gt; tmpdir = mkdtemp(prefix='pyrun-tmp') 
     302&gt;&gt;&gt; from _testutils import mktmpfiles, printpaths 
    301303&gt;&gt;&gt; sysver_cur = sys.version[:3] 
    302304&gt;&gt;&gt; sysver_notcompatible = '.'.join(map(str, 
    303305...   [sys.version_info[0], sys.version_info[1] + 1])) 
    304 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    305 ...     'A', 'AA', 'paaa', 'paaaa')) 
    306 &gt;&gt;&gt; _=file(join(tmpdir, 
    307 ...     'A', 'AA', 'paaa', '__init__.py'), mode='wb') 
    308 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    309 ...     'B', 'BB', 'paaa', 'paaaa')) 
    310 &gt;&gt;&gt; _=file(join(tmpdir, 
    311 ...     'B', 'BB', 'paaa', '__init__.py'), mode='wb') 
    312 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    313 ...     'B', 'BB', 'pbbb', 'pbbbb')) 
    314 &gt;&gt;&gt; _=file(join(tmpdir, 
    315 ...     'B', 'BB', 'pbbb', 'pbbbb', '__init__.py'), mode='wb') 
    316 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    317 ...     'B', 'pc')) 
    318 &gt;&gt;&gt; _=file(join(tmpdir, 
    319 ...     'B', 'pc', '__init__.py'), mode='wb') 
    320 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    321 ...     'Modules',)) 
    322 &gt;&gt;&gt; _=file(join(tmpdir, 
    323 ...     'Modules', 'module_a.py'), 'wb') 
    324 &gt;&gt;&gt; _=file(join(tmpdir, 
    325 ...     'Modules', 'module_b.py'), 'wb') 
     306&gt;&gt;&gt; tmpdir, canonicalpaths = mktmpfiles(( 
     307...     'A/AA/paaa/__init__.py', 
     308...     'A/AA/paaa/paaaa/', 
     309...     'B/BB/paaa/__init__.py', 
     310...     'B/BB/paaa/paaaa/', 
     311...     'B/BB/pbbb/pbbbb/__init__.py', 
     312...     'B/pc/__init__.py', 
     313...     'Modules/module_a.py', 
     314...     'Modules/module_b.py'), 
     315... 
     316...     prefix='pyrun-' 
     317...     ) 
    326318</pre> 
    327319</blockquote> 
     
    331323<pre class="doctest-block"> 
    332324&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 
    333 &gt;&gt;&gt; ':'.join([p.replace(tmpdir + os.path.sep, '', 1) for p in pth]) 
    334 'A/AA:B:B/BB:B/BB/pbbb' 
     325&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     326A/AA 
     327
     328B/BB 
     329B/BB/pbbb 
    335330</pre> 
    336331</blockquote> 
     
    342337...     join(tmpdir, 'B'), tmpdir], run_module=False 
    343338...     ) 
    344 &gt;&gt;&gt; ':'.join([p.replace(tmpdir + os.path.sep,'', 1).replace(os.path.sep, '/') 
    345 ...     for p in pth]) 
    346 'B:B/BB:B/BB/pbbb:A/AA' 
     339&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     340
     341B/BB 
     342B/BB/pbbb 
     343A/AA 
    347344</pre> 
    348345</blockquote> 
     
    353350&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 
    354351...     join(tmpdir, 'Modules', 'module_a.py')], run_module=False) 
    355 &gt;&gt;&gt; ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    356 ...     for p in pth]) 
    357 'Modules:A/AA:B:B/BB:B/BB/pbbb' 
     352&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     353Modules 
     354A/AA 
     355
     356B/BB 
     357B/BB/pbbb 
    358358</pre> 
    359359</blockquote> 
     
    365365...     join(tmpdir, 'Modules', 'module_a.py'), 
    366366...     join(tmpdir, 'Modules', 'module_b.py')], run_module=False) 
    367 &gt;&gt;&gt; ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    368 ...     for p in pth]) 
    369 'Modules:A/AA:B:B/BB:B/BB/pbbb' 
     367&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     368Modules 
     369A/AA 
     370
     371B/BB 
     372B/BB/pbbb 
    370373</pre> 
    371374</blockquote> 
     
    379382viable, especialy given the module loading facilities in the runpy standard 
    380383lib module. I suspect the &quot;force to front&quot; rule is essential for covering 
    381 <em>my</em> use case which is &quot;just fix my path and run that script damit!&quot; 
    382 Lets drop some eggs into the mix. We dont use real eggs for these examples 
     384<em>my</em> use case which is &quot;just fix my path and run that script damit!&quot;</p> 
     385<p>Lets drop some eggs into the mix. We dont use real eggs for these examples 
    383386because the discovery of eggs does not look at egg contents - only file and 
    384387directory names.</p> 
    385388<blockquote> 
    386389<pre class="doctest-block"> 
    387 &gt;&gt;&gt; _=file(join(tmpdir, 
    388 ...     'Modules', 'foo-0.1-py%s.egg' % sysver_cur), 'wb') 
    389 &gt;&gt;&gt; _=file(join(tmpdir, 
    390 ...     'Modules', 'foo-0.2-py%s.egg' % sysver_cur), 'wb') 
    391 &gt;&gt;&gt; _=file(join(tmpdir, 
    392 ...     'Modules', 'foo-0.3-py%s.egg' % sysver_notcompatible), 'wb') 
    393 &gt;&gt;&gt; _=file(join(tmpdir, 
    394 ...     'Modules', 'foo-0.2-py%s.egg-link' % sysver_cur), 'wb') 
    395 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    396 ...     'A', 'bar-0.1-py%s.egg' % sysver_cur)) 
    397 &gt;&gt;&gt; _=mkpath(join(tmpdir, 
    398 ...     'B', 'bar-0.2-py%s.egg' % sysver_cur)) 
    399 </pre> 
    400 </blockquote> 
    401 <p>The full search,</p> 
     390&gt;&gt;&gt; tmpdir, canonicalpaths = mktmpfiles(( 
     391...     'Modules/foo-0.1-py%s.egg' % sysver_cur, 
     392...     'Modules/foo-0.2-py%s.egg' % sysver_cur, 
     393...     'Modules/foo-0.2-py%s.egg-link' % sysver_cur, 
     394...     'Modules/zzz-0.2-py%s.egg-link' % sysver_cur, 
     395...     'Modules/foo-0.3-py%s.egg' % sysver_notcompatible, 
     396...     'A/bar-0.1-py%s.egg' % sysver_cur, 
     397...     'B/bar-0.2-py%s.egg' % sysver_cur), 
     398...     tmpdir=tmpdir 
     399...     ) 
     400</pre> 
     401</blockquote> 
     402<p>A full search,</p> 
    402403<blockquote> 
    403404<pre class="doctest-block"> 
    404405&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 
    405 &gt;&gt;&gt; ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    406 ...     for p in pth]) 
    407 'A/AA:B/bar-0.2-py2.5.egg:B:B/BB:B/BB/pbbb:Modules/foo-0.2-py2.5.egg' 
    408 </pre> 
    409 </blockquote> 
    410 <p>The search that considers 'B' first</p> 
     406&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     407A/AA 
     408B/bar-0.2-py2.5.egg 
     409
     410B/BB 
     411B/BB/pbbb 
     412Modules/foo-0.2-py2.5.egg 
     413</pre> 
     414</blockquote> 
     415<p>A search that considers 'B' first</p> 
    411416<blockquote> 
    412417<pre class="doctest-block"> 
     
    414419...     join(tmpdir, 'B'), tmpdir], run_module=False 
    415420...     ) 
    416 &gt;&gt;&gt; ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    417 ...     for p in pth]) 
    418 'B/bar-0.2-py2.5.egg:B:B/BB:B/BB/pbbb:A/AA:Modules/foo-0.2-py2.5.egg' 
     421&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     422B/bar-0.2-py2.5.egg 
     423
     424B/BB 
     425B/BB/pbbb 
     426A/AA 
     427Modules/foo-0.2-py2.5.egg 
    419428</pre> 
    420429</blockquote> 
  • pyrun/trunk/examples/discover_and_run.rst

    r757 r759  
    11discover_and_run 
    22................ 
     3 
     4All of the command line programs provided by this package are essentially thin 
     5wrappers around the `pyrun.discover_and_run` function. This section provides 
     6`doctest` based discussion and examples. These examples are also part of the 
     7pyrun test suite. 
    38 
    49Lets setup a fake set of python packages and use it to illustrate some basics. 
     
    611    >>> import os, sys 
    712    >>> from os.path import join 
    8     >>> from tempfile import mkdtemp 
    9     >>> from distutils.dir_util import mkpath 
    1013    >>> import pyrun 
    11     >>> tmpdir = mkdtemp(prefix='pyrun-tmp') 
     14    >>> from _testutils import mktmpfiles, printpaths 
    1215    >>> sysver_cur = sys.version[:3] 
    1316    >>> sysver_notcompatible = '.'.join(map(str, 
    1417    ...   [sys.version_info[0], sys.version_info[1] + 1])) 
    15     >>> _=mkpath(join(tmpdir, 
    16     ...     'A', 'AA', 'paaa', 'paaaa')) 
    17     >>> _=file(join(tmpdir, 
    18     ...     'A', 'AA', 'paaa', '__init__.py'), mode='wb') 
    19     >>> _=mkpath(join(tmpdir, 
    20     ...     'B', 'BB', 'paaa', 'paaaa')) 
    21     >>> _=file(join(tmpdir, 
    22     ...     'B', 'BB', 'paaa', '__init__.py'), mode='wb') 
    23     >>> _=mkpath(join(tmpdir, 
    24     ...     'B', 'BB', 'pbbb', 'pbbbb')) 
    25     >>> _=file(join(tmpdir, 
    26     ...     'B', 'BB', 'pbbb', 'pbbbb', '__init__.py'), mode='wb') 
    27     >>> _=mkpath(join(tmpdir, 
    28     ...     'B', 'pc')) 
    29     >>> _=file(join(tmpdir, 
    30     ...     'B', 'pc', '__init__.py'), mode='wb') 
    31     >>> _=mkpath(join(tmpdir, 
    32     ...     'Modules',)) 
    33     >>> _=file(join(tmpdir, 
    34     ...     'Modules', 'module_a.py'), 'wb') 
    35     >>> _=file(join(tmpdir, 
    36     ...     'Modules', 'module_b.py'), 'wb') 
     18    >>> tmpdir, canonicalpaths = mktmpfiles(( 
     19    ...     'A/AA/paaa/__init__.py', 
     20    ...     'A/AA/paaa/paaaa/', 
     21    ...     'B/BB/paaa/__init__.py', 
     22    ...     'B/BB/paaa/paaaa/', 
     23    ...     'B/BB/pbbb/pbbbb/__init__.py', 
     24    ...     'B/pc/__init__.py', 
     25    ...     'Modules/module_a.py', 
     26    ...     'Modules/module_b.py'), 
     27    ... 
     28    ...     prefix='pyrun-' 
     29    ...     ) 
     30 
    3731 
    3832This search gives an os dependent ordering of all packages under A and B 
     
    4034 
    4135    >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 
    42     >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) for p in pth]) 
    43     'A/AA:B:B/BB:B/BB/pbbb' 
     36    >>> printpaths(pth, strip=tmpdir) 
     37    A/AA 
     38    B 
     39    B/BB 
     40    B/BB/pbbb 
    4441 
    4542This search forces paths under 'B' to be considered first, again note that 
     
    4946    ...     join(tmpdir, 'B'), tmpdir], run_module=False 
    5047    ...     ) 
    51     >>> ':'.join([p.replace(tmpdir + os.path.sep,'', 1).replace(os.path.sep, '/') 
    52     ...     for p in pth]) 
    53     'B:B/BB:B/BB/pbbb:A/AA' 
     48    >>> printpaths(pth, strip=tmpdir) 
     49    B 
     50    B/BB 
     51    B/BB/pbbb 
     52    A/AA 
    5453 
    5554Modules is not present in either of the above resulting paths because python 
     
    5857    >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 
    5958    ...     join(tmpdir, 'Modules', 'module_a.py')], run_module=False) 
    60     >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    61     ...     for p in pth]) 
    62     'Modules:A/AA:B:B/BB:B/BB/pbbb' 
     59    >>> printpaths(pth, strip=tmpdir) 
     60    Modules 
     61    A/AA 
     62    B 
     63    B/BB 
     64    B/BB/pbbb 
    6365 
    6466This search mentions two module files explicitly, in addition to the root 
     
    6870    ...     join(tmpdir, 'Modules', 'module_a.py'), 
    6971    ...     join(tmpdir, 'Modules', 'module_b.py')], run_module=False) 
    70     >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    71     ...     for p in pth]) 
    72     'Modules:A/AA:B:B/BB:B/BB/pbbb' 
     72    >>> printpaths(pth, strip=tmpdir) 
     73    Modules 
     74    A/AA 
     75    B 
     76    B/BB 
     77    B/BB/pbbb 
    7378 
    7479The discovery algorithm currently forces paths discovered from module files 
     
    7984directory does not cause duplicates. 
    8085More elaborate schemes for addressing the shadowning problem are definitely 
    81 viable, especialy given the module loading facilities in the runpy standard 
     86viable, especially given the module loading facilities in the runpy standard 
    8287lib module. I suspect the "force to front" rule is essential for covering 
    8388*my* use case which is "just fix my path and run that script damit!" 
     89 
     90 
    8491Lets drop some eggs into the mix. We dont use real eggs for these examples 
    8592because the discovery of eggs does not look at egg contents - only file and 
    8693directory names. 
    8794 
    88     >>> _=file(join(tmpdir, 
    89     ...     'Modules', 'foo-0.1-py%s.egg' % sysver_cur), 'wb') 
    90     >>> _=file(join(tmpdir, 
    91     ...     'Modules', 'foo-0.2-py%s.egg' % sysver_cur), 'wb') 
    92     >>> _=file(join(tmpdir, 
    93     ...     'Modules', 'foo-0.3-py%s.egg' % sysver_notcompatible), 'wb') 
    94     >>> _=file(join(tmpdir, 
    95     ...     'Modules', 'foo-0.2-py%s.egg-link' % sysver_cur), 'wb') 
    96     >>> _=mkpath(join(tmpdir, 
    97     ...     'A', 'bar-0.1-py%s.egg' % sysver_cur)) 
    98     >>> _=mkpath(join(tmpdir, 
    99     ...     'B', 'bar-0.2-py%s.egg' % sysver_cur)) 
     95    >>> tmpdir, canonicalpaths = mktmpfiles(( 
     96    ...     'Modules/foo-0.1-py%s.egg' % sysver_cur, 
     97    ...     'Modules/foo-0.2-py%s.egg' % sysver_cur, 
     98    ...     'Modules/foo-0.2-py%s.egg-link' % sysver_cur, 
     99    ...     'Modules/zzz-0.2-py%s.egg-link' % sysver_cur, 
     100    ...     'Modules/foo-0.3-py%s.egg' % sysver_notcompatible, 
     101    ...     'A/bar-0.1-py%s.egg' % sysver_cur, 
     102    ...     'B/bar-0.2-py%s.egg' % sysver_cur), 
     103    ...     tmpdir=tmpdir 
     104    ...     ) 
    100105 
    101 The full search, 
     106 
     107A full search, 
    102108 
    103109    >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 
    104     >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    105     ...     for p in pth]) 
    106     'A/AA:B/bar-0.2-py2.5.egg:B:B/BB:B/BB/pbbb:Modules/foo-0.2-py2.5.egg' 
     110    >>> printpaths(pth, strip=tmpdir) 
     111    A/AA 
     112    B/bar-0.2-py2.5.egg 
     113    B 
     114    B/BB 
     115    B/BB/pbbb 
     116    Modules/foo-0.2-py2.5.egg 
    107117 
    108 The search that considers 'B' first 
     118A search that considers 'B' first 
    109119 
    110120    >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', 
    111121    ...     join(tmpdir, 'B'), tmpdir], run_module=False 
    112122    ...     ) 
    113     >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 
    114     ...     for p in pth]) 
    115     'B/bar-0.2-py2.5.egg:B:B/BB:B/BB/pbbb:A/AA:Modules/foo-0.2-py2.5.egg' 
     123    >>> printpaths(pth, strip=tmpdir) 
     124    B/bar-0.2-py2.5.egg 
     125    B 
     126    B/BB 
     127    B/BB/pbbb 
     128    A/AA 
     129    Modules/foo-0.2-py2.5.egg 
    116130 
    117131Note that irrespective which order we visit the A and B sub trees, we always 
     
    124138interpreter. But, for now, no special care is taken to deal with platform 
    125139specific eggs (linux-i686 vs whatver windows eggs use.) 
     140 
     141 
  • pyrun/trunk/pkg-info.rst

    r754 r759  
    55:Author-email: robinbryce@gmail.com 
    66:Requires-Python: 2.5 
    7 :Abstract: sys.path discovery and execution of python modules and packages.  
     7:Abstract: A convenient way to run python modules, packages and scripts with a dynamically discovered sys.path. Particularly useful when you want to make use of packages without installing them first, or to circumvent bootstrapping issues with complicated collections of python software. 
    88:Copyright: `Copyright (c) 2007 Robin Bryce, All rights reserved`_ 
    99:URL: http://trac.wiretooth.com/public/wiki/pyrun 
  • pyrun/trunk/pyrun.html

    • Property svn:mime-type set to text/html
    r754 r759  
    330330<div class="abstract topic"> 
    331331<p class="topic-title first">Abstract</p> 
    332 <p>sys.path discovery and execution of python modules and packages.</p> 
     332<p>A convenient way to run python modules, packages and scripts with a dynamically discovered sys.path. Particularly useful when you want to make use of packages without installing them first, or to circumvent bootstrapping issues with complicated collections of python software.</p> 
    333333</div> 
    334334<div class="contents topic"> 
     
    336336<ul class="simple"> 
    337337<li><a class="reference" href="#pyrun" id="id1" name="id1">pyrun</a></li> 
    338 <li><a class="reference" href="#installation" id="id2" name="id2">Installation</a></li> 
    339 <li><a class="reference" href="#changelog" id="id3" name="id3">ChangeLog</a></li> 
     338<li><a class="reference" href="#installation" id="id2" name="id2">Installation</a><ul> 
     339<li><a class="reference" href="#discover-and-run" id="id3" name="id3">discover_and_run</a></li> 
     340</ul> 
     341</li> 
     342<li><a class="reference" href="#changelog" id="id4" name="id4">ChangeLog</a></li> 
    340343</ul> 
    341344</div> 
     
    354357``python ~/pyrun.py  ~/my/python/libs ~/my/python/scripts/go.py`` 
    355358</pre> 
    356 <p>Is all you need in order to run the <cite>go.py' module with a sys.path automatically 
    357 discovered from directories under `~/my/python/libs</cite>. You can list an arbitrary 
    358 number of directories or paths to actual python files. The order you list them 
    359 controls the order in which the path extension entries are built. The resulting 
    360 path will not contain any duplicates. Each entry in the path extension will b
    361 a legitimate import path; Ie.,</p> 
     359<p>Is all you need in order to run the <cite>go.py</cite> module with a sys.path 
     360automatically discovered from directories under <cite>~/my/python/libs</cite>. You can 
     361list an arbitrary number of directories and paths to actual python files. The 
     362order you list them controls the order in which the path extension entries are 
     363built. The resulting path will not contain any duplicates. Each entry in th
     364path extension will be a legitimate import path; Ie.,</p> 
    362365<blockquote> 
    363366<ul class="simple"> 
     
    368371</ul> 
    369372</blockquote> 
    370 <p>If non of the non option arguments identify a python module file then pyrun 
    371 will simply print the path it has discovered and exit. If one or more 
    372 python module files are included in the arguments then pyrun will 'run' th
    373 last one listed. sys.path and sys.argv are adjusted so that your module is 
    374 the __main__ entry point upon execution and the discovered path is available 
    375 for resolving its imports.</p> 
    376 <p>If the module you are running does not naturaly accept a non option argument 
     373<p>If none of the non option arguments identify a python module file then pyrun 
     374will simply print the path it has discovered and exit. If one or more python 
     375module files are included in the arguments then pyrun will 'run' the first on
     376listed. <cite>sys.path</cite> and <cite>sys.argv</cite> are adjusted so that your module is the 
     377__main__ entry point upon execution and the discovered path is available for 
     378resolving its imports.</p> 
     379<p>If the module you are running does not naturally accept a non option argument 
    377380immediately after the module name then you can use <cite>--</cite> to explicitly delimit 
    378381the end of the arguments to pyrun. For example, the distribution 
     
    389392version. The measure of <cite>best egg</cite> uses the same algorithm as used by 
    390393the pkg_resources.py module distributed by the setuptools project.</p> 
    391 <p>But, NOTE that the current version does not filter out incompatible 
    392 <cite>platforms</cite> for eggs that contain c extensions - see <cite>pyrun.filter_best_eggs</cite> 
    393 if you have time on your hands, its not to much work to add this check.</p> 
     394<p>NOTE: The current version does not filter out incompatible <cite>platforms</cite> for eggs 
     395that contain c extensions - see <cite>pyrun.filter_best_eggs</cite> if you have time on 
     396your hands, its not to much work to add this check.</p> 
    394397<p>The issue tracker for this package can be found at: 
    395 <a class="reference" href="http://trac.wiretooth.com/open/">http://trac.wiretooth.com/open/</a>. When opening a ticket please assign it to 
    396 the 'pyrun' component or mention pyrun in the summary.</p> 
    397 <p>Provides facilities which are generally useful for implementing command line 
    398 interfaces and utilities.</p> 
     398<a class="reference" href="http://trac.wiretooth.com/open/">http://trac.wiretooth.com/open/</a>. When opening a ticket please assign it to the 
     399'pyrun' component or mention pyrun in the summary.</p> 
    399400</div> 
    400401<div class="section"> 
     
    403404convenience scripts. You can access the most commonly useful features of 
    404405pyrun, without installing the package, by running the pyrun.py file directly.</p> 
    405 </div> 
    406406<div class="section"> 
    407 <h1><a class="toc-backref" href="#id3" id="changelog" name="changelog">ChangeLog</a></h1> 
     407<h2><a class="toc-backref" href="#id3" id="discover-and-run" name="discover-and-run">discover_and_run</a></h2> 
     408<p>All of the command line programs provided by this package are essentially thin 
     409wrappers around the <cite>pyrun.discover_and_run</cite> function. This section provides 
     410<cite>doctest</cite> based discussion and examples. These examples are also part of the 
     411pyrun test suite.</p> 
     412<p>Lets setup a fake set of python packages and use it to illustrate some basics.</p> 
     413<blockquote> 
     414<pre class="doctest-block"> 
     415&gt;&gt;&gt; import os, sys 
     416&gt;&gt;&gt; from os.path import join 
     417&gt;&gt;&gt; import pyrun 
     418&gt;&gt;&gt; from _testutils import mktmpfiles, printpaths 
     419&gt;&gt;&gt; sysver_cur = sys.version[:3] 
     420&gt;&gt;&gt; sysver_notcompatible = '.'.join(map(str, 
     421...   [sys.version_info[0], sys.version_info[1] + 1])) 
     422&gt;&gt;&gt; tmpdir, canonicalpaths = mktmpfiles(( 
     423...     'A/AA/paaa/__init__.py', 
     424...     'A/AA/paaa/paaaa/', 
     425...     'B/BB/paaa/__init__.py', 
     426...     'B/BB/paaa/paaaa/', 
     427...     'B/BB/pbbb/pbbbb/__init__.py', 
     428...     'B/pc/__init__.py', 
     429...     'Modules/module_a.py', 
     430...     'Modules/module_b.py'), 
     431... 
     432...     prefix='pyrun-' 
     433...     ) 
     434</pre> 
     435</blockquote> 
     436<p>This search gives an os dependent ordering of all packages under A and B 
     437lexicaly ordered depth first is common. Note that Modules is ignored.</p> 
     438<blockquote> 
     439<pre class="doctest-block"> 
     440&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 
     441&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     442A/AA 
     443
     444B/BB 
     445B/BB/pbbb 
     446</pre> 
     447</blockquote> 
     448<p>This search forces paths under 'B' to be considered first, again note that 
     449Modules is ignored.</p> 
     450<blockquote> 
     451<pre class="doctest-block"> 
     452&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', 
     453...     join(tmpdir, 'B'), tmpdir], run_module=False 
     454...     ) 
     455&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     456
     457B/BB 
     458B/BB/pbbb 
     459A/AA 
     460</pre> 
     461</blockquote> 
     462<p>Modules is not present in either of the above resulting paths because python 
     463module files are ignored unless they were explicitly mentioned in the search.</p> 
     464<blockquote> 
     465<pre class="doctest-block"> 
     466&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 
     467...     join(tmpdir, 'Modules', 'module_a.py')], run_module=False) 
     468&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     469Modules 
     470A/AA 
     471
     472B/BB 
     473B/BB/pbbb 
     474</pre> 
     475</blockquote> 
     476<p>This search mentions two module files explicitly, in addition to the root 
     477of our fake tree.</p> 
     478<blockquote> 
     479<pre class="doctest-block"> 
     480&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 
     481...     join(tmpdir, 'Modules', 'module_a.py'), 
     482...     join(tmpdir, 'Modules', 'module_b.py')], run_module=False) 
     483&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     484Modules 
     485A/AA 
     486
     487B/BB 
     488B/BB/pbbb 
     489</pre> 
     490</blockquote> 
     491<p>The discovery algorithm currently forces paths discovered from module files 
     492ahead of those discovered for package files, however the paths for module 
     493files still follow the order in which the module files are listed in the 
     494search path.  Note that for module files which are contained in one directory 
     495you only need to include one in the search but including many from the same 
     496directory does not cause duplicates. 
     497More elaborate schemes for addressing the shadowning problem are definitely 
     498viable, especially given the module loading facilities in the runpy standard 
     499lib module. I suspect the &quot;force to front&quot; rule is essential for covering 
     500<em>my</em> use case which is &quot;just fix my path and run that script damit!&quot;</p> 
     501<p>Lets drop some eggs into the mix. We dont use real eggs for these examples 
     502because the discovery of eggs does not look at egg contents - only file and 
     503directory names.</p> 
     504<blockquote> 
     505<pre class="doctest-block"> 
     506&gt;&gt;&gt; tmpdir, canonicalpaths = mktmpfiles(( 
     507...     'Modules/foo-0.1-py%s.egg' % sysver_cur, 
     508...     'Modules/foo-0.2-py%s.egg' % sysver_cur, 
     509...     'Modules/foo-0.2-py%s.egg-link' % sysver_cur, 
     510...     'Modules/zzz-0.2-py%s.egg-link' % sysver_cur, 
     511...     'Modules/foo-0.3-py%s.egg' % sysver_notcompatible, 
     512...     'A/bar-0.1-py%s.egg' % sysver_cur, 
     513...     'B/bar-0.2-py%s.egg' % sysver_cur), 
     514...     tmpdir=tmpdir 
     515...     ) 
     516</pre> 
     517</blockquote> 
     518<p>A full search,</p> 
     519<blockquote> 
     520<pre class="doctest-block"> 
     521&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 
     522&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     523A/AA 
     524B/bar-0.2-py2.5.egg 
     525
     526B/BB 
     527B/BB/pbbb 
     528Modules/foo-0.2-py2.5.egg 
     529</pre> 
     530</blockquote> 
     531<p>A search that considers 'B' first</p> 
     532<blockquote> 
     533<pre class="doctest-block"> 
     534&gt;&gt;&gt; pth, minfos, ia = pyrun.discover_and_run(['pyrun', 
     535...     join(tmpdir, 'B'), tmpdir], run_module=False 
     536...     ) 
     537&gt;&gt;&gt; printpaths(pth, strip=tmpdir) 
     538B/bar-0.2-py2.5.egg 
     539
     540B/BB 
     541B/BB/pbbb 
     542A/AA 
     543Modules/foo-0.2-py2.5.egg 
     544</pre> 
     545</blockquote> 
     546<p>Note that irrespective which order we visit the A and B sub trees, we always 
     547list bar-0.2. The search discards duplicate egg names, retaining the first 
     548and - irispective of the visit order - <em>always</em> lists the best version of 
     549each egg.</p> 
     550<p>Finaly note that foo-0.3 is <em>not</em> listed. This is not a bug - the search 
     551ignores eggs whose major &amp; minor revisions dont match the current 
     552interpreter. But, for now, no special care is taken to deal with platform 
     553specific eggs (linux-i686 vs whatver windows eggs use.)</p> 
     554</div> 
     555</div> 
     556<div class="section"> 
     557<h1><a class="toc-backref" href="#id4" id="changelog" name="changelog">ChangeLog</a></h1> 
    408558<p>NEXTREVISION</p> 
    409559<blockquote> 
  • pyrun/trunk/pyrun.rst

    r756 r759  
    1010.. include:: INSTALL.txt 
    1111 
     12.. include:: examples/discover_and_run.rst 
     13 
    1214.. include:: ChangeLog 
    1315