[Python-checkins] cpython (merge 3.5 -> default): Issue #14285: Merge runpy fix from 3.5

martin.panter python-checkins at python.org
Thu Dec 10 22:55:59 EST 2015


https://hg.python.org/cpython/rev/a526ebcfd31d
changeset: 99521:a526ebcfd31d
parent: 99519:1fe904420c20
parent: 99520:3202d143a194
user: Martin Panter <vadmium+py at gmail.com>
date: Fri Dec 11 03:35:31 2015 +0000
summary:
 Issue #14285: Merge runpy fix from 3.5
files:
 Doc/library/runpy.rst | 3 +-
 Doc/using/cmdline.rst | 2 +-
 Lib/runpy.py | 22 ++++++++++++++++---
 Lib/test/test_cmd_line_script.py | 1 +
 Lib/test/test_runpy.py | 9 ++++++++
 5 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/Doc/library/runpy.rst b/Doc/library/runpy.rst
--- a/Doc/library/runpy.rst
+++ b/Doc/library/runpy.rst
@@ -36,7 +36,8 @@
 import mechanism (refer to :pep:`302` for details) and then executed in a
 fresh module namespace.
 
- If the supplied module name refers to a package rather than a normal
+ The *mod_name* argument should be an absolute module name.
+ If the module name refers to a package rather than a normal
 module, then that package is imported and the ``__main__`` submodule within
 that package is then executed and the resulting module globals dictionary
 returned.
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
--- a/Doc/using/cmdline.rst
+++ b/Doc/using/cmdline.rst
@@ -77,7 +77,7 @@
 the :mod:`__main__` module.
 
 Since the argument is a *module* name, you must not give a file extension
- (``.py``). The ``module-name`` should be a valid Python module name, but
+ (``.py``). The module name should be a valid absolute Python module name, but
 the implementation may not always enforce this (e.g. it may allow you to
 use a name that includes a hyphen).
 
diff --git a/Lib/runpy.py b/Lib/runpy.py
--- a/Lib/runpy.py
+++ b/Lib/runpy.py
@@ -100,6 +100,21 @@
 
 # Helper to get the loader, code and filename for a module
 def _get_module_details(mod_name, error=ImportError):
+ if mod_name.startswith("."):
+ raise error("Relative module names not supported")
+ pkg_name, _, _ = mod_name.rpartition(".")
+ if pkg_name:
+ # Try importing the parent to avoid catching initialization errors
+ try:
+ __import__(pkg_name)
+ except ImportError as e:
+ # If the parent or higher ancestor package is missing, let the
+ # error be raised by find_spec() below and then be caught. But do
+ # not allow other errors to be caught.
+ if e.name is None or (e.name != pkg_name and
+ not pkg_name.startswith(e.name + ".")):
+ raise
+
 try:
 spec = importlib.util.find_spec(mod_name)
 except (ImportError, AttributeError, TypeError, ValueError) as ex:
@@ -107,17 +122,16 @@
 # importlib, where the latter raises other errors for cases where
 # pkgutil previously raised ImportError
 msg = "Error while finding spec for {!r} ({}: {})"
- raise error(msg.format(mod_name, type(ex), ex)) from ex
+ raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex
 if spec is None:
 raise error("No module named %s" % mod_name)
 if spec.submodule_search_locations is not None:
 if mod_name == "__main__" or mod_name.endswith(".__main__"):
 raise error("Cannot use package as __main__ module")
- __import__(mod_name) # Do not catch exceptions initializing package
 try:
 pkg_main_name = mod_name + ".__main__"
- return _get_module_details(pkg_main_name)
- except ImportError as e:
+ return _get_module_details(pkg_main_name, error)
+ except error as e:
 raise error(("%s; %r is a package and cannot " +
 "be directly executed") %(e, mod_name))
 loader = spec.loader
diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py
--- a/Lib/test/test_cmd_line_script.py
+++ b/Lib/test/test_cmd_line_script.py
@@ -433,6 +433,7 @@
 ('importlib', br'No module named.*'
 br'is a package and cannot be directly executed'),
 ('importlib.nonexistant', br'No module named'),
+ ('.unittest', br'Relative module names not supported'),
 )
 for name, regex in tests:
 with self.subTest(name):
diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py
--- a/Lib/test/test_runpy.py
+++ b/Lib/test/test_runpy.py
@@ -197,8 +197,11 @@
 self.expect_import_error("sys.imp.eric")
 self.expect_import_error("os.path.half")
 self.expect_import_error("a.bee")
+ # Relative names not allowed
 self.expect_import_error(".howard")
 self.expect_import_error("..eaten")
+ self.expect_import_error(".test_runpy")
+ self.expect_import_error(".unittest")
 # Package without __main__.py
 self.expect_import_error("multiprocessing")
 
@@ -460,6 +463,12 @@
 self.assertNotIn("finding spec", format(err))
 else:
 self.fail("Nothing raised; expected {}".format(name))
+ try:
+ run_module(mod_name + ".submodule")
+ except exception as err:
+ self.assertNotIn("finding spec", format(err))
+ else:
+ self.fail("Nothing raised; expected {}".format(name))
 
 def test_run_package_in_namespace_package(self):
 for depth in range(1, 4):
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /