summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2009-02-08 01:26:34 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2009-02-08 01:26:34 (GMT)
commitd39600e69f9782481ffadf1ada1d1da9857489e8 (patch)
tree0e25465b50a97c08a1fd957f25ebf5fd5a94475a /Lib
parente0820e2ea7b378993fcbeb82fc33d9558be85abe (diff)
downloadcpython-d39600e69f9782481ffadf1ada1d1da9857489e8.zip
cpython-d39600e69f9782481ffadf1ada1d1da9857489e8.tar.gz
cpython-d39600e69f9782481ffadf1ada1d1da9857489e8.tar.bz2
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)
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/runpy.py18
-rw-r--r--Lib/test/test_cmd_line_script.py63
2 files changed, 75 insertions, 6 deletions
diff --git a/Lib/runpy.py b/Lib/runpy.py
index fea6104..f9a29ad 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, 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 995d4a8..29c92fa 100644
--- a/Lib/test/test_cmd_line_script.py
+++ b/Lib/test/test_cmd_line_script.py
@@ -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.test_support.run_unittest(CmdLineTest)