diff options
author | Brett Cannon <brett@python.org> | 2012-05-11 18:48:41 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2012-05-11 18:48:41 (GMT) |
commit | c049952de76cbcd00e490e48445ed7a50d3dc83a (patch) | |
tree | 91d1ff6bffbb8d6c5b04a8bae6b53944eb078335 /Lib | |
parent | 0c59b039b86afa9f51c30f7d9f340d9c75984488 (diff) | |
download | cpython-c049952de76cbcd00e490e48445ed7a50d3dc83a.zip cpython-c049952de76cbcd00e490e48445ed7a50d3dc83a.tar.gz cpython-c049952de76cbcd00e490e48445ed7a50d3dc83a.tar.bz2 |
Issue #13959: Have
importlib.abc.FileLoader.load_module()/get_filename() and
importlib.machinery.ExtensionFileLoader.load_module() have their
single argument be optional as the loader's constructor has all the
ncessary information.
This allows for the deprecation of
imp.load_source()/load_compile()/load_package().
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/imp.py | 60 | ||||
-rw-r--r-- | Lib/importlib/_bootstrap.py | 14 | ||||
-rw-r--r-- | Lib/importlib/test/extension/test_loader.py | 20 | ||||
-rw-r--r-- | Lib/importlib/test/source/test_file_loader.py | 35 | ||||
-rw-r--r-- | Lib/test/test_imp.py | 19 | ||||
-rw-r--r-- | Lib/test/test_tools.py | 8 |
6 files changed, 113 insertions, 43 deletions
@@ -24,8 +24,7 @@ import tokenize import warnings -# XXX "deprecate" once find_module(), load_module(), and get_suffixes() are -# deprecated. +# DEPRECATED SEARCH_ERROR = 0 PY_SOURCE = 1 PY_COMPILED = 2 @@ -112,8 +111,11 @@ class _LoadSourceCompatibility(_HackedGetData, _bootstrap.SourceFileLoader): """Compatibility support for implementing load_source().""" -# XXX deprecate after better API exposed in importlib def load_source(name, pathname, file=None): + msg = ('imp.load_source() is deprecated; use ' + 'importlib.machinery.SourceFileLoader(name, pathname).load_module()' + ' instead') + warnings.warn(msg, DeprecationWarning, 2) return _LoadSourceCompatibility(name, pathname, file).load_module(name) @@ -123,15 +125,22 @@ class _LoadCompiledCompatibility(_HackedGetData, """Compatibility support for implementing load_compiled().""" -# XXX deprecate def load_compiled(name, pathname, file=None): + msg = ('imp.load_compiled() is deprecated; use ' + 'importlib.machinery.SourcelessFileLoader(name, pathname).' + 'load_module() instead ') + warnings.warn(msg, DeprecationWarning, 2) return _LoadCompiledCompatibility(name, pathname, file).load_module(name) -# XXX deprecate def load_package(name, path): + msg = ('imp.load_package() is deprecated; use either ' + 'importlib.machinery.SourceFileLoader() or ' + 'importlib.machinery.SourcelessFileLoader() instead') + warnings.warn(msg, DeprecationWarning, 2) if os.path.isdir(path): - extensions = machinery.SOURCE_SUFFIXES[:] + [machinery.BYTECODE_SUFFIXES] + extensions = (machinery.SOURCE_SUFFIXES[:] + + machinery.BYTECODE_SUFFIXES[:]) for extension in extensions: path = os.path.join(path, '__init__'+extension) if os.path.exists(path): @@ -149,26 +158,29 @@ def load_module(name, file, filename, details): """ suffix, mode, type_ = details - 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}: - 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_ == PKG_DIRECTORY: - return load_package(name, filename) - elif type_ == C_BUILTIN: - return init_builtin(name) - elif type_ == PY_FROZEN: - return init_frozen(name) - else: - msg = "Don't know how to import {} (type code {}".format(name, type_) - raise ImportError(msg, name=name) + with warnings.catch_warnings(): + 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}: + 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_ == PKG_DIRECTORY: + return load_package(name, filename) + elif type_ == C_BUILTIN: + return init_builtin(name) + elif type_ == PY_FROZEN: + return init_frozen(name) + else: + msg = "Don't know how to import {} (type code {}".format(name, type_) + raise ImportError(msg, name=name) +# XXX deprecate def find_module(name, path=None): """Search for a module. diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index ce23043..41b96a9 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -282,8 +282,10 @@ def _check_name(method): compared against. If the comparison fails then ImportError is raised. """ - def _check_name_wrapper(self, name, *args, **kwargs): - if self.name != name: + def _check_name_wrapper(self, name=None, *args, **kwargs): + if name is None: + name = self.name + elif self.name != name: raise ImportError("loader cannot handle %s" % name, name=name) return method(self, name, *args, **kwargs) _wrap(_check_name_wrapper, method) @@ -614,6 +616,11 @@ class FileLoader: self.path = path @_check_name + def load_module(self, fullname): + """Load a module from a file.""" + return super().load_module(fullname) + + @_check_name def get_filename(self, fullname): """Return the path to the source file as found by the finder.""" return self.path @@ -713,17 +720,14 @@ class ExtensionFileLoader: del sys.modules[fullname] raise - @_check_name def is_package(self, fullname): """Return False as an extension module can never be a package.""" return False - @_check_name def get_code(self, fullname): """Return None as an extension module cannot create a code object.""" return None - @_check_name def get_source(self, fullname): """Return None as extension modules have no source code.""" return None diff --git a/Lib/importlib/test/extension/test_loader.py b/Lib/importlib/test/extension/test_loader.py index ab2b686..4f486ce 100644 --- a/Lib/importlib/test/extension/test_loader.py +++ b/Lib/importlib/test/extension/test_loader.py @@ -1,4 +1,4 @@ -from importlib import _bootstrap +from importlib import machinery from . import util as ext_util from .. import abc from .. import util @@ -11,10 +11,20 @@ class LoaderTests(abc.LoaderTests): """Test load_module() for extension modules.""" + def setUp(self): + self.loader = machinery.ExtensionFileLoader(ext_util.NAME, + ext_util.FILEPATH) + def load_module(self, fullname): - loader = _bootstrap.ExtensionFileLoader(ext_util.NAME, - ext_util.FILEPATH) - return loader.load_module(fullname) + return self.loader.load_module(fullname) + + def test_load_module_API(self): + # Test the default argument for load_module(). + self.loader.load_module() + self.loader.load_module(None) + with self.assertRaises(ImportError): + self.load_module('XXX') + def test_module(self): with util.uncache(ext_util.NAME): @@ -25,7 +35,7 @@ class LoaderTests(abc.LoaderTests): self.assertEqual(getattr(module, attr), value) self.assertTrue(ext_util.NAME in sys.modules) self.assertTrue(isinstance(module.__loader__, - _bootstrap.ExtensionFileLoader)) + machinery.ExtensionFileLoader)) def test_package(self): # Extensions are not found in packages. diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py index c4c7545..ffa0c24 100644 --- a/Lib/importlib/test/source/test_file_loader.py +++ b/Lib/importlib/test/source/test_file_loader.py @@ -1,5 +1,6 @@ from ... import _bootstrap import importlib +import importlib.abc from .. import abc from .. import util from . import util as source_util @@ -24,6 +25,40 @@ class SimpleTest(unittest.TestCase): """ + def test_load_module_API(self): + # If fullname is not specified that assume self.name is desired. + class TesterMixin(importlib.abc.Loader): + def load_module(self, fullname): return fullname + + class Tester(importlib.abc.FileLoader, TesterMixin): + def get_code(self, _): pass + def get_source(self, _): pass + def is_package(self, _): pass + + name = 'mod_name' + loader = Tester(name, 'some_path') + self.assertEqual(name, loader.load_module()) + self.assertEqual(name, loader.load_module(None)) + self.assertEqual(name, loader.load_module(name)) + with self.assertRaises(ImportError): + loader.load_module(loader.name + 'XXX') + + def test_get_filename_API(self): + # If fullname is not set then assume self.path is desired. + class Tester(importlib.abc.FileLoader): + def get_code(self, _): pass + def get_source(self, _): pass + def is_package(self, _): pass + + path = 'some_path' + name = 'some_name' + loader = Tester(name, path) + self.assertEqual(path, loader.get_filename(name)) + self.assertEqual(path, loader.get_filename()) + self.assertEqual(path, loader.get_filename(None)) + with self.assertRaises(ImportError): + loader.get_filename(name + 'XXX') + # [basic] def test_module(self): with source_util.create_modules('_temp') as mapping: diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py index 5b285fc..3f419b7 100644 --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -1,11 +1,12 @@ import imp +import importlib import os import os.path import shutil import sys -import unittest from test import support -import importlib +import unittest +import warnings class LockTests(unittest.TestCase): @@ -154,18 +155,24 @@ class ImportTests(unittest.TestCase): mod = imp.load_module(temp_mod_name, file, filename, info) self.assertEqual(mod.a, 1) - mod = imp.load_source(temp_mod_name, temp_mod_name + '.py') + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + mod = imp.load_source(temp_mod_name, temp_mod_name + '.py') self.assertEqual(mod.a, 1) - mod = imp.load_compiled( - temp_mod_name, imp.cache_from_source(temp_mod_name + '.py')) + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + mod = imp.load_compiled( + temp_mod_name, imp.cache_from_source(temp_mod_name + '.py')) self.assertEqual(mod.a, 1) if not os.path.exists(test_package_name): os.mkdir(test_package_name) with open(init_file_name, 'w') as file: file.write('b = 2\n') - package = imp.load_package(test_package_name, test_package_name) + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + package = imp.load_package(test_package_name, test_package_name) self.assertEqual(package.b, 2) finally: del sys.path[0] diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py index bc2672d..cbe6d80 100644 --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -6,7 +6,7 @@ Tools directory of a Python checkout or tarball, such as reindent.py. import os import sys -import imp +import importlib.machinery import unittest from unittest import mock import sysconfig @@ -80,7 +80,8 @@ class PdepsTests(unittest.TestCase): @classmethod def setUpClass(self): path = os.path.join(scriptsdir, 'pdeps.py') - self.pdeps = imp.load_source('pdeps', path) + loader = importlib.machinery.SourceFileLoader('pdeps', path) + self.pdeps = loader.load_module() @classmethod def tearDownClass(self): @@ -104,7 +105,8 @@ class Gprof2htmlTests(unittest.TestCase): def setUp(self): path = os.path.join(scriptsdir, 'gprof2html.py') - self.gprof = imp.load_source('gprof2html', path) + loader = importlib.machinery.SourceFileLoader('gprof2html', path) + self.gprof = loader.load_module() oldargv = sys.argv def fixup(): sys.argv = oldargv |