Changeset 790

Show
Ignore:
Timestamp:
08/10/07 17:02:11 (1 year ago)
Author:
robin
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pyrun/trunk/ChangeLog

    r788 r790  
    22~~~~~~~~~ 
    33 
    4 0.1.1 
     40.1.1: 
     5  * bugfix: propagate source file name (or sensibly invented filename) to 
     6    the __file__ attribute of the code instance that becomes our __main__ 
     7  * -d works with -m and -c, should also work with -s but have not tried yet. 
     8  * -d option uses pdb.runeval rather than set_trace making for considerably 
     9    simpler target debugging. May consider introducing an "eager" -d variant 
     10    that behaves like 0.1 (set_trace *in* pyrun.py) later. 
     11  * Allow the target to run when -d is in effect, without requiring user to 
     12    manaully do ``opts.d = False`` 
     13  * By default suppress -D if -d is in effect. 
    514  * Added -c, its much like python -c 
    6   * The `run script` option changed from -S to -C 
    7   * By default, print a warning if any of the argv discovery path items dont 
    8     exist on the file system. -q suppreses the warnings 
     15  * The `run script` option changed from -S to -C exist on the file system. -q 
     16    suppreses the warnings 
    917 
    10 0.1d 
     180.1d: 
    1119  * `-S` option to explicitly run a python script. uses compiler.compile to 
    1220    load and compile the code from an arbitrary file. uses 
     
    2331  * documentation tidy up 
    2432 
    25 0.1c 
     330.1c: 
    2634  * Use the parent directory of the top package directory for each explicitly 
    2735    listed python file in the discovery path. This means you need to *always*  
     
    2937    to allow the targeted modules imports to work correctly. 
    3038 
    31 0.1b 
     390.1b: 
    3240 
    3341  * path discovery and  python module execution 
  • pyrun/trunk/pyrun.py

    r788 r790  
    444444 
    445445 
    446 def compile_and_run(source, mod_name='__main__', 
    447     init_globals=None, mod_fname=None, mod_loader=None, alter_sys=True): 
    448     """compile `filename` and run the code using runpy._run_module_code.""" 
    449  
     446def get_module_code_and_filename(mod_name): 
     447    """Get the code object and filename for the python module `mod_name` 
     448 
     449    This is exactly like runpy.run_module but instead of running the code, 
     450    it returns (code, filename) 
     451 
     452    """ 
    450453    global runpy 
    451454    if not have_runpy: 
    452455        runpy = __import__('runpy') 
    453456 
    454     if mod_fname is None: 
    455         mod_fname = filename 
    456     code = compiler.compile(source, mod_fname or '<unknown-source>', 'exec') 
    457     return runpy._run_module_code(code, 
    458             mod_name=mod_name, 
    459             init_globals=init_globals, 
    460             mod_fname=mod_fname, 
    461             mod_loader=mod_loader, 
    462             alter_sys=alter_sys 
    463             ) 
    464  
     457    loader = runpy.get_loader(mod_name) 
     458    if loader is None: 
     459        raise ImportError("No module named " + mod_name) 
     460    code = loader.get_code(mod_name) 
     461    if code is None: 
     462        raise ImportError("No code object available for " + mod_name) 
     463    filename = runpy._get_filename(loader, mod_name) 
     464    return code, filename 
     465 
     466 
     467def get_module_code(mod_name): 
     468    """Get the code object for the python module `mod_name`""" 
     469 
     470    return get_module_code_and_filename(mod_name)[0] 
     471 
     472 
     473def get_module_filename(mod_name): 
     474    """Get the filename for the python module `mod_name`""" 
     475 
     476    return get_module_code_and_filename(mod_name)[1] 
     477 
     478 
     479def dbg_run_code(code, run_globals, init_globals, 
     480        mod_name, mod_fname, mod_loader): 
     481    if init_globals is not None: 
     482        run_globals.update(init_globals) 
     483    run_globals.update(__name__ = mod_name, 
     484                       __file__ = mod_fname, 
     485                       __loader__ = mod_loader) 
     486    import pdb 
     487    pdb.runeval(code, run_globals) 
     488    return run_globals 
     489 
     490 
     491def run_module_code(runner, code, init_globals=None, 
     492                    mod_name=None, mod_fname=None, 
     493                    mod_loader=None, alter_sys=False): 
     494 
     495    """Variant of runpy._run_module_code with hook for _run_code 
     496 
     497    `runner` must be None or be a suitable replacement for runpy._run_code 
     498 
     499    (For example see dbg_run_code above) 
     500 
     501    """ 
     502 
     503    if runner is None: 
     504        assert have_runpy 
     505        runner = runpy._run_code 
     506 
     507    # Set up the top level namespace dictionary 
     508    if alter_sys: 
     509        # Modify sys.argv[0] and sys.module[mod_name] 
     510        temp_module = imp.new_module(mod_name) 
     511        mod_globals = temp_module.__dict__ 
     512        saved_argv0 = sys.argv[0] 
     513        restore_module = mod_name in sys.modules 
     514        if restore_module: 
     515            saved_module = sys.modules[mod_name] 
     516        sys.argv[0] = mod_fname 
     517        sys.modules[mod_name] = temp_module 
     518        try: 
     519            runner(code, mod_globals, init_globals, 
     520                      mod_name, mod_fname, mod_loader) 
     521        finally: 
     522            sys.argv[0] = saved_argv0 
     523        if restore_module: 
     524            sys.modules[mod_name] = saved_module 
     525        else: 
     526            del sys.modules[mod_name] 
     527        # Copy the globals of the temporary module, as they 
     528        # may be cleared when the temporary module goes away 
     529        return mod_globals.copy() 
     530    else: 
     531        # Leave the sys module alone 
     532        return runner(code, {}, init_globals, 
     533                         mod_name, mod_fname, mod_loader) 
     534 
     535 
     536def striplines(s): 
     537    return '\n'.join(map(''.__class__.strip, s.split('\n'))) 
     538 
     539interactive_BANNER_BOILERPLATE = """\ 
     540handy locals() are: 
     541    The function run() (runs the discovered module or -c/-C/-S options) 
     542    The variables target_argv, pthextend 
     543 
     544Update target_argv *in place* before calling run() if you want to tweak 
     545the sys.argv the module sees.""" 
    465546 
    466547def runex(argv=None): 
     
    485566        sourcefile = None 
    486567        if opts.c and opts.C and not opts.q: 
    487             print ( 
    488             'Warning: -c and -C can not be used together. Ignoring "-C %s"' 
    489             ) % opts.C 
     568            print striplines((''' 
     569            Warning: -c and -C can not be used together. Ignoring "-C %s" 
     570            ''' % opts.C) 
     571            ) 
    490572 
    491573        if opts.C: 
     
    501583 
    502584        if not opts.q and doesnotexist: 
    503             print (''' 
    504 Warning: your discovery path arguments referenced the following files or 
    505 directories which do not exist on the file system:''') 
     585            print striplines('''\ 
     586            Warning: your discovery path arguments referenced the following 
     587            files or directories which do not exist on the file system: 
     588            ''') 
    506589            print '\t' + '\n\t'.join(doesnotexist) 
    507590 
     
    595678            sys.argv[:] = target_argv[:] 
    596679            if runpy is not False: 
     680                runner = None 
     681                if opts.d: 
     682                    runner = dbg_run_code 
    597683                if not source: 
    598                     return runpy.run_module( 
    599                             modname, run_name='__main__', alter_sys=True 
    600                             ) 
     684                    code, filename = get_module_code_and_filename(modname) 
    601685                else: 
    602                     return compile_and_run(source, mod_fname=sourcefile) 
    603  
    604         if opts.d: 
    605             import pdb 
    606             pdb.set_trace() 
     686                    code = compiler.compile(source, sourcefile, 'exec') 
     687                    filename = sourcefile 
     688 
     689                return run_module_code(runner, code, 
     690                        init_globals=None, 
     691                        mod_name='__main__', 
     692                        mod_fname=filename, 
     693                        alter_sys=True 
     694                        ) 
    607695        if opts.i: 
    608696            banner='' 
     
    617705            if opts.p or opts.P: 
    618706                banner += '\n\n' 
    619             banner += """\ 
    620 handy locals() are: 
    621     The function run() (runs the discovered module or -c/-C/-S options) 
    622     The variables target_argv, pthextend 
    623  
    624 Update target_argv *in place* before calling run() if you want to tweak 
    625 the sys.argv the module sees.""" 
     707 
     708            bannerl += interactive_BANNER_BOILERPLATE 
    626709 
    627710            import code 
     
    639722            print os.pathsep.join(pthextend) 
    640723 
    641         if not (opts.n or opts.d or opts.i) and (modname or source): 
     724        if not (opts.n or opts.i) and (modname or source): 
    642725            exitval = run() 
    643726            if not isinstance(exitval, int): 
     
    652735        msg = exc_string(einfo=einfo) 
    653736        print msg 
    654         if opts.D
     737        if opts.D and not opts.d
    655738            import pdb 
    656739            pdb.post_mortem(einfo[2])