ImportError.
The exception is raised by import when a module could not be found.
Technically this is defined as no viable loader could be found for the
specified module. This includes ``from ... import`` statements so that
the module usage is consistent for all situations where import
couldn't find what was requested.
This should allow for the common idiom of::
try:
import something
except ImportError:
pass
to be updated to using ModuleNotFoundError and not accidentally mask
ImportError messages that should propagate (e.g. issues with a
loader).
This work was driven by the fact that the ``from ... import``
statement needed to be able to tell the difference between an
ImportError that simply couldn't find a module (and thus silence the
exception so that ceval can raise it) and an ImportError that
represented an actual problem.
Previously __path__ was set to [__name__], but that could lead to bad
results if someone managed to circumvent the frozen importer and
somehow ended up with a finder that thought __name__ was a legit
directory/location.
importlib.abc.Loader.init_module_attrs() and implement
importlib.abc.InspectLoader.load_module().
The importlib.abc.Loader.init_module_attrs() method sets the various
attributes on the module being loaded. It is done unconditionally to
support reloading. Typically people used
importlib.util.module_for_loader, but since that's a decorator there
was no way to override it's actions, so init_module_attrs() came into
existence to allow for overriding. This is also why module_for_loader
is now pending deprecation (having its other use replaced by
importlib.util.module_to_load).
All of this allowed for importlib.abc.InspectLoader.load_module() to
be implemented. At this point you can now implement a loader with
nothing more than get_code() (which only requires get_source();
package support requires is_package()). Thanks to init_module_attrs()
the implementation of load_module() is basically a context manager
containing 2 methods calls, a call to exec(), and a return statement.
handle providing (and cleaning up if needed) the module to be loaded.
A future commit will use the context manager in
Lib/importlib/_bootstrap.py and thus why the code is placed there
instead of in Lib/importlib/util.py.
While the previous location was fine, it makes more sense to have the
method higher up in the inheritance chain, especially at a point where
get_source() is defined which is the earliest source_to_code() could
programmatically be used in the inheritance tree in importlib.abc.
attributes to None.
The long-term goal is for people to be able to rely on these
attributes existing and checking for None to see if they have been
set. Since import itself sets these attributes when a loader does not
the only instances when the attributes are None are from someone
overloading __import__() and not using a loader or someone creating a
module from scratch.
This patch also unifies module initialization. Before you could have
different attributes with default values depending on how the module
object was created. Now the only way to not get the same default set
of attributes is to circumvent initialization by calling
ModuleType.__new__() directly.
the default exception/value when called instead of raising/returning
NotimplementedError/NotImplemented (except where appropriate).
This should allow for the ABCs to act as the bottom/end of the MRO with expected
default results.
As part of this work, also make importlib.abc.Loader.module_repr()
optional instead of an abstractmethod.
__loader__ is not set on a module. This brings the exception in line
with when __loader__ is None (which is equivalent to not having the
attribute defined).
__loader__ for this test to succeed without a major changes. It also
doesn't test the original issue of modules imported by Py_Initialize()
having __loader__ set (the rest of the test covers that).
scratch. This means they do not set __loader__ by default. This is
acceptable under importlib/PEP 302 definitions, so relax the test that
was trying to apply this universally.
importlib.machinery.FileFinder when the directory has become
unreadable or a file. This brings semantics in line with Python 3.2
import.
Reported and diagnosed by David Pritchard.
fromlist of __import__ propagate.
The problem previously was that if something listed in fromlist didn't
exist then that's okay. The fix for that was too broad in terms of
catching ImportError.
The trick with the solution to this issue is that the proper
refactoring of import thanks to importlib doesn't allow for a way to
distinguish (portably) between an ImportError because finders couldn't
find a loader, or a loader raised the exception. In Python 3.4 the
hope is to introduce a new exception (e.g. ModuleNotFound) to make it
clean to differentiate why ImportError was raised.
state of the import system. Also make importlib.invalidate_caches()
work with sys.meta_path instead of sys.path_importer_cache to
completely separate the path-based import system from the overall
import system.
Patch by Eric Snow.