r47142 - in python/trunk: Doc/lib/librunpy.tex Lib/runpy.py Lib/test/test_runpy.py
Author: nick.coghlan Date: Wed Jun 28 12:41:47 2006 New Revision: 47142 Modified: python/trunk/Doc/lib/librunpy.tex python/trunk/Lib/runpy.py python/trunk/Lib/test/test_runpy.py Log: Make full module name available as __module_name__ even when __name__ is set to something else (like '__main__') Modified: python/trunk/Doc/lib/librunpy.tex ============================================================================== --- python/trunk/Doc/lib/librunpy.tex (original) +++ python/trunk/Doc/lib/librunpy.tex Wed Jun 28 12:41:47 2006 @@ -35,16 +35,19 @@ global variables below are defined in the supplied dictionary, those definitions are overridden by the \code{run_module} function. -The special global variables \code{__name__}, \code{__file__}, -\code{__loader__} and \code{__builtins__} are set in the globals -dictionary before the module code is executed. +The special global variables \code{__name__}, \code{__module_name__}, +\code{__file__}, \code{__loader__} and \code{__builtins__} are +set in the globals dictionary before the module code is executed. \code{__name__} is set to \var{run_name} if this optional argument is supplied, and the \var{mod_name} argument otherwise. +\code{__module_name__} is always set to \var{mod_name} (this allows +modules to use imports relative to their package name). + \code{__loader__} is set to the PEP 302 module loader used to retrieve -the code for the module (This loader may be a wrapper around the -standard import mechanism). +the code for the module (This will not be defined if the module was +found using the standard import mechanism). \code{__file__} is set to the name provided by the module loader. If the loader does not make filename information available, this @@ -55,10 +58,12 @@ If the argument \var{alter_sys} is supplied and evaluates to \code{True}, then \code{sys.argv[0]} is updated with the value of -\code{__file__} and \code{sys.modules[__name__]} is updated with a +\code{__file__} and \code{sys.modules[mod_name]} is updated with a temporary module object for the module being executed. Both -\code{sys.argv[0]} and \code{sys.modules[__name__]} are restored to -their original values before the function returns. +\code{sys.argv[0]} and \code{sys.modules[mod_name]} are restored to +their original values before the function returns. If \var{run_name} +differs from \var{mod_name} entries are made in \code{sys.modules} +for both names. Note that this manipulation of \module{sys} is not thread-safe. Other threads may see the partially initialised module, as well as the Modified: python/trunk/Lib/runpy.py ============================================================================== --- python/trunk/Lib/runpy.py (original) +++ python/trunk/Lib/runpy.py Wed Jun 28 12:41:47 2006 @@ -21,18 +21,19 @@ ] -def _run_code(code, run_globals, init_globals, +def _run_code(code, run_globals, init_globals, run_name, mod_name, mod_fname, mod_loader): """Helper for _run_module_code""" if init_globals is not None: run_globals.update(init_globals) - run_globals.update(__name__ = mod_name, + run_globals.update(__name__ = run_name, + __module_name__ = mod_name, __file__ = mod_fname, __loader__ = mod_loader) exec code in run_globals return run_globals -def _run_module_code(code, init_globals=None, +def _run_module_code(code, init_globals=None, run_name=None, mod_name=None, mod_fname=None, mod_loader=None, alter_sys=False): """Helper for run_module""" @@ -42,26 +43,33 @@ temp_module = imp.new_module(mod_name) mod_globals = temp_module.__dict__ saved_argv0 = sys.argv[0] - restore_module = mod_name in sys.modules - if restore_module: - saved_module = sys.modules[mod_name] + sentinel = object() + module_mod_name = sys.modules.get(mod_name, sentinel) + module_run_name = sys.modules.get(run_name, sentinel) sys.argv[0] = mod_fname sys.modules[mod_name] = temp_module + if run_name != mod_name: + sys.modules[run_name] = temp_module try: - _run_code(code, mod_globals, init_globals, + _run_code(code, mod_globals, init_globals, run_name, mod_name, mod_fname, mod_loader) finally: sys.argv[0] = saved_argv0 - if restore_module: - sys.modules[mod_name] = saved_module - else: - del sys.modules[mod_name] + if module_mod_name is not sentinel: + sys.modules[mod_name] = module_mod_name + else: + del sys.modules[mod_name] + if run_name != mod_name: + if module_run_name is not sentinel: + sys.modules[run_name] = module_run_name + else: + del sys.modules[run_name] # Copy the globals of the temporary module, as they # may be cleared when the temporary module goes away return mod_globals.copy() else: # Leave the sys module alone - return _run_code(code, {}, init_globals, + return _run_code(code, {}, init_globals, run_name, mod_name, mod_fname, mod_loader) @@ -92,7 +100,7 @@ if run_name is None: run_name = mod_name return _run_module_code(code, init_globals, run_name, - filename, loader, alter_sys) + mod_name, filename, loader, alter_sys) if __name__ == "__main__": Modified: python/trunk/Lib/test/test_runpy.py ============================================================================== --- python/trunk/Lib/test/test_runpy.py (original) +++ python/trunk/Lib/test/test_runpy.py Wed Jun 28 12:41:47 2006 @@ -23,6 +23,8 @@ "run_argv0 = sys.argv[0]\n" "if __name__ in sys.modules:\n" " run_name = sys.modules[__name__].__name__\n" + "if __module_name__ in sys.modules:\n" + " mod_name = sys.modules[__module_name__].__module_name__\n" "# Check nested operation\n" "import runpy\n" "nested = runpy._run_module_code('x=1\\n', mod_name='<run>',\n" @@ -32,14 +34,16 @@ def test_run_module_code(self): initial = object() - name = "<Nonsense>" + run_name = "<Nonsense>" + mod_name = "<ModuleNonsense>" file = "Some other nonsense" loader = "Now you're just being silly" d1 = dict(initial=initial) saved_argv0 = sys.argv[0] d2 = _run_module_code(self.test_source, d1, - name, + run_name, + mod_name, file, loader, True) @@ -47,19 +51,23 @@ self.failUnless(d2["initial"] is initial) self.failUnless(d2["result"] == self.expected_result) self.failUnless(d2["nested"]["x"] == 1) - self.failUnless(d2["__name__"] is name) - self.failUnless(d2["run_name"] is name) + self.failUnless(d2["__name__"] is run_name) + self.failUnless(d2["run_name"] is run_name) + self.failUnless(d2["__module_name__"] is mod_name) + self.failUnless(d2["mod_name"] is mod_name) self.failUnless(d2["__file__"] is file) self.failUnless(d2["run_argv0"] is file) self.failUnless(d2["__loader__"] is loader) self.failUnless(sys.argv[0] is saved_argv0) - self.failUnless(name not in sys.modules) + self.failUnless(mod_name not in sys.modules) + self.failUnless(run_name not in sys.modules) def test_run_module_code_defaults(self): saved_argv0 = sys.argv[0] d = _run_module_code(self.test_source) self.failUnless(d["result"] == self.expected_result) self.failUnless(d["__name__"] is None) + self.failUnless(d["__module_name__"] is None) self.failUnless(d["__file__"] is None) self.failUnless(d["__loader__"] is None) self.failUnless(d["run_argv0"] is saved_argv0)
On Wednesday 28 June 2006 20:41, nick.coghlan wrote:
Author: nick.coghlan Date: Wed Jun 28 12:41:47 2006 New Revision: 47142
Modified: python/trunk/Doc/lib/librunpy.tex python/trunk/Lib/runpy.py python/trunk/Lib/test/test_runpy.py Log: Make full module name available as __module_name__ even when __name__ is set to something else (like '__main__')
Er. Um. Feature freeze? Anthony -- Anthony Baxter <anthony@interlink.com.au> It's never too late to have a happy childhood.
Anthony Baxter wrote:
On Wednesday 28 June 2006 20:41, nick.coghlan wrote:
Author: nick.coghlan Date: Wed Jun 28 12:41:47 2006 New Revision: 47142
Modified: python/trunk/Doc/lib/librunpy.tex python/trunk/Lib/runpy.py python/trunk/Lib/test/test_runpy.py Log: Make full module name available as __module_name__ even when __name__ is set to something else (like '__main__')
Er. Um. Feature freeze?
Sorry about that - I was trying to deal with a conflict between PEP 328 and 338 (bug 1510172) and didn't even think about the fact that this counted as a new feature. See my response to your RFC about tightening up control of the trunk - I'd really like to make these two PEPs play nicely together before beta 2. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org
participants (3)
-
Anthony Baxter -
Nick Coghlan -
nick.coghlan