Changeset 783
- Timestamp:
- 08/01/07 23:30:20 (1 year ago)
- Files:
-
- pyrun/trunk/ChangeLog (modified) (1 diff)
- pyrun/trunk/command_line_interface.rst (modified) (1 diff)
- pyrun/trunk/examples/examples-as-tests.txt (modified) (1 diff)
- pyrun/trunk/pkg-info.rst (modified) (1 diff)
- pyrun/trunk/pyrun.html (modified) (3 diffs)
- pyrun/trunk/pyrun.py (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
pyrun/trunk/ChangeLog
r781 r783 3 3 4 4 0.1d 5 * `-S` option to explicitly run a python script. uses compiler.compile to 6 load and compile the code from an arbitrary file. uses 7 runpy._run_module_code to execute the resulting module as __main__. 8 NOTE No discovery or sys.path manipulation is performed on the file 9 specified with this option. works for plain old python scripts and 10 executable scripts that lack an extension. 11 . 12 The chief motivation for this is to support python projects that 13 distribute substantive scripts rather than using the setuptools 14 entry_points 'wrapper' script approach. (For example see the 15 0.2.1 source tarbal for pyflakes). 16 5 17 * documentation tidy up 6 18 pyrun/trunk/command_line_interface.rst
r781 r783 18 18 -n NORUN. Don't run any of the modules implied by module file 19 19 references in the discovery path. 20 -m MODULE Explicitly select a module to run. 20 -S SCRIPT Identify a *python* SCRIPT to execute. The script need not 21 have file extension but it must contain leagal python code. 22 This option trumps -m. This option should only be necessary 23 when the launcher for the python program you wish to run 24 contains significant functionality. No additions are made to 25 the discovery path or sys.path as a result of using this 26 option. If the target script imports a related package you 27 will need to include additional non option arguments to 28 discover its path. 29 -m MODULE Explicitly select a module to run. (trumped by -S) 21 30 -d DEBUG session. Prepare for execution, but start a pdb session 22 31 using `pdb.set_trace`. pyrun/trunk/examples/examples-as-tests.txt
r767 r783 4 4 cd pyrun-checkoutdir && python pyrun.py -m nose.core nose/and/setuptools/under/here -v --with-doctest --doctest-extension=.rst -w examples 5 5 6 # or 7 cd pyrun-trunk 8 python pyrun.py -S `which nosetests` lib/ -v --with-doctest --doctest-extension=.rst -w examples/ 9 10 6 11 The equivelent, without using pyrun, would be something like:: 7 12 pyrun/trunk/pkg-info.rst
r782 r783 1 1 :License: MIT 2 2 :Name: pyrun 3 :Version: 0.1d .dev3 :Version: 0.1d 4 4 :Author: Robin Bryce 5 5 :Author-email: robinbryce@gmail.com pyrun/trunk/pyrun.html
r782 r783 300 300 </tr> 301 301 <tr><th class="docinfo-name">Version:</th> 302 <td>0.1d .dev</td></tr>302 <td>0.1d</td></tr> 303 303 <tr><th class="docinfo-name">Author:</th> 304 304 <td>Robin Bryce</td></tr> … … 465 465 references in the discovery path.</td></tr> 466 466 <tr><td class="option-group"> 467 <kbd><span class="option">-S <var>SCRIPT</var></span></kbd></td> 468 <td>Identify a <em>python</em> SCRIPT to execute. The script need not 469 have file extension but it must contain leagal python code. 470 This option trumps -m. This option should only be necessary 471 when the launcher for the python program you wish to run 472 contains significant functionality. No additions are made to 473 the discovery path or sys.path as a result of using this 474 option. If the target script imports a related package you 475 will need to include additional non option arguments to 476 discover its path.</td></tr> 477 <tr><td class="option-group"> 467 478 <kbd><span class="option">-m <var>MODULE</var></span></kbd></td> 468 <td>Explicitly select a module to run. </td></tr>479 <td>Explicitly select a module to run. (trumped by -S)</td></tr> 469 480 <tr><td class="option-group"> 470 481 <kbd><span class="option">-d</span></kbd></td> … … 645 656 <dt>0.1d</dt> 646 657 <dd><ul class="first last simple"> 658 <li><cite>-S</cite> option to explicitly run a python script. uses compiler.compile to 659 load and compile the code from an arbitrary file. uses 660 runpy._run_module_code to execute the resulting module as __main__. 661 NOTE No discovery or sys.path manipulation is performed on the file 662 specified with this option. works for plain old python scripts and 663 executable scripts that lack an extension. 664 . 665 The chief motivation for this is to support python projects that 666 distribute substantive scripts rather than using the setuptools 667 entry_points 'wrapper' script approach. (For example see the 668 0.2.1 source tarbal for pyflakes).</li> 647 669 <li>documentation tidy up</li> 648 670 </ul> pyrun/trunk/pyrun.py
r781 r783 1 #!/usr/bin/env python 1 2 # Copyright (c) 2007 Robin Bryce 2 # All rights reserved 3 # 4 # Permission is hereby granted, free of charge, to any person obtaining a 5 # copy of this software and associated documentation files (the "Software"), 6 # to deal in the Software without restriction, including without limitation 7 # the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 # and/or sell copies of the Software, and to permit persons to whom the 9 # Software is furnished to do so, subject to the following conditions: 10 # 11 # The above copyright notice and this permission notice shall be included in 12 # all copies or substantial portions of the Software. 13 # 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 # DEALINGS IN THE SOFTWARE. 21 22 import os, sys, types, re, traceback, inspect, imp 23 24 from os.path import abspath, normpath, join, expanduser, expandvars, dirname 25 from os.path import basename, isabs, exists, isfile, isdir 3 # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 4 5 import os, sys, types, re, traceback, inspect, imp, compiler 6 7 from os.path import join, dirname, basename, isfile, isdir 8 9 have_runpy=False 10 try: 11 import runpy 12 have_runpy=True 13 except ImportError: 14 pass 15 26 16 27 17 def exc_string(einfo=None): … … 125 115 return (p, '.'.join(packages), ext, mode, mtype) 126 116 127 128 def run_pkg_minfo():129 print path_pkg_moduleinfo(sys.argv[1])130 return 0131 117 132 118 # from distutils.util, because fools at debian think its a good idea to remove … … 368 354 minfos.append(minfo) 369 355 a = minfo[0] 356 357 # Currently ~/xxx/foo.py will put ~/xxx in the path irespective 358 # of whether there is a ~/xxx/__init__.py. I am very tempted 359 # to reject directories which are not discovered from genuine 360 # packages and just rely on cwd for the setup.py use case. 361 # 362 # The reason I'm tempted is that I'm not sure I like the fact that 363 # , with the current implementation, python files collected 364 # together in a 'scripts' directory will be able to do sibling 365 # imports ( and hence shadow things for each other) becuase their 366 # common parent directory gets put on the path here. 370 367 if a not in pthset: 371 368 pthextend.append(a) … … 416 413 """ 417 414 418 if run_module:419 import runpy420 421 415 argv = argv or sys.argv[:] 422 416 423 417 pthextend, minfos, ia = discover_path(1, *argv) 424 418 425 if run_module: 426 427 if not isinstance(run_module, types.StringTypes): 428 run_module = minfos[0][1] 429 430 if modify_sys: 431 # We are running the module, eat the artificial `--` delimiter 432 # if it artificially terminated the argv 433 if ia < len(argv) and argv[ia] == '--': 434 del argv[ia] 435 sys.path[0:0] = pthextend[:] 436 sys.argv[:] = [] 437 sys.argv.append(run_module) 438 sys.argv.extend(argv[ia:]) 439 419 # We are running the module, eat the artificial `--` delimiter 420 # if it artificially terminated the argv 421 if ia < len(argv) and argv[ia] == '--': 422 del argv[ia] 423 424 if run_module and not isinstance(run_module, types.StringTypes): 425 run_module = minfos[0][1] 426 427 428 if modify_sys: 429 sys.path[0:0] = pthextend[:] 430 sys.argv[:] = [] 431 sys.argv.append(run_module) 432 sys.argv.extend(argv[ia:]) 433 434 if run_module and have_runpy is not False: 440 435 return runpy.run_module( 441 436 run_module, run_name='__main__', alter_sys=True … … 443 438 444 439 return pthextend, minfos, ia 440 441 442 def compile_and_run(filename, mod_name='__main__', 443 init_globals=None, mod_fname=None, mod_loader=None, alter_sys=True): 444 """compile `filename` and run the code using runpy._run_module_code.""" 445 global runpy 446 if not have_runpy: 447 runpy = __import__('runpy') 448 449 if mod_fname is None: 450 mod_fname = filename 451 code = compiler.compile(file(filename).read(), filename, 'exec') 452 return runpy._run_module_code(code, 453 mod_name=mod_name, 454 init_globals=init_globals, 455 mod_fname=mod_fname, 456 mod_loader=mod_loader, 457 alter_sys=alter_sys 458 ) 445 459 446 460 … … 517 531 # else: its definitely *not* a pyrun option 518 532 519 modname = opts.m or (minfos and minfos[0][1]) or ''533 modname = not opts.S and (opts.m or (minfos and minfos[0][1]) or '') 520 534 521 535 # Allways update the sys path. pthextend is the record of what we have … … 528 542 529 543 target_argv = [] 530 if modname :531 target_argv.append(modname )544 if modname or opts.S: 545 target_argv.append(modname or opts.S) 532 546 target_argv.extend(argv[ia:]) 533 547 … … 539 553 print 'argv is empty' 540 554 return 0 541 import runpy542 555 sys.argv[:] = target_argv[:] 543 return runpy.run_module( 544 modname, run_name='__main__', alter_sys=True 545 ) 556 if runpy is not False: 557 if not opts.S: 558 return runpy.run_module( 559 modname, run_name='__main__', alter_sys=True 560 ) 561 else: 562 return compile_and_run(opts.S) 563 546 564 if opts.d: 547 565 import pdb … … 581 599 print os.pathsep.join(pthextend) 582 600 583 if not (opts.n or opts.d or opts.i) and modname:601 if not (opts.n or opts.d or opts.i) and (modname or opts.S): 584 602 exitval = run_module() 585 603 if not isinstance(exitval, int): … … 627 645 return rval 628 646 629 OPTIONS_runex=[630 631 ('-p', dict(default=False, action='store_true', metavar='PRINTPATH', help=632 "Print the discovered path")),633 634 ('-P', dict(default=False, action='store_true', metavar='PRINTPATH', help=635 "Print the discovered path in a PYTHONPATH compatible format")),636 637 638 ('-n', dict(default=False, action='store_true', metavar='NORUN', help=639 '''NORUN. Don't run any of the modules implied by module file references in640 the discovery path.''')),641 642 ('-m', dict(default='', metavar='MODULE', help=643 "Explicitly select a module to run.")),644 645 ('-d', dict(default=False, action='store_true', metavar='DEBUG', help=646 """DEBUG session. Prepare for execution, but start a pdb session using647 `pdb.set_trace`.""")),648 649 ('-D', dict(default=False, action='store_true', metavar='DEBUG', help=650 """POSTMORTEM debugging. If the target raises an exception, start a651 postmortem pdb debugging session.""")),652 653 ('-i', dict(default=False, action='store_true', metavar='INTERACTIVE', help=654 "INTERACTIVE session with prepared sys.argv and sys.path.")),655 656 ('-c', dict(default=False, metavar='STATEMENT', help=657 """Update sys.argv and sys.path then execute statement in a new658 python module. [NYI]""")),659 660 ('-C', dict(default=False, metavar='STATEMENT', help=661 """Update sys.argv and sys.path then execute statement in the context of the662 selected module. [NYI]"""))663 664 ]665 666 flagOPTIONS_runex=tuple([o[1:] for o, kw in OPTIONS_runex667 if kw.get('action', None) in ('store_true', 'store_false')]668 )669 670 647 USAGE_runex="""\ 671 648 %prog [-nidDpP] [BASEPATH(s)][-m mod.name | '--'] [TARGET-OPTIONS] … … 682 659 NOTE: Any option that is marked [NYI] is Not Yet Implemented.""" 683 660 661 OPTIONS_runex=[ 662 663 ('-p', dict(default=False, action='store_true', metavar='PRINTPATH', help= 664 "Print the discovered path")), 665 666 ('-P', dict(default=False, action='store_true', metavar='PRINTPATH', help= 667 "Print the discovered path in a PYTHONPATH compatible format")), 668 669 670 ('-n', dict(default=False, action='store_true', metavar='NORUN', help= 671 """NORUN. Don't run any of the modules implied by module file references in 672 the discovery path.""")), 673 674 ('-S', dict(default=None, type='string', metavar='SCRIPT', help= 675 """Identify a *python* SCRIPT to execute. The script need not have file 676 extension but it must contain leagal python code. This option trumps -m. This 677 option should only be necessary when the launcher for the python program you 678 wish to run contains significant functionality. No additions are made to the 679 discovery path or sys.path as a result of using this option. If the target 680 script imports a related package you will need to include additional non option 681 arguments to discover its path.""")), 682 683 ('-m', dict(default='', metavar='MODULE', help= 684 "Explicitly select a module to run. (trumped by -S)")), 685 686 ('-d', dict(default=False, action='store_true', metavar='DEBUG', help= 687 """DEBUG session. Prepare for execution, but start a pdb session using 688 `pdb.set_trace`.""")), 689 690 ('-D', dict(default=False, action='store_true', metavar='DEBUG', help= 691 """POSTMORTEM debugging. If the target raises an exception, start a 692 postmortem pdb debugging session.""")), 693 694 ('-i', dict(default=False, action='store_true', metavar='INTERACTIVE', help= 695 "INTERACTIVE session with prepared sys.argv and sys.path.")), 696 697 ('-c', dict(default=False, metavar='STATEMENT', help= 698 """Update sys.argv and sys.path then execute statement in a new 699 python module. [NYI]""")), 700 701 ('-C', dict(default=False, metavar='STATEMENT', help= 702 """Update sys.argv and sys.path then execute statement in the context of the 703 selected module. [NYI]""")) 704 705 ] 706 707 flagOPTIONS_runex=tuple([o[1:] for o, kw in OPTIONS_runex 708 if kw.get('action', None) in ('store_true', 'store_false')] 709 ) 710 711 684 712 if __name__=='__main__': 685 #sys.exit(run_top_minfo())686 713 sys.exit(runex()) 687 714