Issue #15828: Restore support for C extension modules in imp.load_module()

This commit is contained in:
Nick Coghlan 2012-09-01 00:13:45 +10:00
parent 2d337c7061
commit 5d0612411e
4 changed files with 35 additions and 21 deletions

View File

@ -153,13 +153,15 @@ def load_module(name, file, filename, details):
warnings.simplefilter('ignore') warnings.simplefilter('ignore')
if mode and (not mode.startswith(('r', 'U')) or '+' in mode): if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
raise ValueError('invalid file open mode {!r}'.format(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_) msg = 'file object required for import (type code {})'.format(type_)
raise ValueError(msg) raise ValueError(msg)
elif type_ == PY_SOURCE: elif type_ == PY_SOURCE:
return load_source(name, filename, file) return load_source(name, filename, file)
elif type_ == PY_COMPILED: elif type_ == PY_COMPILED:
return load_compiled(name, filename, file) return load_compiled(name, filename, file)
elif type_ == C_EXTENSION:
return load_dynamic(name, filename, file)
elif type_ == PKG_DIRECTORY: elif type_ == PKG_DIRECTORY:
return load_package(name, filename) return load_package(name, filename)
elif type_ == C_BUILTIN: elif type_ == C_BUILTIN:
@ -167,7 +169,7 @@ def load_module(name, file, filename, details):
elif type_ == PY_FROZEN: elif type_ == PY_FROZEN:
return init_frozen(name) return init_frozen(name)
else: 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) raise ImportError(msg, name=name)

View File

@ -186,6 +186,35 @@ class ImportTests(unittest.TestCase):
self.assertRaises(SyntaxError, self.assertRaises(SyntaxError,
imp.find_module, "badsyntax_pep3120", [path]) 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): def test_load_dynamic_ImportError_path(self):
# Issue #1559549 added `name` and `path` attributes to ImportError # Issue #1559549 added `name` and `path` attributes to ImportError
# in order to provide better detail. Issue #10854 implemented those # in order to provide better detail. Issue #10854 implemented those

View File

@ -149,25 +149,6 @@ class ImportTests(unittest.TestCase):
self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(mode)) 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): def test_bug7732(self):
source = TESTFN + '.py' source = TESTFN + '.py'
os.mkdir(source) os.mkdir(source)

View File

@ -54,6 +54,8 @@ Core and Builtins
Library Library
------- -------
- Issue #15828: Restore support for C extensions in imp.load_module()
- Issue #10650: Deprecate the watchexp parameter of the Decimal.quantize() - Issue #10650: Deprecate the watchexp parameter of the Decimal.quantize()
method. method.