.. versionchanged:: 3.7
Introduced the optional :meth:`get_resource_reader` method.
+ .. versionchanged:: 3.15
+ Removed the ``load_module()`` method.
+
.. method:: create_module(spec)
A method that returns the module object to use when
.. versionchanged:: 3.6
:meth:`create_module` must also be defined.
- .. method:: load_module(fullname)
-
- A legacy method for loading a module. If the module cannot be
- loaded, :exc:`ImportError` is raised, otherwise the loaded module is
- returned.
-
- If the requested module already exists in :data:`sys.modules`, that
- module should be used and reloaded.
- Otherwise the loader should create a new module and insert it into
- :data:`sys.modules` before any loading begins, to prevent recursion
- from the import. If the loader inserted a module and the load fails, it
- must be removed by the loader from :data:`sys.modules`; modules already
- in :data:`sys.modules` before the loader began execution should be left
- alone.
-
- The loader should set several attributes on the module
- (note that some of these attributes can change when a module is
- reloaded):
-
- - :attr:`module.__name__`
- - :attr:`module.__file__`
- - :attr:`module.__cached__` *(deprecated)*
- - :attr:`module.__path__`
- - :attr:`module.__package__` *(deprecated)*
- - :attr:`module.__loader__` *(deprecated)*
-
- When :meth:`exec_module` is available then backwards-compatible
- functionality is provided.
-
- .. versionchanged:: 3.4
- Raise :exc:`ImportError` when called instead of
- :exc:`NotImplementedError`. Functionality provided when
- :meth:`exec_module` is available.
-
- .. deprecated-removed:: 3.4 3.15
- The recommended API for loading a module is :meth:`exec_module`
- (and :meth:`create_module`). Loaders should implement it instead of
- :meth:`load_module`. The import machinery takes care of all the
- other responsibilities of :meth:`load_module` when
- :meth:`exec_module` is implemented.
-
.. class:: ResourceLoader
.. versionadded:: 3.4
- .. method:: load_module(fullname)
-
- Implementation of :meth:`Loader.load_module`.
-
- .. deprecated-removed:: 3.4 3.15
- use :meth:`exec_module` instead.
-
.. class:: ExecutionLoader
.. versionadded:: 3.3
+ .. versionchanged:: 3.15
+ Removed the ``load_module()`` method.
+
.. attribute:: name
The name of the module the loader can handle.
Path to the file of the module.
- .. method:: load_module(fullname)
-
- Calls super's ``load_module()``.
-
- .. deprecated-removed:: 3.4 3.15
- Use :meth:`Loader.exec_module` instead.
-
.. method:: get_filename(fullname)
:abstractmethod:
optimization to speed up loading by removing the parsing step of Python's
compiler, and so no bytecode-specific API is exposed.
+ .. versionchanged:: 3.15
+ Removed the ``load_module()`` method.
+
.. method:: path_stats(path)
Optional abstract method which returns a :class:`dict` containing
.. versionadded:: 3.4
- .. method:: load_module(fullname)
-
- Concrete implementation of :meth:`Loader.load_module`.
-
- .. deprecated-removed:: 3.4 3.15
- Use :meth:`exec_module` instead.
-
.. method:: get_source(fullname)
Concrete implementation of :meth:`InspectLoader.get_source`.
.. versionadded:: 3.3
+ .. versionchanged:: 3.15
+ Removed the ``load_module()`` method.
+
.. attribute:: name
The name of the module that this loader will handle.
Concrete implementation of :meth:`importlib.abc.SourceLoader.set_data`.
- .. method:: load_module(name=None)
-
- Concrete implementation of :meth:`importlib.abc.Loader.load_module` where
- specifying the name of the module to load is optional.
-
- .. deprecated-removed:: 3.6 3.15
-
- Use :meth:`importlib.abc.Loader.exec_module` instead.
-
.. class:: SourcelessFileLoader(fullname, path)
.. versionadded:: 3.3
+ .. versionchanged:: 3.15
+ Removed the ``load_module()`` method.
+
.. attribute:: name
The name of the module the loader will handle.
Returns ``None`` as bytecode files have no source when this loader is
used.
- .. method:: load_module(name=None)
-
- Concrete implementation of :meth:`importlib.abc.Loader.load_module` where
- specifying the name of the module to load is optional.
-
- .. deprecated-removed:: 3.6 3.15
-
- Use :meth:`importlib.abc.Loader.exec_module` instead.
-
.. class:: ExtensionFileLoader(fullname, path)
if spec.loader is None:
# unsupported
raise ImportError
- if spec.origin is None and spec.submodule_search_locations is not None:
- # namespace package
- sys.modules[spec.name] = module
- elif not hasattr(spec.loader, 'exec_module'):
- module = spec.loader.load_module(spec.name)
- else:
- sys.modules[spec.name] = module
+
+ sys.modules[spec.name] = module
+ try:
+ spec.loader.exec_module(module)
+ except BaseException:
try:
- spec.loader.exec_module(module)
- except BaseException:
- try:
- del sys.modules[spec.name]
- except KeyError:
- pass
- raise
+ del sys.modules[spec.name]
+ except KeyError:
+ pass
+ raise
return sys.modules[spec.name]
Note the following details:
.. versionchanged:: 3.4
The import system has taken over the boilerplate responsibilities of
loaders. These were previously performed by the
- :meth:`importlib.abc.Loader.load_module` method.
+ ``importlib.abc.Loader.load_module`` method.
+
+.. versionchanged:: 3.15
+ The ``load_module`` method is no longer used.
Loaders
-------
The :meth:`~importlib.abc.Loader.create_module` method of loaders.
.. versionchanged:: 3.4
- The :meth:`~importlib.abc.Loader.load_module` method was replaced by
+ The ``importlib.abc.Loader.load_module`` method was replaced by
:meth:`~importlib.abc.Loader.exec_module` and the import
machinery assumed all the boilerplate responsibilities of loading.
compatibility. Specifically,
:meth:`!find_loader`/:meth:`!find_module`
(superseded by :meth:`~importlib.abc.MetaPathFinder.find_spec`),
- :meth:`~importlib.abc.Loader.load_module`
+ ``importlib.abc.Loader.load_module``
(superseded by :meth:`~importlib.abc.Loader.exec_module`),
:meth:`!module_repr` (which the import system
takes care of for you), the ``__package__`` attribute
preference for :meth:`~zipimport.zipimporter.exec_module`.
(Contributed by Brett Cannon in :issue:`26131`.)
-* The use of :meth:`~importlib.abc.Loader.load_module` by the import
+* The use of ``importlib.abc.Loader.load_module`` by the import
system now triggers an :exc:`ImportWarning` as
:meth:`~importlib.abc.Loader.exec_module` is preferred.
(Contributed by Brett Cannon in :issue:`26131`.)
:meth:`!importlib.abc.PathEntryFinder.find_loader` and
:meth:`!find_module` are replaced by
:meth:`importlib.abc.PathEntryFinder.find_spec`; all of the :samp:`{xxx}Loader` ABC
- ``load_module`` methods (:meth:`!importlib.abc.Loader.load_module`,
- :meth:`!importlib.abc.InspectLoader.load_module`,
- :meth:`!importlib.abc.FileLoader.load_module`,
- :meth:`!importlib.abc.SourceLoader.load_module`) should no longer be
+ ``load_module`` methods (``importlib.abc.Loader.load_module``,
+ ``importlib.abc.InspectLoader.load_module``,
+ ``importlib.abc.FileLoader.load_module``,
+ ``importlib.abc.SourceLoader.load_module``) should no longer be
implemented, instead loaders should implement an
``exec_module`` method
(:meth:`importlib.abc.Loader.exec_module`,
importlib
~~~~~~~~~
-The :meth:`importlib.machinery.SourceFileLoader.load_module` and
-:meth:`importlib.machinery.SourcelessFileLoader.load_module` methods
+The ``importlib.machinery.SourceFileLoader.load_module`` and
+``importlib.machinery.SourcelessFileLoader.load_module`` methods
are now deprecated. They were the only remaining implementations of
-:meth:`importlib.abc.Loader.load_module` in :mod:`importlib` that had not
+``importlib.abc.Loader.load_module`` in :mod:`importlib` that had not
been deprecated in previous versions of Python in favour of
:meth:`importlib.abc.Loader.exec_module`.
# We don't define exec_module() here since that would break
# hasattr checks we do to support backward compatibility.
-
- def load_module(self, fullname):
- """Return the loaded module.
-
- The module must be added to sys.modules and have import-related
- attributes set properly. The fullname is a str.
-
- ImportError is raised on failure.
-
- This method is deprecated in favor of loader.exec_module(). If
- exec_module() exists then it is used to provide a backwards-compatible
- functionality for this method.
-
- """
- if not hasattr(self, 'exec_module'):
- raise ImportError
- # Warning implemented in _load_module_shim().
- return _bootstrap._load_module_shim(self, fullname)
return _requires_frozen_wrapper
-# Typically used by loader classes as a method replacement.
-def _load_module_shim(self, fullname):
- """Load the specified module into sys.modules and return it.
-
- This method is deprecated. Use loader.exec_module() instead.
-
- """
- msg = ("the load_module() method is deprecated and slated for removal in "
- "Python 3.15; use exec_module() instead")
- _warnings.warn(msg, DeprecationWarning)
- spec = spec_from_loader(fullname, self)
- if fullname in sys.modules:
- module = sys.modules[fullname]
- _exec(spec, module)
- return sys.modules[fullname]
- else:
- return _load(spec)
-
# Module specifications #######################################################
def _module_repr(module):
# should also be None for consistency. While a bit of a hack,
# this is the best place to ensure this consistency.
#
- # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module
- # and bpo-32305
+ # See bpo-32305
module.__file__ = None
try:
module.__loader__ = loader
return f'<module {spec.name!r} ({spec.origin})>'
-# Used by importlib.reload() and _load_module_shim().
+# Used by importlib.reload().
def _exec(spec, module):
"""Execute the spec's specified module in an existing module's namespace."""
name = spec.name
_init_module_attrs(spec, module, override=True)
else:
_init_module_attrs(spec, module, override=True)
- if not hasattr(spec.loader, 'exec_module'):
- msg = (f"{_object_name(spec.loader)}.exec_module() not found; "
- "falling back to load_module()")
- _warnings.warn(msg, ImportWarning)
- spec.loader.load_module(name)
- else:
- spec.loader.exec_module(module)
+ spec.loader.exec_module(module)
finally:
# Update the order of insertion into sys.modules for module
# clean-up at shutdown.
sys.modules[spec.name] = module
return module
-
-def _load_backward_compatible(spec):
- # It is assumed that all callers have been warned about using load_module()
- # appropriately before calling this function.
- try:
- spec.loader.load_module(spec.name)
- except:
- if spec.name in sys.modules:
- module = sys.modules.pop(spec.name)
- sys.modules[spec.name] = module
- raise
- # The module must be in sys.modules at this point!
- # Move it to the end of sys.modules.
- module = sys.modules.pop(spec.name)
- sys.modules[spec.name] = module
- if getattr(module, '__loader__', None) is None:
- try:
- module.__loader__ = spec.loader
- except AttributeError:
- pass
- if getattr(module, '__package__', None) is None:
- try:
- # Since module.__path__ may not line up with
- # spec.submodule_search_paths, we can't necessarily rely
- # on spec.parent here.
- module.__package__ = module.__name__
- if not hasattr(module, '__path__'):
- module.__package__ = spec.name.rpartition('.')[0]
- except AttributeError:
- pass
- if getattr(module, '__spec__', None) is None:
- try:
- module.__spec__ = spec
- except AttributeError:
- pass
- return module
-
def _load_unlocked(spec):
# A helper for direct use by the import system.
- if spec.loader is not None:
- # Not a namespace package.
- if not hasattr(spec.loader, 'exec_module'):
- msg = (f"{_object_name(spec.loader)}.exec_module() not found; "
- "falling back to load_module()")
- _warnings.warn(msg, ImportWarning)
- return _load_backward_compatible(spec)
-
module = module_from_spec(spec)
# This must be done before putting the module in sys.modules
return module
-# A method used during testing of _load_unlocked() and by
-# _load_module_shim().
+# A method used during testing of _load_unlocked().
def _load(spec):
"""Return a new module object, loaded by the spec's loader.
"""Return False as built-in modules are never packages."""
return False
- load_module = classmethod(_load_module_shim)
-
class FrozenImporter:
code = _call_with_frames_removed(_imp.get_frozen_object, name)
exec(code, module.__dict__)
- @classmethod
- def load_module(cls, fullname):
- """Load a frozen module.
-
- This method is deprecated. Use exec_module() instead.
-
- """
- # Warning about deprecation implemented in _load_module_shim().
- module = _load_module_shim(cls, fullname)
- info = _imp.find_frozen(fullname)
- assert info is not None
- _, ispkg, origname = info
- module.__origname__ = origname
- vars(module).pop('__file__', None)
- if ispkg:
- module.__path__ = []
- cls._fix_up_module(module)
- return module
-
@classmethod
@_requires_frozen
def get_code(cls, fullname):
'get_code() returns None')
_bootstrap._call_with_frames_removed(exec, code, module.__dict__)
- def load_module(self, fullname):
- """This method is deprecated."""
- # Warning implemented in _load_module_shim().
- return _bootstrap._load_module_shim(self, fullname)
-
class SourceLoader(_LoaderBasics):
def __hash__(self):
return hash(self.name) ^ hash(self.path)
- @_check_name
- def load_module(self, fullname):
- """Load a module from a file.
-
- This method is deprecated. Use exec_module() instead.
-
- """
- # The only reason for this method is for the name check.
- # Issue #14857: Avoid the zero-argument form of super so the implementation
- # of that form can be updated without breaking the frozen module.
- return super(FileLoader, self).load_module(fullname)
-
@_check_name
def get_filename(self, fullname):
"""Return the path to the source file as found by the finder."""
def exec_module(self, module):
pass
- def load_module(self, fullname):
- """Load a namespace module.
-
- This method is deprecated. Use exec_module() instead.
-
- """
- # The import system never calls this method.
- _bootstrap._verbose_message('namespace module loaded with path {!r}',
- self._path)
- # Warning implemented in _load_module_shim().
- return _bootstrap._load_module_shim(self, fullname)
-
def get_resource_reader(self, module):
from importlib.readers import NamespaceReader
return NamespaceReader(self._path)
return compile(data, path, 'exec', dont_inherit=True, module=fullname)
exec_module = _bootstrap_external._LoaderBasics.exec_module
- load_module = _bootstrap_external._LoaderBasics.load_module
_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter, machinery.NamespaceLoader)
# away from the traceback.
self.create_module("foo", "")
importlib = sys.modules['_frozen_importlib_external']
- if 'load_module' in vars(importlib.SourceLoader):
- old_exec_module = importlib.SourceLoader.exec_module
- else:
- old_exec_module = None
try:
def exec_module(*args):
1/0
self.fail("ZeroDivisionError should have been raised")
self.assert_traceback(tb, [__file__, '<frozen importlib', __file__])
finally:
- if old_exec_module is None:
- del importlib.SourceLoader.exec_module
- else:
- importlib.SourceLoader.exec_module = old_exec_module
+ del importlib.SourceLoader.exec_module
@unittest.skipUnless(TESTFN_UNENCODABLE, 'need TESTFN_UNENCODABLE')
def test_unencodable_filename(self):
# This is essentially copied from the old imp module.
from importlib._bootstrap import _load
loader = self.LOADER(name, path)
-
- # Issue bpo-24748: Skip the sys.modules check in _load_module_shim;
- # always load new extension.
spec = importlib.util.spec_from_file_location(name, path,
loader=loader)
return _load(spec)
class LoaderTests(metaclass=abc.ABCMeta):
- @abc.abstractmethod
- def test_module(self):
- """A module should load without issue.
-
- After the loader returns the module should be in sys.modules.
-
- Attributes to verify:
-
- * __file__
- * __loader__
- * __name__
- * No __path__
-
- """
- pass
-
@abc.abstractmethod
def test_package(self):
"""Loading a package should work.
import unittest
import warnings
-@unittest.skipIf(util.BUILTINS.good_name is None, 'no reasonable builtin module')
-class LoaderTests(abc.LoaderTests):
-
- """Test load_module() for built-in modules."""
-
- def setUp(self):
- self.verification = {'__name__': 'errno', '__package__': '',
- '__loader__': self.machinery.BuiltinImporter}
-
- def verify(self, module):
- """Verify that the module matches against what it should have."""
- self.assertIsInstance(module, types.ModuleType)
- for attr, value in self.verification.items():
- self.assertEqual(getattr(module, attr), value)
- self.assertIn(module.__name__, sys.modules)
-
- def load_module(self, name):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- return self.machinery.BuiltinImporter.load_module(name)
-
- def test_module(self):
- # Common case.
- with util.uncache(util.BUILTINS.good_name):
- module = self.load_module(util.BUILTINS.good_name)
- self.verify(module)
-
- # Built-in modules cannot be a package.
- test_package = test_lacking_parent = None
-
- # No way to force an import failure.
- test_state_after_failure = None
-
- def test_module_reuse(self):
- # Test that the same module is used in a reload.
- with util.uncache(util.BUILTINS.good_name):
- module1 = self.load_module(util.BUILTINS.good_name)
- module2 = self.load_module(util.BUILTINS.good_name)
- self.assertIs(module1, module2)
-
- def test_unloadable(self):
- name = 'dssdsdfff'
- assert name not in sys.builtin_module_names
- with self.assertRaises(ImportError) as cm:
- self.load_module(name)
- self.assertEqual(cm.exception.name, name)
-
- def test_already_imported(self):
- # Using the name of a module already imported but not a built-in should
- # still fail.
- module_name = 'builtin_reload_test'
- assert module_name not in sys.builtin_module_names
- with util.uncache(module_name):
- module = types.ModuleType(module_name)
- sys.modules[module_name] = module
- with self.assertRaises(ImportError) as cm:
- self.load_module(module_name)
- self.assertEqual(cm.exception.name, module_name)
-
-
-(Frozen_LoaderTests,
- Source_LoaderTests
- ) = util.test_both(LoaderTests, machinery=machinery)
-
@unittest.skipIf(util.BUILTINS.good_name is None, 'no reasonable builtin module')
class InspectLoaderTests:
self.loader = self.LoaderClass(util.EXTENSIONS.name, util.EXTENSIONS.file_path)
- def load_module(self, fullname):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- return self.loader.load_module(fullname)
-
def test_equality(self):
other = self.LoaderClass(util.EXTENSIONS.name, util.EXTENSIONS.file_path)
self.assertEqual(self.loader, other)
other = self.LoaderClass('_' + util.EXTENSIONS.name, util.EXTENSIONS.file_path)
self.assertNotEqual(self.loader, other)
- def test_load_module_API(self):
- # Test the default argument for load_module().
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- self.loader.load_module()
- self.loader.load_module(None)
- with self.assertRaises(ImportError):
- self.load_module('XXX')
-
- def test_module(self):
- with util.uncache(util.EXTENSIONS.name):
- module = self.load_module(util.EXTENSIONS.name)
- for attr, value in [('__name__', util.EXTENSIONS.name),
- ('__file__', util.EXTENSIONS.file_path),
- ('__package__', '')]:
- self.assertEqual(getattr(module, attr), value)
- self.assertIn(util.EXTENSIONS.name, sys.modules)
- self.assertIsInstance(module.__loader__, self.LoaderClass)
-
# No extension module as __init__ available for testing.
test_package = None
# No easy way to trigger a failure after a successful import.
test_state_after_failure = None
- def test_unloadable(self):
- name = 'asdfjkl;'
- with self.assertRaises(ImportError) as cm:
- self.load_module(name)
- self.assertEqual(cm.exception.name, name)
-
- def test_module_reuse(self):
- with util.uncache(util.EXTENSIONS.name):
- module1 = self.load_module(util.EXTENSIONS.name)
- module2 = self.load_module(util.EXTENSIONS.name)
- self.assertIs(module1, module2)
-
def test_is_package(self):
self.assertFalse(self.loader.is_package(util.EXTENSIONS.name))
for suffix in self.machinery.EXTENSION_SUFFIXES:
self.loader = self.LoaderClass(self.name, self.spec.origin)
- def load_module(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- return self.loader.load_module(self.name)
-
def load_module_by_name(self, fullname):
# Load a module from the test extension by name.
origin = self.spec.origin
loader.exec_module(module)
return module
- def test_module(self):
- # Test loading an extension module.
- with util.uncache(self.name):
- module = self.load_module()
- for attr, value in [('__name__', self.name),
- ('__file__', self.spec.origin),
- ('__package__', '')]:
- self.assertEqual(getattr(module, attr), value)
- with self.assertRaises(AttributeError):
- module.__path__
- self.assertIs(module, sys.modules[self.name])
- self.assertIsInstance(module.__loader__, self.LoaderClass)
-
# No extension module as __init__ available for testing.
test_package = None
assert self.spec
self.loader = self.LoaderClass(self.name, self.spec.origin)
- def load_module(self):
- # Load the module from the test extension.
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- return self.loader.load_module(self.name)
-
def load_module_by_name(self, fullname):
# Load a module from the test extension by name.
origin = self.spec.origin
# Handling failure on reload is the up to the module.
test_state_after_failure = None
- def test_module(self):
- # Test loading an extension module.
- with util.uncache(self.name):
- module = self.load_module()
- for attr, value in [('__name__', self.name),
- ('__file__', self.spec.origin),
- ('__package__', '')]:
- self.assertEqual(getattr(module, attr), value)
- with self.assertRaises(AttributeError):
- module.__path__
- self.assertIs(module, sys.modules[self.name])
- self.assertIsInstance(module.__loader__, self.LoaderClass)
-
- def test_functionality(self):
- # Test basic functionality of stuff defined in an extension module.
- with util.uncache(self.name):
- module = self.load_module()
- self.assertIsInstance(module, types.ModuleType)
- ex = module.Example()
- self.assertEqual(ex.demo('abcd'), 'abcd')
- self.assertEqual(ex.demo(), None)
- with self.assertRaises(AttributeError):
- ex.abc
- ex.abc = 0
- self.assertEqual(ex.abc, 0)
- self.assertEqual(module.foo(9, 9), 18)
- self.assertIsInstance(module.Str(), str)
- self.assertEqual(module.Str(1) + '23', '123')
- with self.assertRaises(module.error):
- raise module.error()
- self.assertEqual(module.int_const, 1969)
- self.assertEqual(module.str_const, 'something different')
-
- def test_reload(self):
- # Test that reload didn't re-set the module's attributes.
- with util.uncache(self.name):
- module = self.load_module()
- ex_class = module.Example
- importlib.reload(module)
- self.assertIs(ex_class, module.Example)
-
- def test_try_registration(self):
- # Assert that the PyState_{Find,Add,Remove}Module C API doesn't work.
- with util.uncache(self.name):
- module = self.load_module()
- with self.subTest('PyState_FindModule'):
- self.assertEqual(module.call_state_registration_func(0), None)
- with self.subTest('PyState_AddModule'):
- with self.assertRaises(SystemError):
- module.call_state_registration_func(1)
- with self.subTest('PyState_RemoveModule'):
- with self.assertRaises(SystemError):
- module.call_state_registration_func(2)
-
def test_load_submodule(self):
# Test loading a simulated submodule.
module = self.load_module_by_name('pkg.' + self.name)
raise ImportError('I cannot be loaded!')
-class BadLoaderFinder:
- @classmethod
- def load_module(cls, fullname):
- if fullname == SUBMOD_NAME:
- raise ImportError('I cannot be loaded!')
-
-
class APITest:
"""Test API-specific details for __import__ (e.g. raising the right
self.assertEqual(cm.exception.name, SUBMOD_NAME)
-class OldAPITests(APITest):
- bad_finder_loader = BadLoaderFinder
-
- def test_raises_ModuleNotFoundError(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- super().test_raises_ModuleNotFoundError()
-
- def test_name_requires_rparition(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- super().test_name_requires_rparition()
-
- def test_negative_level(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- super().test_negative_level()
-
- def test_nonexistent_fromlist_entry(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- super().test_nonexistent_fromlist_entry()
-
- def test_fromlist_load_error_propagates(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- super().test_fromlist_load_error_propagates
-
- def test_blocked_fromlist(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- super().test_blocked_fromlist()
-
-
-(Frozen_OldAPITests,
- Source_OldAPITests
- ) = util.test_both(OldAPITests, __import__=util.__import__)
-
-
class SpecAPITests(APITest):
bad_finder_loader = BadSpecFinderLoader
from test.test_py_compile import SourceDateEpochTestMeta
-class SimpleTest(abc.LoaderTests):
+class SimpleTest:
"""Should have no issue importing a source module [basic]. And if there is
a syntax error, it should raise a SyntaxError [syntax error].
self.filepath = os.path.join('ham', self.name + '.py')
self.loader = self.machinery.SourceFileLoader(self.name, self.filepath)
- def test_load_module_API(self):
- class Tester(self.abc.FileLoader):
- def get_source(self, _): return 'attr = 42'
- def is_package(self, _): return False
-
- loader = Tester('blah', 'blah.py')
- self.addCleanup(unload, 'blah')
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module() # Should not raise an exception.
-
def test_get_filename_API(self):
# If fullname is not set then assume self.path is desired.
class Tester(self.abc.FileLoader):
other = self.machinery.SourceFileLoader('_' + self.name, self.filepath)
self.assertNotEqual(self.loader, other)
- # [basic]
- def test_module(self):
- with util.create_modules('_temp') as mapping:
- loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module('_temp')
- self.assertIn('_temp', sys.modules)
- check = {'__name__': '_temp', '__file__': mapping['_temp'],
- '__package__': ''}
- for attr, value in check.items():
- self.assertEqual(getattr(module, attr), value)
-
- def test_package(self):
- with util.create_modules('_pkg.__init__') as mapping:
- loader = self.machinery.SourceFileLoader('_pkg',
- mapping['_pkg.__init__'])
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module('_pkg')
- self.assertIn('_pkg', sys.modules)
- check = {'__name__': '_pkg', '__file__': mapping['_pkg.__init__'],
- '__path__': [os.path.dirname(mapping['_pkg.__init__'])],
- '__package__': '_pkg'}
- for attr, value in check.items():
- self.assertEqual(getattr(module, attr), value)
-
-
- def test_lacking_parent(self):
- with util.create_modules('_pkg.__init__', '_pkg.mod')as mapping:
- loader = self.machinery.SourceFileLoader('_pkg.mod',
- mapping['_pkg.mod'])
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module('_pkg.mod')
- self.assertIn('_pkg.mod', sys.modules)
- check = {'__name__': '_pkg.mod', '__file__': mapping['_pkg.mod'],
- '__package__': '_pkg'}
- for attr, value in check.items():
- self.assertEqual(getattr(module, attr), value)
def fake_mtime(self, fxn):
"""Fake mtime to always be higher than expected."""
return lambda name: fxn(name) + 1
- def test_module_reuse(self):
- with util.create_modules('_temp') as mapping:
- loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module('_temp')
- module_id = id(module)
- module_dict_id = id(module.__dict__)
- with open(mapping['_temp'], 'w', encoding='utf-8') as file:
- file.write("testing_var = 42\n")
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module('_temp')
- self.assertIn('testing_var', module.__dict__,
- "'testing_var' not in "
- "{0}".format(list(module.__dict__.keys())))
- self.assertEqual(module, sys.modules['_temp'])
- self.assertEqual(id(module), module_id)
- self.assertEqual(id(module.__dict__), module_dict_id)
-
- def test_state_after_failure(self):
- # A failed reload should leave the original module intact.
- attributes = ('__file__', '__path__', '__package__')
- value = '<test>'
- name = '_temp'
- with util.create_modules(name) as mapping:
- orig_module = types.ModuleType(name)
- for attr in attributes:
- setattr(orig_module, attr, value)
- with open(mapping[name], 'w', encoding='utf-8') as file:
- file.write('+++ bad syntax +++')
- loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
- with self.assertRaises(SyntaxError):
- loader.exec_module(orig_module)
- for attr in attributes:
- self.assertEqual(getattr(orig_module, attr), value)
- with self.assertRaises(SyntaxError):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- loader.load_module(name)
- for attr in attributes:
- self.assertEqual(getattr(orig_module, attr), value)
-
- # [syntax error]
- def test_bad_syntax(self):
- with util.create_modules('_temp') as mapping:
- with open(mapping['_temp'], 'w', encoding='utf-8') as file:
- file.write('=')
- loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
- with self.assertRaises(SyntaxError):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- loader.load_module('_temp')
- self.assertNotIn('_temp', sys.modules)
-
- def test_file_from_empty_string_dir(self):
- # Loading a module found from an empty string entry on sys.path should
- # not only work, but keep all attributes relative.
- file_path = '_temp.py'
- with open(file_path, 'w', encoding='utf-8') as file:
- file.write("# test file for importlib")
- try:
- with util.uncache('_temp'):
- loader = self.machinery.SourceFileLoader('_temp', file_path)
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- mod = loader.load_module('_temp')
- self.assertEqual(file_path, mod.__file__)
- self.assertEqual(self.util.cache_from_source(file_path),
- mod.__cached__)
- finally:
- os.unlink(file_path)
- pycache = os.path.dirname(self.util.cache_from_source(file_path))
- if os.path.exists(pycache):
- shutil.rmtree(pycache)
-
- @util.writes_bytecode_files
- def test_timestamp_overflow(self):
- # When a modification timestamp is larger than 2**32, it should be
- # truncated rather than raise an OverflowError.
- with util.create_modules('_temp') as mapping:
- source = mapping['_temp']
- compiled = self.util.cache_from_source(source)
- with open(source, 'w', encoding='utf-8') as f:
- f.write("x = 5")
- try:
- os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5))
- except OverflowError:
- self.skipTest("cannot set modification time to large integer")
- except OSError as e:
- if e.errno != getattr(errno, 'EOVERFLOW', None):
- raise
- self.skipTest("cannot set modification time to large integer ({})".format(e))
- loader = self.machinery.SourceFileLoader('_temp', mapping['_temp'])
- # PEP 451
- module = types.ModuleType('_temp')
- module.__spec__ = self.util.spec_from_loader('_temp', loader)
- loader.exec_module(module)
- self.assertEqual(module.x, 5)
- self.assertTrue(os.path.exists(compiled))
- os.unlink(compiled)
- # PEP 302
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- mod = loader.load_module('_temp')
- # Sanity checks.
- self.assertEqual(mod.__cached__, compiled)
- self.assertEqual(mod.x, 5)
- # The pyc file was created.
- self.assertTrue(os.path.exists(compiled))
-
- def test_unloadable(self):
- loader = self.machinery.SourceFileLoader('good name', {})
- module = types.ModuleType('bad name')
- module.__spec__ = self.machinery.ModuleSpec('bad name', loader)
- with self.assertRaises(ImportError):
- loader.exec_module(module)
- with self.assertRaises(ImportError):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- loader.load_module('bad name')
-
@util.writes_bytecode_files
def test_checked_hash_based_pyc(self):
with util.create_modules('_temp') as mapping:
loader.exec_module(module)
-class BadBytecodeTestPEP302(BadBytecodeTest):
-
- def import_(self, file, module_name):
- loader = self.loader(module_name, file)
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = loader.load_module(module_name)
- self.assertIn(module_name, sys.modules)
-
-
class SourceLoaderBadBytecodeTest:
@classmethod
util=importlib_util)
-class SourceLoaderBadBytecodeTestPEP302(
- SourceLoaderBadBytecodeTest, BadBytecodeTestPEP302):
- pass
-
-
-(Frozen_SourceBadBytecodePEP302,
- Source_SourceBadBytecodePEP302
- ) = util.test_both(SourceLoaderBadBytecodeTestPEP302, importlib=importlib,
- machinery=machinery, abc=importlib_abc,
- util=importlib_util)
-
-
class SourcelessLoaderBadBytecodeTest:
@classmethod
util=importlib_util)
-class SourcelessLoaderBadBytecodeTestPEP302(SourcelessLoaderBadBytecodeTest,
- BadBytecodeTestPEP302):
- pass
-
-
-(Frozen_SourcelessBadBytecodePEP302,
- Source_SourcelessBadBytecodePEP302
- ) = util.test_both(SourcelessLoaderBadBytecodeTestPEP302, importlib=importlib,
- machinery=machinery, abc=importlib_abc,
- util=importlib_util)
-
-
if __name__ == '__main__':
unittest.main()
if error.errno != errno.ENOENT:
raise
loader = self.import_(mapping['.root'], test)
- self.assertHasAttr(loader, 'load_module')
+ self.assertHasAttr(loader, 'exec_module')
return loader
def test_module(self):
with util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
loader = self.import_(pkg_dir, 'pkg.sub')
- self.assertHasAttr(loader, 'load_module')
+ self.assertHasAttr(loader, 'exec_module')
# [sub package]
def test_package_in_package(self):
with context as mapping:
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
loader = self.import_(pkg_dir, 'pkg.sub')
- self.assertHasAttr(loader, 'load_module')
+ self.assertHasAttr(loader, 'exec_module')
# [package over modules]
def test_package_over_module(self):
file.write("# test file for importlib")
try:
loader = self._find(finder, 'mod', loader_only=True)
- self.assertHasAttr(loader, 'load_module')
+ self.assertHasAttr(loader, 'exec_module')
finally:
os.unlink('mod.py')
) = util.test_both(EncodingTestPEP451, machinery=machinery)
-class EncodingTestPEP302(EncodingTest):
-
- def load(self, loader):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- return loader.load_module(self.module_name)
-
-
-(Frozen_EncodingTestPEP302,
- Source_EncodingTestPEP302
- ) = util.test_both(EncodingTestPEP302, machinery=machinery)
-
-
class LineEndingTest:
r"""Source written with the three types of line endings (\n, \r\n, \r)
) = util.test_both(LineEndingTestPEP451, machinery=machinery)
-class LineEndingTestPEP302(LineEndingTest):
-
- def load(self, loader, module_name):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- return loader.load_module(module_name)
-
-
-(Frozen_LineEndingTestPEP302,
- Source_LineEndingTestPEP302
- ) = util.test_both(LineEndingTestPEP302, machinery=machinery)
-
-
if __name__ == '__main__':
unittest.main()
spec = 'a spec'
self.assertIsNone(self.ins.create_module(spec))
- def test_load_module(self):
- with self.assertRaises(ImportError):
- self.ins.load_module('something')
-
def test_module_repr(self):
mod = types.ModuleType('blah')
with warnings.catch_warnings():
return SpecLoader()
- def test_fresh(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- loader = self.loader()
- name = 'blah'
- with test_util.uncache(name):
- loader.load_module(name)
- module = loader.found
- self.assertIs(sys.modules[name], module)
- self.assertEqual(loader, module.__loader__)
- self.assertEqual(loader, module.__spec__.loader)
- self.assertEqual(name, module.__name__)
- self.assertEqual(name, module.__spec__.name)
- self.assertIsNotNone(module.__path__)
- self.assertIsNotNone(module.__path__,
- module.__spec__.submodule_search_locations)
-
- def test_reload(self):
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- name = 'blah'
- loader = self.loader()
- module = types.ModuleType(name)
- module.__spec__ = self.util.spec_from_loader(name, loader)
- module.__loader__ = loader
- with test_util.uncache(name):
- sys.modules[name] = module
- loader.load_module(name)
- found = loader.found
- self.assertIs(found, sys.modules[name])
- self.assertIs(module, sys.modules[name])
-
(Frozen_LoaderLoadModuleTests,
Source_LoaderLoadModuleTests
InspectLoaderSubclass=SPLIT_IL)
-class InspectLoaderLoadModuleTests:
-
- """Test InspectLoader.load_module()."""
-
- module_name = 'blah'
-
- def setUp(self):
- import_helper.unload(self.module_name)
- self.addCleanup(import_helper.unload, self.module_name)
-
- def load(self, loader):
- spec = self.util.spec_from_loader(self.module_name, loader)
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- return self.init._bootstrap._load_unlocked(spec)
-
- def mock_get_code(self):
- return mock.patch.object(self.InspectLoaderSubclass, 'get_code')
-
- def test_get_code_ImportError(self):
- # If get_code() raises ImportError, it should propagate.
- with self.mock_get_code() as mocked_get_code:
- mocked_get_code.side_effect = ImportError
- with self.assertRaises(ImportError):
- loader = self.InspectLoaderSubclass()
- self.load(loader)
-
- def test_get_code_None(self):
- # If get_code() returns None, raise ImportError.
- with self.mock_get_code() as mocked_get_code:
- mocked_get_code.return_value = None
- with self.assertRaises(ImportError):
- loader = self.InspectLoaderSubclass()
- self.load(loader)
-
- def test_module_returned(self):
- # The loaded module should be returned.
- code = compile('attr = 42', '<string>', 'exec')
- with self.mock_get_code() as mocked_get_code:
- mocked_get_code.return_value = code
- loader = self.InspectLoaderSubclass()
- module = self.load(loader)
- self.assertEqual(module, sys.modules[self.module_name])
-
-
-(Frozen_ILLoadModuleTests,
- Source_ILLoadModuleTests
- ) = test_util.test_both(InspectLoaderLoadModuleTests,
- InspectLoaderSubclass=SPLIT_IL,
- init=init,
- util=util)
-
-
##### ExecutionLoader concrete methods #########################################
class ExecutionLoaderGetCodeTests:
code = self.loader.source_to_code(self.loader.source, self.path)
self.verify_code(code)
- def test_load_module(self):
- # Loading a module should set __name__, __loader__, __package__,
- # __path__ (for packages), __file__, and __cached__.
- # The module should also be put into sys.modules.
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- with test_util.uncache(self.name):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = self.loader.load_module(self.name)
- self.verify_module(module)
- self.assertEqual(module.__path__, [os.path.dirname(self.path)])
- self.assertIn(self.name, sys.modules)
-
- def test_package_settings(self):
- # __package__ needs to be set, while __path__ is set on if the module
- # is a package.
- # Testing the values for a package are covered by test_load_module.
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- self.setUp(is_package=False)
- with test_util.uncache(self.name):
- with warnings.catch_warnings():
- warnings.simplefilter('ignore', DeprecationWarning)
- module = self.loader.load_module(self.name)
- self.verify_module(module)
- self.assertNotHasAttr(module, '__path__')
-
def test_get_source_encoding(self):
# Source is considered encoded in UTF-8 by default unless otherwise
# specified by an encoding line.
loaded = self.bootstrap._load(self.spec)
self.assertNotIn(self.spec.name, sys.modules)
- def test_load_legacy_attributes_immutable(self):
- module = object()
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", ImportWarning)
- class ImmutableLoader(TestLoader):
- def load_module(self, name):
- sys.modules[name] = module
- return module
- self.spec.loader = ImmutableLoader()
- with CleanImport(self.spec.name):
- loaded = self.bootstrap._load(self.spec)
-
- self.assertIs(sys.modules[self.spec.name], module)
-
# reload()
def test_reload(self):
.. nonce: jQ0CvW
.. section: Library
-Update the deprecation warning of :meth:`importlib.abc.Loader.load_module`.
+Update the deprecation warning of ``importlib.abc.Loader.load_module``.
..
--- /dev/null
+Remove all ``*.load_module()`` usage and definitions from the import system
+and importlib. The method has been deprecated in favor of
+``importlib.abc.Loader.exec_module()`` since Python 3.4.