diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2009-02-08 01:58:26 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2009-02-08 01:58:26 (GMT) |
commit | 3f48ae35c710c5e5101d5de6721b1e2ccb56df68 (patch) | |
tree | 971feab37df37b7ab70429c75069d36b2c8b9557 /Lib | |
parent | f72d9fb02f2ff536c64f1e65780b4a414eb3bb4d (diff) | |
download | cpython-3f48ae35c710c5e5101d5de6721b1e2ccb56df68.zip cpython-3f48ae35c710c5e5101d5de6721b1e2ccb56df68.tar.gz cpython-3f48ae35c710c5e5101d5de6721b1e2ccb56df68.tar.bz2 |
Merged revisions 69419-69420 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r69419 | nick.coghlan | 2009-02-08 11:26:34 +1000 (Sun, 08 Feb 2009) | 1 line
Issue 4195: Restore the ability to execute packages with the -m switch (but this time in a way that leaves the import machinery in a valid state). (Original patch by Andi Vajda)
........
r69420 | nick.coghlan | 2009-02-08 11:46:01 +1000 (Sun, 08 Feb 2009) | 1 line
Mention patch submitter in NEWS entry for r69419
........
Diffstat (limited to 'Lib')
-rwxr-xr-x | Lib/runpy.py | 18 | ||||
-rw-r--r-- | Lib/test/test_cmd_line_script.py | 65 |
2 files changed, 76 insertions, 7 deletions
diff --git a/Lib/runpy.py b/Lib/runpy.py index 22a2989..e0aabeb 100755 --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -80,13 +80,19 @@ def _get_module_details(mod_name): if loader is None: raise ImportError("No module named %s" % mod_name) if loader.is_package(mod_name): - raise ImportError(("%s is a package and cannot " + - "be directly executed") % mod_name) + if mod_name == "__main__" or mod_name.endswith(".__main__"): + raise ImportError(("Cannot use package as __main__ module")) + try: + pkg_main_name = mod_name + ".__main__" + return _get_module_details(pkg_main_name) + except ImportError as e: + raise ImportError(("%s; %r is a package and cannot " + + "be directly executed") %(e, mod_name)) code = loader.get_code(mod_name) if code is None: raise ImportError("No code object available for %s" % mod_name) filename = _get_filename(loader, mod_name) - return loader, code, filename + return mod_name, loader, code, filename # XXX ncoghlan: Should this be documented and made public? @@ -101,12 +107,12 @@ def _run_module_as_main(mod_name, set_argv0=True): __loader__ """ try: - loader, code, fname = _get_module_details(mod_name) + mod_name, loader, code, fname = _get_module_details(mod_name) except ImportError as exc: # Try to provide a good error message # for directories, zip files and the -m switch if set_argv0: - # For -m switch, just disply the exception + # For -m switch, just display the exception info = str(exc) else: # For directories/zipfiles, let the user @@ -127,7 +133,7 @@ def run_module(mod_name, init_globals=None, Returns the resulting top level namespace dictionary """ - loader, code, fname = _get_module_details(mod_name) + mod_name, loader, code, fname = _get_module_details(mod_name) if run_name is None: run_name = mod_name pkg_name = mod_name.rpartition('.')[0] diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index 7fab383..e060ec1 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -113,7 +113,7 @@ def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, os.unlink(script_name) #if verbose: # zip_file = zipfile.ZipFile(zip_name, 'r') - # print 'Contents of %r:' % zip_name + # print('Contents of %r:' % zip_name) # zip_file.printdir() # zip_file.close() return zip_name, os.path.join(zip_name, script_name_in_zip) @@ -158,6 +158,16 @@ class CmdLineTest(unittest.TestCase): self.assert_(printed_package in data) self.assert_(printed_argv0 in data) + def _check_import_error(self, script_name, expected_msg, + *cmd_line_switches): + run_args = cmd_line_switches + (script_name,) + exit_code, data = _run_python(*run_args) + if verbose: + print('Output from test script %r:' % script_name) + print(data) + print('Expected output: %r' % expected_msg) + self.assert_(expected_msg in data) + def test_basic_script(self): with temp_dir() as script_dir: script_name = _make_test_script(script_dir, 'script') @@ -182,6 +192,11 @@ class CmdLineTest(unittest.TestCase): os.remove(script_name) self._check_script(script_dir, compiled_name, script_dir, '') + def test_directory_error(self): + with temp_dir() as script_dir: + msg = "can't find '__main__.py' in %r" % script_dir + self._check_import_error(script_dir, msg) + def test_zipfile(self): with temp_dir() as script_dir: script_name = _make_test_script(script_dir, '__main__') @@ -195,6 +210,13 @@ class CmdLineTest(unittest.TestCase): zip_name, run_name = _make_test_zip(script_dir, 'test_zip', compiled_name) self._check_script(zip_name, run_name, zip_name, '') + def test_zipfile_error(self): + with temp_dir() as script_dir: + script_name = _make_test_script(script_dir, 'not_main') + zip_name, run_name = _make_test_zip(script_dir, 'test_zip', script_name) + msg = "can't find '__main__.py' in %r" % zip_name + self._check_import_error(zip_name, msg) + def test_module_in_package(self): with temp_dir() as script_dir: pkg_dir = os.path.join(script_dir, 'test_pkg') @@ -215,6 +237,47 @@ class CmdLineTest(unittest.TestCase): launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name) self._check_script(launch_name, run_name, run_name, 'test_pkg.test_pkg') + def test_package(self): + with temp_dir() as script_dir: + pkg_dir = os.path.join(script_dir, 'test_pkg') + _make_test_pkg(pkg_dir) + script_name = _make_test_script(pkg_dir, '__main__') + launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') + self._check_script(launch_name, script_name, + script_name, 'test_pkg') + + def test_package_compiled(self): + with temp_dir() as script_dir: + pkg_dir = os.path.join(script_dir, 'test_pkg') + _make_test_pkg(pkg_dir) + script_name = _make_test_script(pkg_dir, '__main__') + compiled_name = _compile_test_script(script_name) + os.remove(script_name) + launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') + self._check_script(launch_name, compiled_name, + compiled_name, 'test_pkg') + + def test_package_error(self): + with temp_dir() as script_dir: + pkg_dir = os.path.join(script_dir, 'test_pkg') + _make_test_pkg(pkg_dir) + msg = ("'test_pkg' is a package and cannot " + "be directly executed") + launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') + self._check_import_error(launch_name, msg) + + def test_package_recursion(self): + with temp_dir() as script_dir: + pkg_dir = os.path.join(script_dir, 'test_pkg') + _make_test_pkg(pkg_dir) + main_dir = os.path.join(pkg_dir, '__main__') + _make_test_pkg(main_dir) + msg = ("Cannot use package as __main__ module; " + "'test_pkg' is a package and cannot " + "be directly executed") + launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg') + self._check_import_error(launch_name, msg) + def test_main(): test.support.run_unittest(CmdLineTest) |