Skip to content

Commit

Permalink
Add sys.meta_path entry for APE zip store (#425)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahgamut authored Jun 26, 2022
1 parent 893cc06 commit b535937
Show file tree
Hide file tree
Showing 10 changed files with 340 additions and 84 deletions.
2 changes: 2 additions & 0 deletions third_party/python/Include/import.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ PyObject * PyImport_GetImporter(PyObject *path);
PyObject * PyImport_Import(PyObject *name);
PyObject * PyImport_ReloadModule(PyObject *m);
void PyImport_Cleanup(void);
void _PyImportLookupTables_Init(void);
void _PyImportLookupTables_Cleanup(void);
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000
int PyImport_ImportFrozenModuleObject(
PyObject *name
Expand Down
33 changes: 24 additions & 9 deletions third_party/python/Lib/importlib/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def _verbose_message(message, *args, verbosity=1):
def _requires_builtin(fxn):
"""Decorator to verify the named module is built-in."""
def _requires_builtin_wrapper(self, fullname):
if fullname not in BUILTIN_MODULE_NAMES:
if not _imp.is_builtin(fullname):
raise ImportError('{!r} is not a built-in module'.format(fullname),
name=fullname)
return fxn(self, fullname)
Expand Down Expand Up @@ -631,7 +631,7 @@ def module_repr(module):
def find_spec(cls, fullname, path=None, target=None):
if path is not None:
return None
if fullname in BUILTIN_MODULE_NAMES:
if _imp.is_builtin(fullname):
return spec_from_loader(fullname, cls, origin='built-in')
else:
return None
Expand All @@ -651,7 +651,7 @@ def find_module(cls, fullname, path=None):
@classmethod
def create_module(self, spec):
"""Create a built-in module"""
if spec.name not in BUILTIN_MODULE_NAMES:
if not _imp.is_builtin(spec.name):
raise ImportError('{!r} is not a built-in module'.format(spec.name),
name=spec.name)
return _call_with_frames_removed(_imp.create_builtin, spec)
Expand Down Expand Up @@ -871,7 +871,7 @@ def _find_and_load_unlocked(name, import_):
msg = (_ERR_MSG + '; {!r} is not a package').format(name, parent)
raise ModuleNotFoundError(msg, name=name) from None
spec = _find_spec(name, path)
if spec is None and name in BUILTIN_MODULE_NAMES:
if spec is None and _imp.is_builtin(name):
# If this module is a C extension, the interpreter
# expects it to be a shared object located in path,
# and returns spec is None because it was not found.
Expand Down Expand Up @@ -1033,6 +1033,21 @@ def _builtin_from_name(name):
raise ImportError('no built-in module named ' + name)
return _load_unlocked(spec)

def _get_builtin_spec(name):
# called from CosmoImporter in import.c
return ModuleSpec(name, BuiltinImporter, origin="built-in", is_package=False)

def _get_frozen_spec(name, is_package):
# called from CosmoImporter in import.c
return ModuleSpec(name, FrozenImporter, origin="frozen", is_package=is_package)

def _get_zipstore_spec(name, loader, origin, is_package):
# called from CosmoImporter in import.c
spec = ModuleSpec(name, loader, origin=origin, is_package=is_package)
spec.has_location = True
if is_package:
spec.submodule_search_locations = [origin.rpartition("/")[0]]
return spec

def _setup(sys_module, _imp_module):
"""Setup importlib by importing needed built-in modules and injecting them
Expand All @@ -1042,16 +1057,15 @@ def _setup(sys_module, _imp_module):
modules, those two modules must be explicitly passed in.
"""
global _imp, sys, BUILTIN_MODULE_NAMES
global _imp, sys
_imp = _imp_module
sys = sys_module
BUILTIN_MODULE_NAMES = frozenset(sys.builtin_module_names)

# Set up the spec for existing builtin/frozen modules.
module_type = type(sys)
for name, module in sys.modules.items():
if isinstance(module, module_type):
if name in BUILTIN_MODULE_NAMES:
if _imp.is_builtin(name):
loader = BuiltinImporter
elif _imp.is_frozen(name):
loader = FrozenImporter
Expand All @@ -1072,8 +1086,9 @@ def _install(sys_module, _imp_module):
"""Install importlib as the implementation of import."""
_setup(sys_module, _imp_module)

sys.meta_path.append(BuiltinImporter)
sys.meta_path.append(FrozenImporter)
sys.meta_path.append(_imp_module.CosmoImporter)
# sys.meta_path.append(BuiltinImporter)
# sys.meta_path.append(FrozenImporter)

global _bootstrap_external
import _frozen_importlib_external
Expand Down
4 changes: 2 additions & 2 deletions third_party/python/Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -1346,10 +1346,10 @@ def _get_supported_file_loaders():
Each item is a tuple (loader, suffixes).
"""
extensions = ExtensionFileLoader, _imp.extension_suffixes()
# extensions = ExtensionFileLoader, _imp.extension_suffixes()
source = SourceFileLoader, SOURCE_SUFFIXES
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
return [bytecode, extensions, source]
return [source, bytecode] #, extensions]

def _setup(_bootstrap_module):
"""Setup the path-based importers for importlib by importing needed
Expand Down
6 changes: 2 additions & 4 deletions third_party/python/Lib/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ class TextIOBase(_io._TextIOBase, IOBase):
del klass

try:
from _io import _WindowsConsoleIO
except ImportError:
RawIOBase.register(_io._WindowsConsoleIO)
except AttributeError:
pass
else:
RawIOBase.register(_WindowsConsoleIO)
15 changes: 8 additions & 7 deletions third_party/python/Lib/ntpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import os
import sys
import stat
import posix
import genericpath
from genericpath import *

Expand Down Expand Up @@ -276,8 +277,8 @@ def lexists(path):
# common case: drive letter roots. The alternative which uses GetVolumePathName
# fails if the drive letter is the result of a SUBST.
try:
from posix import _getvolumepathname
except ImportError:
_getvolumepathname = posix._getvolumepathname
except AttributeError:
_getvolumepathname = None
def ismount(path):
"""Test whether a path is a mount point (a drive root, the root of a
Expand Down Expand Up @@ -534,9 +535,9 @@ def _abspath_fallback(path):

# Return an absolute path.
try:
from posix import _getfullpathname
_getfullpathname = posix._getfullpathname

except ImportError: # not running on Windows - mock up something sensible
except AttributeError: # not running on Windows - mock up something sensible
abspath = _abspath_fallback

else: # use native Windows method on Windows
Expand Down Expand Up @@ -664,7 +665,7 @@ def commonpath(paths):
# GetFinalPathNameByHandle is available starting with Windows 6.0.
# Windows XP and non-Windows OS'es will mock _getfinalpathname.
if sys.getwindowsversion()[:2] >= (6, 0):
from posix import _getfinalpathname
_getfinalpathname = posix._getfinalpathname
else:
raise ImportError
except (AttributeError, ImportError, OSError):
Expand All @@ -681,7 +682,7 @@ def _getfinalpathname(f):
# attribute to tell whether or not the path is a directory.
# This is overkill on Windows - just pass the path to GetFileAttributes
# and check the attribute from there.
from posix import _isdir as isdir
except ImportError:
isdir = posix._isdir
except AttributeError:
# Use genericpath.isdir as imported above.
pass
4 changes: 4 additions & 0 deletions third_party/python/Lib/test/test_cmd_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,10 @@ def test_isolatedmode(self):
with open(fake, "w") as f:
f.write("raise RuntimeError('isolated mode test')\n")
with open(main, "w") as f:
f.write("import sys\n")
f.write("import _imp\n")
f.write("if sys.meta_path[0] == _imp.CosmoImporter:\n")
f.write("\tsys.meta_path.pop(0)\n")
f.write("import uuid\n")
f.write("print('ok')\n")
self.assertRaises(subprocess.CalledProcessError,
Expand Down
1 change: 1 addition & 0 deletions third_party/python/Python/finalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ Py_FinalizeEx(void)
#endif
/* Destroy all modules */
PyImport_Cleanup();
_PyImportLookupTables_Cleanup();

/* Flush sys.stdout and sys.stderr (again, in case more was printed) */
if (_Py_FlushStdFiles() < 0) {
Expand Down
Loading

0 comments on commit b535937

Please sign in to comment.