summaryrefslogtreecommitdiffstats
path: root/Lib/importlib
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2021-10-05 16:01:27 (GMT)
committerGitHub <noreply@github.com>2021-10-05 16:01:27 (GMT)
commitc3d9ac8b340fcbf54cee865737e67f11fcd70ed3 (patch)
tree71171709f9a44e02cca8ffee4a0fe2c49335b59a /Lib/importlib
parentb9bb74871b27d9226df2dd3fce9d42bda8b43c2b (diff)
downloadcpython-c3d9ac8b340fcbf54cee865737e67f11fcd70ed3.zip
cpython-c3d9ac8b340fcbf54cee865737e67f11fcd70ed3.tar.gz
cpython-c3d9ac8b340fcbf54cee865737e67f11fcd70ed3.tar.bz2
bpo-45324: Capture data in FrozenImporter.find_spec() to use in exec_module(). (gh-28633)
Before this change we end up duplicating effort and throwing away data in FrozenImporter.find_spec(). Now we do the work once in find_spec() and the only thing we do in FrozenImporter.exec_module() is turn the raw frozen data into a code object and then exec it. We've added _imp.find_frozen(), add an arg to _imp.get_frozen_object(), and updated FrozenImporter. We've also moved some code around to reduce duplication, get a little more consistency in outcomes, and be more efficient. Note that this change is mostly necessary if we want to set __file__ on frozen stdlib modules. (See https://bugs.python.org/issue21736.) https://bugs.python.org/issue45324
Diffstat (limited to 'Lib/importlib')
-rw-r--r--Lib/importlib/_bootstrap.py32
1 files changed, 24 insertions, 8 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index e64f7ad..5807577 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -826,10 +826,15 @@ class FrozenImporter:
@classmethod
def find_spec(cls, fullname, path=None, target=None):
- if _imp.is_frozen(fullname):
- return spec_from_loader(fullname, cls, origin=cls._ORIGIN)
- else:
+ info = _call_with_frames_removed(_imp.find_frozen, fullname)
+ if info is None:
return None
+ data, ispkg = info
+ spec = spec_from_loader(fullname, cls,
+ origin=cls._ORIGIN,
+ is_package=ispkg)
+ spec.loader_state = data
+ return spec
@classmethod
def find_module(cls, fullname, path=None):
@@ -849,11 +854,22 @@ class FrozenImporter:
@staticmethod
def exec_module(module):
- name = module.__spec__.name
- if not _imp.is_frozen(name):
- raise ImportError('{!r} is not a frozen module'.format(name),
- name=name)
- code = _call_with_frames_removed(_imp.get_frozen_object, name)
+ spec = module.__spec__
+ name = spec.name
+ try:
+ data = spec.loader_state
+ except AttributeError:
+ if not _imp.is_frozen(name):
+ raise ImportError('{!r} is not a frozen module'.format(name),
+ name=name)
+ data = None
+ else:
+ # We clear the extra data we got from the finder, to save memory.
+ # Note that if this method is called again (e.g. by
+ # importlib.reload()) then _imp.get_frozen_object() will notice
+ # no data was provided and will look it up.
+ spec.loader_state = None
+ code = _call_with_frames_removed(_imp.get_frozen_object, name, data)
exec(code, module.__dict__)
@classmethod