rewriting functionality in pure Python.
To start, imp.new_module() has been rewritten in pure Python, put into
importlib (privately) and then publicly exposed in imp.
of sys.modules when possible.
This is being done for two reasons. One is to gain a little bit of
performance by skipping an unnecessary dict lookup in sys.modules. But
the other (and main) reason is to be a little bit more clear in how
things should work from the perspective of import's interactions with
loaders. Otherwise loaders can easily forget to return the module even
though PEP 302 explicitly states they are expected to return the module
they loaded.
importlib._bootstrap is now frozen into Python/importlib.h and stored
as _frozen_importlib in sys.modules. Py_Initialize() loads the frozen
code along with sys and imp and then uses _frozen_importlib._install()
to set builtins.__import__() w/ _frozen_importlib.__import__().
importation, then respect that injection.
Discovered thanks to Lib/xml/parsers/expat.py injecting
xml.parsers.expat.errors and etree now importing that directly as a
module.
It seems better to cache the finder for the cwd under its full path
insetad of '' in case the cwd changes. Otherwise FileFinder needs to
dynamically change itself based on whether it is given '' instead of
caching a finder for every change to the cwd.
This required updating the code to use posix instead of os. This is
all being done to make bootstrapping easier to removing dependencies
that are kept in importlib.__init__ and thus outside of the single
file to bootstrap from.
paths.
__import__ does a little trick when importing from bytecode by
back-patching the co_filename paths to point to the file location
where the code object was loaded from, *not* where the code object was
originally created. This allows co_filename to point to a valid path.
Problem is that co_filename is immutable from Python, so a private
function -- imp._fix_co_filename() -- had to be introduced in order to
get things working properly. Originally the plan was to add a file
argument to marshal.loads(), but that failed as the algorithm used by
__import__ is not fully recursive as one might expect, so to be fully
backwards-compatible the code used by __import__ needed to be exposed.
This closes issue #6811 by taking a different approach than outlined
in the issue.