summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-09-01 00:13:45 +1000
committerNick Coghlan <ncoghlan@gmail.com>2012-09-01 00:13:45 +1000
commit91b9f139bc629e1ba931c60a3301e8062f6f4e6d (patch)
treee959ba896e7fcb4c24bcafad98673c737b281369
parent380c55cc58911a4777f080744f596d1e96fd2357 (diff)
downloadcpython-git-91b9f139bc629e1ba931c60a3301e8062f6f4e6d.tar.gz
Issue #15828: Restore support for C extension modules in imp.load_module()
-rw-r--r--Lib/imp.py6
-rw-r--r--Lib/test/test_imp.py29
-rw-r--r--Lib/test/test_import.py19
-rw-r--r--Misc/NEWS2
4 files changed, 35 insertions, 21 deletions
diff --git a/Lib/imp.py b/Lib/imp.py
index 80b04c83ed..da9c84ee39 100644
--- a/Lib/imp.py
+++ b/Lib/imp.py
@@ -153,13 +153,15 @@ def load_module(name, file, filename, details):
warnings.simplefilter('ignore')
if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
raise ValueError('invalid file open mode {!r}'.format(mode))
- elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
+ elif file is None and type_ in {PY_SOURCE, PY_COMPILED, C_EXTENSION}:
msg = 'file object required for import (type code {})'.format(type_)
raise ValueError(msg)
elif type_ == PY_SOURCE:
return load_source(name, filename, file)
elif type_ == PY_COMPILED:
return load_compiled(name, filename, file)
+ elif type_ == C_EXTENSION:
+ return load_dynamic(name, filename, file)
elif type_ == PKG_DIRECTORY:
return load_package(name, filename)
elif type_ == C_BUILTIN:
@@ -167,7 +169,7 @@ def load_module(name, file, filename, details):
elif type_ == PY_FROZEN:
return init_frozen(name)
else:
- msg = "Don't know how to import {} (type code {}".format(name, type_)
+ msg = "Don't know how to import {} (type code {})".format(name, type_)
raise ImportError(msg, name=name)
diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py
index a660278c9c..20e5608e81 100644
--- a/Lib/test/test_imp.py
+++ b/Lib/test/test_imp.py
@@ -186,6 +186,35 @@ class ImportTests(unittest.TestCase):
self.assertRaises(SyntaxError,
imp.find_module, "badsyntax_pep3120", [path])
+ def test_load_from_source(self):
+ # Verify that the imp module can correctly load and find .py files
+ # XXX (ncoghlan): It would be nice to use support.CleanImport
+ # here, but that breaks because the os module registers some
+ # handlers in copy_reg on import. Since CleanImport doesn't
+ # revert that registration, the module is left in a broken
+ # state after reversion. Reinitialising the module contents
+ # and just reverting os.environ to its previous state is an OK
+ # workaround
+ orig_path = os.path
+ orig_getenv = os.getenv
+ with support.EnvironmentVarGuard():
+ x = imp.find_module("os")
+ self.addCleanup(x[0].close)
+ new_os = imp.load_module("os", *x)
+ self.assertIs(os, new_os)
+ self.assertIs(orig_path, new_os.path)
+ self.assertIsNot(orig_getenv, new_os.getenv)
+
+ @support.cpython_only
+ def test_issue15828_load_extensions(self):
+ # Issue 15828 picked up that the adapter between the old imp API
+ # and importlib couldn't handle C extensions
+ example = "_heapq"
+ x = imp.find_module(example)
+ self.addCleanup(x[0].close)
+ mod = imp.load_module(example, *x)
+ self.assertEqual(mod.__name__, example)
+
def test_load_dynamic_ImportError_path(self):
# Issue #1559549 added `name` and `path` attributes to ImportError
# in order to provide better detail. Issue #10854 implemented those
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index 60447dc26b..19863b936a 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -149,25 +149,6 @@ class ImportTests(unittest.TestCase):
self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(mode))
- def test_imp_module(self):
- # Verify that the imp module can correctly load and find .py files
- # XXX (ncoghlan): It would be nice to use support.CleanImport
- # here, but that breaks because the os module registers some
- # handlers in copy_reg on import. Since CleanImport doesn't
- # revert that registration, the module is left in a broken
- # state after reversion. Reinitialising the module contents
- # and just reverting os.environ to its previous state is an OK
- # workaround
- orig_path = os.path
- orig_getenv = os.getenv
- with EnvironmentVarGuard():
- x = imp.find_module("os")
- self.addCleanup(x[0].close)
- new_os = imp.load_module("os", *x)
- self.assertIs(os, new_os)
- self.assertIs(orig_path, new_os.path)
- self.assertIsNot(orig_getenv, new_os.getenv)
-
def test_bug7732(self):
source = TESTFN + '.py'
os.mkdir(source)
diff --git a/Misc/NEWS b/Misc/NEWS
index 946ac46467..ccf60c26eb 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,8 @@ Core and Builtins
Library
-------
+- Issue #15828: Restore support for C extensions in imp.load_module().
+
- Issue #15340: Fix importing the random module when /dev/urandom cannot
be opened. This was a regression caused by the hash randomization patch.