Changeset 759
- Timestamp:
- 07/21/07 00:49:41 (1 year ago)
- Files:
-
- pyrun/trunk/README.txt (modified) (3 diffs)
- pyrun/trunk/examples/_testutils.py (added)
- pyrun/trunk/examples/discover_and_run.html (modified) (8 diffs)
- pyrun/trunk/examples/discover_and_run.rst (modified) (8 diffs)
- pyrun/trunk/pkg-info.rst (modified) (1 diff)
- pyrun/trunk/pyrun.html (modified) (6 diffs, 1 prop)
- pyrun/trunk/pyrun.rst (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
pyrun/trunk/README.txt
r754 r759 16 16 ``python ~/pyrun.py ~/my/python/libs ~/my/python/scripts/go.py`` 17 17 18 Is all you need in order to run the `go.py ' module with a sys.path automatically19 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 be23 a legitimate import path; Ie.,18 Is all you need in order to run the `go.py` module with a sys.path 19 automatically discovered from directories under `~/my/python/libs`. You can 20 list an arbitrary number of directories and paths to actual python files. The 21 order you list them controls the order in which the path extension entries are 22 built. The resulting path will not contain any duplicates. Each entry in the 23 path extension will be a legitimate import path; Ie., 24 24 25 25 * It is a directory on the file system with one or more child directories … … 28 28 * OR It is an egg path 29 29 30 If non of the non option arguments identify a python module file then pyrun31 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' the33 l ast one listed. sys.path and sys.argv are adjusted so that your module is34 the __main__ entry point upon execution and the discovered path is available 35 forresolving its imports.30 If none 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 python 32 module files are included in the arguments then pyrun will 'run' the first one 33 listed. `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 35 resolving its imports. 36 36 37 If the module you are running does not natural y accept a non option argument37 If the module you are running does not naturally accept a non option argument 38 38 immediately after the module name then you can use `--` to explicitly delimit 39 39 the end of the arguments to pyrun. For example, the distribution … … 49 49 For egg paths only the *best* version of each egg is allowed onto the extended 50 50 path, 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 51 version. The measure of `best egg` uses the same algorithm as used by 52 52 the pkg_resources.py module distributed by the setuptools project. 53 53 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 onyour hands, its not to much work to add this check.54 NOTE: The current version does not filter out incompatible `platforms` for eggs 55 that contain c extensions - see `pyrun.filter_best_eggs` if you have time on 56 your hands, its not to much work to add this check. 57 57 58 58 59 59 The 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 60 http://trac.wiretooth.com/open/. When opening a ticket please assign it to the 61 'pyrun' component or mention pyrun in the summary. 63 62 64 Provides facilities which are generally useful for implementing command line65 interfaces and utilities.pyrun/trunk/examples/discover_and_run.html
r758 r759 290 290 <h1 class="title">discover_and_run</h1> 291 291 292 <p>All of the command line programs provided by this package are essentially thin 293 wrappers 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 295 pyrun test suite.</p> 292 296 <p>Lets setup a fake set of python packages and use it to illustrate some basics.</p> 293 297 <blockquote> … … 295 299 >>> import os, sys 296 300 >>> from os.path import join 297 >>> from tempfile import mkdtemp298 >>> from distutils.dir_util import mkpath299 301 >>> import pyrun 300 >>> tmpdir = mkdtemp(prefix='pyrun-tmp')302 >>> from _testutils import mktmpfiles, printpaths 301 303 >>> sysver_cur = sys.version[:3] 302 304 >>> sysver_notcompatible = '.'.join(map(str, 303 305 ... [sys.version_info[0], sys.version_info[1] + 1])) 304 >>> _=mkpath(join(tmpdir, 305 ... 'A', 'AA', 'paaa', 'paaaa')) 306 >>> _=file(join(tmpdir, 307 ... 'A', 'AA', 'paaa', '__init__.py'), mode='wb') 308 >>> _=mkpath(join(tmpdir, 309 ... 'B', 'BB', 'paaa', 'paaaa')) 310 >>> _=file(join(tmpdir, 311 ... 'B', 'BB', 'paaa', '__init__.py'), mode='wb') 312 >>> _=mkpath(join(tmpdir, 313 ... 'B', 'BB', 'pbbb', 'pbbbb')) 314 >>> _=file(join(tmpdir, 315 ... 'B', 'BB', 'pbbb', 'pbbbb', '__init__.py'), mode='wb') 316 >>> _=mkpath(join(tmpdir, 317 ... 'B', 'pc')) 318 >>> _=file(join(tmpdir, 319 ... 'B', 'pc', '__init__.py'), mode='wb') 320 >>> _=mkpath(join(tmpdir, 321 ... 'Modules',)) 322 >>> _=file(join(tmpdir, 323 ... 'Modules', 'module_a.py'), 'wb') 324 >>> _=file(join(tmpdir, 325 ... 'Modules', 'module_b.py'), 'wb') 306 >>> 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 ... ) 326 318 </pre> 327 319 </blockquote> … … 331 323 <pre class="doctest-block"> 332 324 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 333 >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) for p in pth]) 334 'A/AA:B:B/BB:B/BB/pbbb' 325 >>> printpaths(pth, strip=tmpdir) 326 A/AA 327 B 328 B/BB 329 B/BB/pbbb 335 330 </pre> 336 331 </blockquote> … … 342 337 ... join(tmpdir, 'B'), tmpdir], run_module=False 343 338 ... ) 344 >>> ':'.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 >>> printpaths(pth, strip=tmpdir) 340 B 341 B/BB 342 B/BB/pbbb 343 A/AA 347 344 </pre> 348 345 </blockquote> … … 353 350 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 354 351 ... join(tmpdir, 'Modules', 'module_a.py')], run_module=False) 355 >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 356 ... for p in pth]) 357 'Modules:A/AA:B:B/BB:B/BB/pbbb' 352 >>> printpaths(pth, strip=tmpdir) 353 Modules 354 A/AA 355 B 356 B/BB 357 B/BB/pbbb 358 358 </pre> 359 359 </blockquote> … … 365 365 ... join(tmpdir, 'Modules', 'module_a.py'), 366 366 ... join(tmpdir, 'Modules', 'module_b.py')], run_module=False) 367 >>> ':'.join([p.replace(tmpdir + os.path.sep, '', 1) 368 ... for p in pth]) 369 'Modules:A/AA:B:B/BB:B/BB/pbbb' 367 >>> printpaths(pth, strip=tmpdir) 368 Modules 369 A/AA 370 B 371 B/BB 372 B/BB/pbbb 370 373 </pre> 371 374 </blockquote> … … 379 382 viable, especialy given the module loading facilities in the runpy standard 380 383 lib module. I suspect the "force to front" rule is essential for covering 381 <em>my</em> use case which is "just fix my path and run that script damit!" 382 Lets drop some eggs into the mix. We dont use real eggs for these examples384 <em>my</em> use case which is "just fix my path and run that script damit!"</p> 385 <p>Lets drop some eggs into the mix. We dont use real eggs for these examples 383 386 because the discovery of eggs does not look at egg contents - only file and 384 387 directory names.</p> 385 388 <blockquote> 386 389 <pre class="doctest-block"> 387 >>> _=file(join(tmpdir, 388 ... 'Modules', 'foo-0.1-py%s.egg' % sysver_cur), 'wb') 389 >>> _=file(join(tmpdir, 390 ... 'Modules', 'foo-0.2-py%s.egg' % sysver_cur), 'wb') 391 >>> _=file(join(tmpdir, 392 ... 'Modules', 'foo-0.3-py%s.egg' % sysver_notcompatible), 'wb') 393 >>> _=file(join(tmpdir, 394 ... 'Modules', 'foo-0.2-py%s.egg-link' % sysver_cur), 'wb') 395 >>> _=mkpath(join(tmpdir, 396 ... 'A', 'bar-0.1-py%s.egg' % sysver_cur)) 397 >>> _=mkpath(join(tmpdir, 398 ... 'B', 'bar-0.2-py%s.egg' % sysver_cur)) 399 </pre> 400 </blockquote> 401 <p>The full search,</p> 390 >>> 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> 402 403 <blockquote> 403 404 <pre class="doctest-block"> 404 405 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 405 >>> ':'.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 >>> printpaths(pth, strip=tmpdir) 407 A/AA 408 B/bar-0.2-py2.5.egg 409 B 410 B/BB 411 B/BB/pbbb 412 Modules/foo-0.2-py2.5.egg 413 </pre> 414 </blockquote> 415 <p>A search that considers 'B' first</p> 411 416 <blockquote> 412 417 <pre class="doctest-block"> … … 414 419 ... join(tmpdir, 'B'), tmpdir], run_module=False 415 420 ... ) 416 >>> ':'.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 >>> printpaths(pth, strip=tmpdir) 422 B/bar-0.2-py2.5.egg 423 B 424 B/BB 425 B/BB/pbbb 426 A/AA 427 Modules/foo-0.2-py2.5.egg 419 428 </pre> 420 429 </blockquote> pyrun/trunk/examples/discover_and_run.rst
r757 r759 1 1 discover_and_run 2 2 ................ 3 4 All of the command line programs provided by this package are essentially thin 5 wrappers around the `pyrun.discover_and_run` function. This section provides 6 `doctest` based discussion and examples. These examples are also part of the 7 pyrun test suite. 3 8 4 9 Lets setup a fake set of python packages and use it to illustrate some basics. … … 6 11 >>> import os, sys 7 12 >>> from os.path import join 8 >>> from tempfile import mkdtemp9 >>> from distutils.dir_util import mkpath10 13 >>> import pyrun 11 >>> tmpdir = mkdtemp(prefix='pyrun-tmp')14 >>> from _testutils import mktmpfiles, printpaths 12 15 >>> sysver_cur = sys.version[:3] 13 16 >>> sysver_notcompatible = '.'.join(map(str, 14 17 ... [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 37 31 38 32 This search gives an os dependent ordering of all packages under A and B … … 40 34 41 35 >>> 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 44 41 45 42 This search forces paths under 'B' to be considered first, again note that … … 49 46 ... join(tmpdir, 'B'), tmpdir], run_module=False 50 47 ... ) 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 54 53 55 54 Modules is not present in either of the above resulting paths because python … … 58 57 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 59 58 ... 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 63 65 64 66 This search mentions two module files explicitly, in addition to the root … … 68 70 ... join(tmpdir, 'Modules', 'module_a.py'), 69 71 ... 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 73 78 74 79 The discovery algorithm currently forces paths discovered from module files … … 79 84 directory does not cause duplicates. 80 85 More elaborate schemes for addressing the shadowning problem are definitely 81 viable, especial y given the module loading facilities in the runpy standard86 viable, especially given the module loading facilities in the runpy standard 82 87 lib module. I suspect the "force to front" rule is essential for covering 83 88 *my* use case which is "just fix my path and run that script damit!" 89 90 84 91 Lets drop some eggs into the mix. We dont use real eggs for these examples 85 92 because the discovery of eggs does not look at egg contents - only file and 86 93 directory names. 87 94 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 ... ) 100 105 101 The full search, 106 107 A full search, 102 108 103 109 >>> 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 107 117 108 Thesearch that considers 'B' first118 A search that considers 'B' first 109 119 110 120 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', 111 121 ... join(tmpdir, 'B'), tmpdir], run_module=False 112 122 ... ) 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 116 130 117 131 Note that irrespective which order we visit the A and B sub trees, we always … … 124 138 interpreter. But, for now, no special care is taken to deal with platform 125 139 specific eggs (linux-i686 vs whatver windows eggs use.) 140 141 pyrun/trunk/pkg-info.rst
r754 r759 5 5 :Author-email: robinbryce@gmail.com 6 6 :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. 8 8 :Copyright: `Copyright (c) 2007 Robin Bryce, All rights reserved`_ 9 9 :URL: http://trac.wiretooth.com/public/wiki/pyrun pyrun/trunk/pyrun.html
- Property svn:mime-type set to text/html
r754 r759 330 330 <div class="abstract topic"> 331 331 <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> 333 333 </div> 334 334 <div class="contents topic"> … … 336 336 <ul class="simple"> 337 337 <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> 340 343 </ul> 341 344 </div> … … 354 357 ``python ~/pyrun.py ~/my/python/libs ~/my/python/scripts/go.py`` 355 358 </pre> 356 <p>Is all you need in order to run the <cite>go.py ' module with a sys.path automatically357 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 be361 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 360 automatically discovered from directories under <cite>~/my/python/libs</cite>. You can 361 list an arbitrary number of directories and paths to actual python files. The 362 order you list them controls the order in which the path extension entries are 363 built. The resulting path will not contain any duplicates. Each entry in the 364 path extension will be a legitimate import path; Ie.,</p> 362 365 <blockquote> 363 366 <ul class="simple"> … … 368 371 </ul> 369 372 </blockquote> 370 <p>If non of the non option arguments identify a python module file then pyrun371 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' the373 l ast one listed. sys.path and sys.argv are adjusted so that your module is374 the __main__ entry point upon execution and the discovered path is available 375 forresolving its imports.</p>376 <p>If the module you are running does not natural y accept a non option argument373 <p>If none of the non option arguments identify a python module file then pyrun 374 will simply print the path it has discovered and exit. If one or more python 375 module files are included in the arguments then pyrun will 'run' the first one 376 listed. <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 378 resolving its imports.</p> 379 <p>If the module you are running does not naturally accept a non option argument 377 380 immediately after the module name then you can use <cite>--</cite> to explicitly delimit 378 381 the end of the arguments to pyrun. For example, the distribution … … 389 392 version. The measure of <cite>best egg</cite> uses the same algorithm as used by 390 393 the pkg_resources.py module distributed by the setuptools project.</p> 391 <p> But, NOTE that the current version does not filter out incompatible392 <cite>platforms</cite> for eggs that contain c extensions - see <cite>pyrun.filter_best_eggs</cite> 393 if you have time onyour 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 395 that contain c extensions - see <cite>pyrun.filter_best_eggs</cite> if you have time on 396 your hands, its not to much work to add this check.</p> 394 397 <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> 399 400 </div> 400 401 <div class="section"> … … 403 404 convenience scripts. You can access the most commonly useful features of 404 405 pyrun, without installing the package, by running the pyrun.py file directly.</p> 405 </div>406 406 <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 409 wrappers 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 411 pyrun 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 >>> import os, sys 416 >>> from os.path import join 417 >>> import pyrun 418 >>> from _testutils import mktmpfiles, printpaths 419 >>> sysver_cur = sys.version[:3] 420 >>> sysver_notcompatible = '.'.join(map(str, 421 ... [sys.version_info[0], sys.version_info[1] + 1])) 422 >>> 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 437 lexicaly ordered depth first is common. Note that Modules is ignored.</p> 438 <blockquote> 439 <pre class="doctest-block"> 440 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 441 >>> printpaths(pth, strip=tmpdir) 442 A/AA 443 B 444 B/BB 445 B/BB/pbbb 446 </pre> 447 </blockquote> 448 <p>This search forces paths under 'B' to be considered first, again note that 449 Modules is ignored.</p> 450 <blockquote> 451 <pre class="doctest-block"> 452 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', 453 ... join(tmpdir, 'B'), tmpdir], run_module=False 454 ... ) 455 >>> printpaths(pth, strip=tmpdir) 456 B 457 B/BB 458 B/BB/pbbb 459 A/AA 460 </pre> 461 </blockquote> 462 <p>Modules is not present in either of the above resulting paths because python 463 module files are ignored unless they were explicitly mentioned in the search.</p> 464 <blockquote> 465 <pre class="doctest-block"> 466 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir, 467 ... join(tmpdir, 'Modules', 'module_a.py')], run_module=False) 468 >>> printpaths(pth, strip=tmpdir) 469 Modules 470 A/AA 471 B 472 B/BB 473 B/BB/pbbb 474 </pre> 475 </blockquote> 476 <p>This search mentions two module files explicitly, in addition to the root 477 of our fake tree.</p> 478 <blockquote> 479 <pre class="doctest-block"> 480 >>> 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 >>> printpaths(pth, strip=tmpdir) 484 Modules 485 A/AA 486 B 487 B/BB 488 B/BB/pbbb 489 </pre> 490 </blockquote> 491 <p>The discovery algorithm currently forces paths discovered from module files 492 ahead of those discovered for package files, however the paths for module 493 files still follow the order in which the module files are listed in the 494 search path. Note that for module files which are contained in one directory 495 you only need to include one in the search but including many from the same 496 directory does not cause duplicates. 497 More elaborate schemes for addressing the shadowning problem are definitely 498 viable, especially given the module loading facilities in the runpy standard 499 lib module. I suspect the "force to front" rule is essential for covering 500 <em>my</em> use case which is "just fix my path and run that script damit!"</p> 501 <p>Lets drop some eggs into the mix. We dont use real eggs for these examples 502 because the discovery of eggs does not look at egg contents - only file and 503 directory names.</p> 504 <blockquote> 505 <pre class="doctest-block"> 506 >>> 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 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', tmpdir], run_module=False) 522 >>> printpaths(pth, strip=tmpdir) 523 A/AA 524 B/bar-0.2-py2.5.egg 525 B 526 B/BB 527 B/BB/pbbb 528 Modules/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 >>> pth, minfos, ia = pyrun.discover_and_run(['pyrun', 535 ... join(tmpdir, 'B'), tmpdir], run_module=False 536 ... ) 537 >>> printpaths(pth, strip=tmpdir) 538 B/bar-0.2-py2.5.egg 539 B 540 B/BB 541 B/BB/pbbb 542 A/AA 543 Modules/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 547 list bar-0.2. The search discards duplicate egg names, retaining the first 548 and - irispective of the visit order - <em>always</em> lists the best version of 549 each egg.</p> 550 <p>Finaly note that foo-0.3 is <em>not</em> listed. This is not a bug - the search 551 ignores eggs whose major & minor revisions dont match the current 552 interpreter. But, for now, no special care is taken to deal with platform 553 specific 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> 408 558 <p>NEXTREVISION</p> 409 559 <blockquote> pyrun/trunk/pyrun.rst
r756 r759 10 10 .. include:: INSTALL.txt 11 11 12 .. include:: examples/discover_and_run.rst 13 12 14 .. include:: ChangeLog 13 15