4949import sys
5050import re
5151import code
52+ import types
5253import optparse
5354import subprocess
5455import contextlib
@@ -71,7 +72,7 @@ def get_filename(self, fullpath):
7172
7273 def get_code (self , fullpath ):
7374 if fullpath == self .source :
74- return compile (self .source , '<command>' , 'single ' )
75+ return compile (self .source , '<command>' , 'exec ' )
7576
7677 def get_source (self , fullpath ):
7778 if fullpath == self .source :
@@ -307,7 +308,7 @@ def execfile(self, filepath):
307308 src .close ()
308309 if co is not None :
309310 try :
310- exec (co , globals () , self .locals )
311+ exec (co , self . globals , self .locals )
311312 except :
312313 e , v , tb = sys .exc_info ()
313314 print_exception (e , v , tb .tb_next or tb )
@@ -390,16 +391,13 @@ def postmortem(funcpath):
390391
391392class Execution (object ):
392393 """
393- Given argv, context, locals, environ, make an execution instance that,
394- when called, will execute the Python configured code.
394+ Given argv and context make an execution instance that, when called, will
395+ execute the configured Python code.
395396
396397 This class provides the ability to identify what the main part of the
397398 execution of the configured Python code. For instance, shall it execute a
398399 console, the file that the first argument points to, a -m option module
399400 appended to the python_context option value, or the code given within -c?
400-
401- Primarily, it simply identifies what "__main__" is, while providing other
402- conveniences such as postmortem.
403401 """
404402 def __init__ (self ,
405403 args , context = (),
@@ -414,15 +412,14 @@ def __init__(self,
414412 context
415413 A list of loader descriptors that will be used to establish the
416414 context of __main__ module.
417- locals
418- The dictionary that will be used for __main__.
419415 main
420416 Overload to explicitly state what main is. None will cause the
421417 class to attempt to fill in the attribute using 'args' and other
422418 system objects like sys.stdin.
423419 """
424420 self .args = args
425421 self .context = context and list (context ) or ()
422+ self .reset_module__main__ ()
426423
427424 if main is not None :
428425 self .main = main
@@ -458,8 +455,13 @@ class to attempt to fill in the attribute using 'args' and other
458455 # console
459456 self .main = (None , None )
460457
458+ def reset_module__main__ (self ):
459+ mod = types .ModuleType ('__main__' )
460+ mod .__package__ = None
461+ mod .__builtins__ = __builtins__
462+ self .module__main__ = mod
463+
461464 def _call (self ,
462- locals = None ,
463465 console = ExtendedConsole ,
464466 context = None
465467 ):
@@ -468,10 +470,8 @@ def _call(self,
468470 (Note: tramples on sys.argv, __main__ in sys.modules)
469471 (Use __call__ instead)
470472 """
471- if locals is None :
472- locals = {}
473- locals ['__name__' ] = '__context__'
474- sys .modules ['__context__' ] = locals
473+ sys .modules ['__main__' ] = self .module__main__
474+ md = self .module__main__ .__dict__
475475
476476 # Establish execution context in the locals;
477477 # iterate over all the loaders in self.context and
@@ -491,19 +491,17 @@ def _call(self,
491491 except :
492492 print_exception (* sys .exc_info ())
493493 return 1
494- locals [ ' __file__' ] = getattr (
494+ self . module__main__ . __file__ = getattr (
495495 li , 'get_filename' , lambda x : x
496496 )(rpath )
497- locals [ ' __loader__' ] = li
497+ self . module__main__ . __loader__ = li
498498 try :
499- exec (code , globals (), locals )
499+ exec (code , md , md )
500500 except :
501501 e , v , tb = sys .exc_info ()
502502 print_exception (e , v , tb .tb_next or tb )
503503 return 1
504504
505- sys .modules ['__main__' ] = locals
506- locals ['__name__' ] = '__main__'
507505 if self .main == (None , None ):
508506 # It's interactive.
509507 sys .argv = self .args or ['<console>' ]
@@ -514,7 +512,7 @@ def _call(self,
514512 except ImportError :
515513 pass
516514
517- ic = console (locals = locals )
515+ ic = console (locals = md )
518516 try :
519517 ic .interact ()
520518 except SystemExit as e :
@@ -523,11 +521,11 @@ def _call(self,
523521 else :
524522 # It's ultimately a code object.
525523 path , loader = self .main
526- locals [ ' __file__' ] = getattr (
524+ self . module__main__ . __file__ = getattr (
527525 loader , 'get_filename' , lambda x : x
528526 )(path )
529527 sys .argv = list (self .args )
530- sys .argv .insert (0 , locals [ ' __file__' ] )
528+ sys .argv .insert (0 , self . module__main__ . __file__ )
531529 try :
532530 code = loader .get_code (path )
533531 except :
@@ -540,13 +538,13 @@ def _call(self,
540538 if context is not None :
541539 with context :
542540 try :
543- exec (code , globals (), locals )
541+ exec (code , md , md )
544542 except :
545543 exe_exception = True
546544 raise
547545 else :
548546 try :
549- exec (code , globals (), locals )
547+ exec (code , md , md )
550548 except :
551549 exe_exception = True
552550 raise
@@ -610,9 +608,8 @@ def command_execution(args = sys.argv):
610608 loader = getattr (co , 'python_main' , None ),
611609 )
612610
613- def command (args = sys .argv , locals = {} ):
611+ def command (args = sys .argv ):
614612 return command_execution (args = args )(
615- locals = locals ,
616613 context = postmortem (os .environ .get ('PYTHON_POSTMORTEM' ))
617614 )
618615
0 commit comments