Commit 79d1c2e6 authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-25711: Rewrite zipimport in pure Python. (GH-6809)

parent 4ba3b50b
...@@ -64,6 +64,7 @@ class PythonValuesTestCase(unittest.TestCase): ...@@ -64,6 +64,7 @@ class PythonValuesTestCase(unittest.TestCase):
bootstrap_expected = [ bootstrap_expected = [
b'_frozen_importlib', b'_frozen_importlib',
b'_frozen_importlib_external', b'_frozen_importlib_external',
b'zipimport',
] ]
for entry in ft: for entry in ft:
# This is dangerous. We *can* iterate over a pointer, but # This is dangerous. We *can* iterate over a pointer, but
......
...@@ -48,8 +48,8 @@ else: ...@@ -48,8 +48,8 @@ else:
sys.modules['importlib._bootstrap_external'] = _bootstrap_external sys.modules['importlib._bootstrap_external'] = _bootstrap_external
# To simplify imports in test code # To simplify imports in test code
_w_long = _bootstrap_external._w_long _pack_uint32 = _bootstrap_external._pack_uint32
_r_long = _bootstrap_external._r_long _unpack_uint32 = _bootstrap_external._unpack_uint32
# Fully bootstrapped at this point, import whatever you like, circular # Fully bootstrapped at this point, import whatever you like, circular
# dependencies and startup overhead minimisation permitting :) # dependencies and startup overhead minimisation permitting :)
......
...@@ -43,14 +43,20 @@ def _make_relax_case(): ...@@ -43,14 +43,20 @@ def _make_relax_case():
return _relax_case return _relax_case
def _w_long(x): def _pack_uint32(x):
"""Convert a 32-bit integer to little-endian.""" """Convert a 32-bit integer to little-endian."""
return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little') return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little')
def _r_long(int_bytes): def _unpack_uint32(data):
"""Convert 4 bytes in little-endian to an integer.""" """Convert 4 bytes in little-endian to an integer."""
return int.from_bytes(int_bytes, 'little') assert len(data) == 4
return int.from_bytes(data, 'little')
def _unpack_uint16(data):
"""Convert 2 bytes in little-endian to an integer."""
assert len(data) == 2
return int.from_bytes(data, 'little')
def _path_join(*path_parts): def _path_join(*path_parts):
...@@ -503,7 +509,7 @@ def _classify_pyc(data, name, exc_details): ...@@ -503,7 +509,7 @@ def _classify_pyc(data, name, exc_details):
message = f'reached EOF while reading pyc header of {name!r}' message = f'reached EOF while reading pyc header of {name!r}'
_bootstrap._verbose_message('{}', message) _bootstrap._verbose_message('{}', message)
raise EOFError(message) raise EOFError(message)
flags = _r_long(data[4:8]) flags = _unpack_uint32(data[4:8])
# Only the first two flags are defined. # Only the first two flags are defined.
if flags & ~0b11: if flags & ~0b11:
message = f'invalid flags {flags!r} in {name!r}' message = f'invalid flags {flags!r} in {name!r}'
...@@ -530,12 +536,12 @@ def _validate_timestamp_pyc(data, source_mtime, source_size, name, ...@@ -530,12 +536,12 @@ def _validate_timestamp_pyc(data, source_mtime, source_size, name,
An ImportError is raised if the bytecode is stale. An ImportError is raised if the bytecode is stale.
""" """
if _r_long(data[8:12]) != (source_mtime & 0xFFFFFFFF): if _unpack_uint32(data[8:12]) != (source_mtime & 0xFFFFFFFF):
message = f'bytecode is stale for {name!r}' message = f'bytecode is stale for {name!r}'
_bootstrap._verbose_message('{}', message) _bootstrap._verbose_message('{}', message)
raise ImportError(message, **exc_details) raise ImportError(message, **exc_details)
if (source_size is not None and if (source_size is not None and
_r_long(data[12:16]) != (source_size & 0xFFFFFFFF)): _unpack_uint32(data[12:16]) != (source_size & 0xFFFFFFFF)):
raise ImportError(f'bytecode is stale for {name!r}', **exc_details) raise ImportError(f'bytecode is stale for {name!r}', **exc_details)
...@@ -579,9 +585,9 @@ def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None): ...@@ -579,9 +585,9 @@ def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None):
def _code_to_timestamp_pyc(code, mtime=0, source_size=0): def _code_to_timestamp_pyc(code, mtime=0, source_size=0):
"Produce the data for a timestamp-based pyc." "Produce the data for a timestamp-based pyc."
data = bytearray(MAGIC_NUMBER) data = bytearray(MAGIC_NUMBER)
data.extend(_w_long(0)) data.extend(_pack_uint32(0))
data.extend(_w_long(mtime)) data.extend(_pack_uint32(mtime))
data.extend(_w_long(source_size)) data.extend(_pack_uint32(source_size))
data.extend(marshal.dumps(code)) data.extend(marshal.dumps(code))
return data return data
...@@ -590,7 +596,7 @@ def _code_to_hash_pyc(code, source_hash, checked=True): ...@@ -590,7 +596,7 @@ def _code_to_hash_pyc(code, source_hash, checked=True):
"Produce the data for a hash-based pyc." "Produce the data for a hash-based pyc."
data = bytearray(MAGIC_NUMBER) data = bytearray(MAGIC_NUMBER)
flags = 0b1 | checked << 1 flags = 0b1 | checked << 1
data.extend(_w_long(flags)) data.extend(_pack_uint32(flags))
assert len(source_hash) == 8 assert len(source_hash) == 8
data.extend(source_hash) data.extend(source_hash)
data.extend(marshal.dumps(code)) data.extend(marshal.dumps(code))
......
...@@ -726,7 +726,7 @@ class StateTestCase(BaseTestCase): ...@@ -726,7 +726,7 @@ class StateTestCase(BaseTestCase):
('line', 2, 'tfunc_import'), ('step', ), ('line', 2, 'tfunc_import'), ('step', ),
('line', 3, 'tfunc_import'), ('quit', ), ('line', 3, 'tfunc_import'), ('quit', ),
] ]
skip = ('importlib*', TEST_MODULE) skip = ('importlib*', 'zipimport', TEST_MODULE)
with TracerRun(self, skip=skip) as tracer: with TracerRun(self, skip=skip) as tracer:
tracer.runcall(tfunc_import) tracer.runcall(tfunc_import)
......
...@@ -629,7 +629,7 @@ class SourceLoaderBadBytecodeTest: ...@@ -629,7 +629,7 @@ class SourceLoaderBadBytecodeTest:
bytecode_file.write(zeros) bytecode_file.write(zeros)
self.import_(mapping['_temp'], '_temp') self.import_(mapping['_temp'], '_temp')
source_mtime = os.path.getmtime(mapping['_temp']) source_mtime = os.path.getmtime(mapping['_temp'])
source_timestamp = self.importlib._w_long(source_mtime) source_timestamp = self.importlib._pack_uint32(source_mtime)
with open(bytecode_path, 'rb') as bytecode_file: with open(bytecode_path, 'rb') as bytecode_file:
bytecode_file.seek(8) bytecode_file.seek(8)
self.assertEqual(bytecode_file.read(4), source_timestamp) self.assertEqual(bytecode_file.read(4), source_timestamp)
......
...@@ -712,9 +712,9 @@ class SourceLoader(SourceOnlyLoader): ...@@ -712,9 +712,9 @@ class SourceLoader(SourceOnlyLoader):
if magic is None: if magic is None:
magic = self.util.MAGIC_NUMBER magic = self.util.MAGIC_NUMBER
data = bytearray(magic) data = bytearray(magic)
data.extend(self.init._w_long(0)) data.extend(self.init._pack_uint32(0))
data.extend(self.init._w_long(self.source_mtime)) data.extend(self.init._pack_uint32(self.source_mtime))
data.extend(self.init._w_long(self.source_size)) data.extend(self.init._pack_uint32(self.source_size))
code_object = compile(self.source, self.path, 'exec', code_object = compile(self.source, self.path, 'exec',
dont_inherit=True) dont_inherit=True)
data.extend(marshal.dumps(code_object)) data.extend(marshal.dumps(code_object))
...@@ -876,9 +876,9 @@ class SourceLoaderBytecodeTests(SourceLoaderTestHarness): ...@@ -876,9 +876,9 @@ class SourceLoaderBytecodeTests(SourceLoaderTestHarness):
if bytecode_written: if bytecode_written:
self.assertIn(self.cached, self.loader.written) self.assertIn(self.cached, self.loader.written)
data = bytearray(self.util.MAGIC_NUMBER) data = bytearray(self.util.MAGIC_NUMBER)
data.extend(self.init._w_long(0)) data.extend(self.init._pack_uint32(0))
data.extend(self.init._w_long(self.loader.source_mtime)) data.extend(self.init._pack_uint32(self.loader.source_mtime))
data.extend(self.init._w_long(self.loader.source_size)) data.extend(self.init._pack_uint32(self.loader.source_size))
data.extend(marshal.dumps(code_object)) data.extend(marshal.dumps(code_object))
self.assertEqual(self.loader.written[self.cached], bytes(data)) self.assertEqual(self.loader.written[self.cached], bytes(data))
......
...@@ -551,7 +551,12 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): ...@@ -551,7 +551,12 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
z.writestr(name, data) z.writestr(name, data)
z.close() z.close()
zi = zipimport.zipimporter(TEMP_ZIP) zi = zipimport.zipimporter(TEMP_ZIP)
self.assertEqual(data, zi.get_data(FunnyStr(name))) try:
data2 = zi.get_data(FunnyStr(name))
except AttributeError:
pass
else:
self.assertEqual(data2, data)
finally: finally:
z.close() z.close()
os.remove(TEMP_ZIP) os.remove(TEMP_ZIP)
...@@ -677,9 +682,9 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): ...@@ -677,9 +682,9 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
zipimport.zipimporter(filename) zipimport.zipimporter(filename)
zipimport.zipimporter(os.fsencode(filename)) zipimport.zipimporter(os.fsencode(filename))
with self.assertWarns(DeprecationWarning): with self.assertRaises(TypeError):
zipimport.zipimporter(bytearray(os.fsencode(filename))) zipimport.zipimporter(bytearray(os.fsencode(filename)))
with self.assertWarns(DeprecationWarning): with self.assertRaises(TypeError):
zipimport.zipimporter(memoryview(os.fsencode(filename))) zipimport.zipimporter(memoryview(os.fsencode(filename)))
@support.cpython_only @support.cpython_only
...@@ -687,14 +692,14 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): ...@@ -687,14 +692,14 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
# The interpreter shouldn't crash in case of calling methods of an # The interpreter shouldn't crash in case of calling methods of an
# uninitialized zipimport.zipimporter object. # uninitialized zipimport.zipimporter object.
zi = zipimport.zipimporter.__new__(zipimport.zipimporter) zi = zipimport.zipimporter.__new__(zipimport.zipimporter)
self.assertRaises(ValueError, zi.find_module, 'foo') self.assertRaises((ValueError, AttributeError), zi.find_module, 'foo')
self.assertRaises(ValueError, zi.find_loader, 'foo') self.assertRaises((ValueError, AttributeError), zi.find_loader, 'foo')
self.assertRaises(ValueError, zi.load_module, 'foo') self.assertRaises((ValueError, AttributeError), zi.load_module, 'foo')
self.assertRaises(ValueError, zi.get_filename, 'foo') self.assertRaises((ValueError, AttributeError), zi.get_filename, 'foo')
self.assertRaises(ValueError, zi.is_package, 'foo') self.assertRaises((ValueError, AttributeError), zi.is_package, 'foo')
self.assertRaises(ValueError, zi.get_data, 'foo') self.assertRaises((ValueError, AttributeError), zi.get_data, 'foo')
self.assertRaises(ValueError, zi.get_code, 'foo') self.assertRaises((ValueError, AttributeError), zi.get_code, 'foo')
self.assertRaises(ValueError, zi.get_source, 'foo') self.assertRaises((ValueError, AttributeError), zi.get_source, 'foo')
@support.requires_zlib @support.requires_zlib
...@@ -712,7 +717,7 @@ class CompressedZipImportTestCase(UncompressedZipImportTestCase): ...@@ -712,7 +717,7 @@ class CompressedZipImportTestCase(UncompressedZipImportTestCase):
zip_file.writestr('bar.py', b'print("hello world")', ZIP_DEFLATED) zip_file.writestr('bar.py', b'print("hello world")', ZIP_DEFLATED)
zi = zipimport.zipimporter(TEMP_ZIP) zi = zipimport.zipimporter(TEMP_ZIP)
with support.swap_attr(zlib, 'decompress', bad_decompress): with support.swap_attr(zlib, 'decompress', bad_decompress):
self.assertRaises(TypeError, zi.get_source, 'bar') self.assertRaises((TypeError, AttributeError), zi.get_source, 'bar')
class BadFileZipImportTestCase(unittest.TestCase): class BadFileZipImportTestCase(unittest.TestCase):
......
This diff is collapsed.
...@@ -713,16 +713,22 @@ Programs/_freeze_importlib: Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FRO ...@@ -713,16 +713,22 @@ Programs/_freeze_importlib: Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FRO
regen-importlib: Programs/_freeze_importlib regen-importlib: Programs/_freeze_importlib
# Regenerate Python/importlib_external.h # Regenerate Python/importlib_external.h
# from Lib/importlib/_bootstrap_external.py using _freeze_importlib # from Lib/importlib/_bootstrap_external.py using _freeze_importlib
./Programs/_freeze_importlib \ ./Programs/_freeze_importlib importlib._bootstrap_external \
$(srcdir)/Lib/importlib/_bootstrap_external.py \ $(srcdir)/Lib/importlib/_bootstrap_external.py \
$(srcdir)/Python/importlib_external.h.new $(srcdir)/Python/importlib_external.h.new
$(UPDATE_FILE) $(srcdir)/Python/importlib_external.h $(srcdir)/Python/importlib_external.h.new $(UPDATE_FILE) $(srcdir)/Python/importlib_external.h $(srcdir)/Python/importlib_external.h.new
# Regenerate Python/importlib.h from Lib/importlib/_bootstrap.py # Regenerate Python/importlib.h from Lib/importlib/_bootstrap.py
# using _freeze_importlib # using _freeze_importlib
./Programs/_freeze_importlib \ ./Programs/_freeze_importlib importlib._bootstrap \
$(srcdir)/Lib/importlib/_bootstrap.py \ $(srcdir)/Lib/importlib/_bootstrap.py \
$(srcdir)/Python/importlib.h.new $(srcdir)/Python/importlib.h.new
$(UPDATE_FILE) $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib.h.new $(UPDATE_FILE) $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib.h.new
# Regenerate Python/importlib_zipimport.h from Lib/zipimport.py
# using _freeze_importlib
./Programs/_freeze_importlib zipimport \
$(srcdir)/Lib/zipimport.py \
$(srcdir)/Python/importlib_zipimport.h.new
$(UPDATE_FILE) $(srcdir)/Python/importlib_zipimport.h $(srcdir)/Python/importlib_zipimport.h.new
############################################################################ ############################################################################
...@@ -897,7 +903,8 @@ regen-opcode-targets: ...@@ -897,7 +903,8 @@ regen-opcode-targets:
Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h Python/ceval.o: $(srcdir)/Python/opcode_targets.h $(srcdir)/Python/ceval_gil.h
Python/frozen.o: $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib_external.h Python/frozen.o: $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib_external.h \
$(srcdir)/Python/importlib_zipimport.h
# Generate DTrace probe macros, then rename them (PYTHON_ -> PyDTrace_) to # Generate DTrace probe macros, then rename them (PYTHON_ -> PyDTrace_) to
# follow our naming conventions. dtrace(1) uses the output filename to generate # follow our naming conventions. dtrace(1) uses the output filename to generate
......
The :mod:`zipimport` module has been rewritten in pure Python.
...@@ -125,10 +125,6 @@ _locale _localemodule.c # -lintl ...@@ -125,10 +125,6 @@ _locale _localemodule.c # -lintl
# Standard I/O baseline # Standard I/O baseline
_io -DPy_BUILD_CORE -I$(srcdir)/Modules/_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c _io -DPy_BUILD_CORE -I$(srcdir)/Modules/_io _io/_iomodule.c _io/iobase.c _io/fileio.c _io/bytesio.c _io/bufferedio.c _io/textio.c _io/stringio.c
# The zipimport module is always imported at startup. Having it as a
# builtin module avoids some bootstrapping problems and reduces overhead.
zipimport -DPy_BUILD_CORE zipimport.c
# faulthandler module # faulthandler module
faulthandler faulthandler.c faulthandler faulthandler.c
......
This diff is collapsed.
This diff is collapsed.
...@@ -35,7 +35,6 @@ extern PyObject* PyInit__weakref(void); ...@@ -35,7 +35,6 @@ extern PyObject* PyInit__weakref(void);
/* XXX: These two should really be extracted to standalone extensions. */ /* XXX: These two should really be extracted to standalone extensions. */
extern PyObject* PyInit_xxsubtype(void); extern PyObject* PyInit_xxsubtype(void);
extern PyObject* PyInit__xxsubinterpreters(void); extern PyObject* PyInit__xxsubinterpreters(void);
extern PyObject* PyInit_zipimport(void);
extern PyObject* PyInit__random(void); extern PyObject* PyInit__random(void);
extern PyObject* PyInit_itertools(void); extern PyObject* PyInit_itertools(void);
extern PyObject* PyInit__collections(void); extern PyObject* PyInit__collections(void);
...@@ -131,7 +130,6 @@ struct _inittab _PyImport_Inittab[] = { ...@@ -131,7 +130,6 @@ struct _inittab _PyImport_Inittab[] = {
{"xxsubtype", PyInit_xxsubtype}, {"xxsubtype", PyInit_xxsubtype},
{"_xxsubinterpreters", PyInit__xxsubinterpreters}, {"_xxsubinterpreters", PyInit__xxsubinterpreters},
{"zipimport", PyInit_zipimport},
#ifdef _Py_HAVE_ZLIB #ifdef _Py_HAVE_ZLIB
{"zlib", PyInit_zlib}, {"zlib", PyInit_zlib},
#endif #endif
......
...@@ -77,19 +77,26 @@ ...@@ -77,19 +77,26 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\Lib\importlib\_bootstrap.py"> <None Include="..\Lib\importlib\_bootstrap.py">
<ModName>importlib._bootstrap</ModName>
<IntFile>$(IntDir)importlib.g.h</IntFile> <IntFile>$(IntDir)importlib.g.h</IntFile>
<OutFile>$(PySourcePath)Python\importlib.h</OutFile> <OutFile>$(PySourcePath)Python\importlib.h</OutFile>
</None> </None>
<None Include="..\Lib\importlib\_bootstrap_external.py"> <None Include="..\Lib\importlib\_bootstrap_external.py">
<ModName>importlib._bootstrap_external</ModName>
<IntFile>$(IntDir)importlib_external.g.h</IntFile> <IntFile>$(IntDir)importlib_external.g.h</IntFile>
<OutFile>$(PySourcePath)Python\importlib_external.h</OutFile> <OutFile>$(PySourcePath)Python\importlib_external.h</OutFile>
</None> </None>
<None Include="..\Lib\zipimport.py">
<ModName>zipimport</ModName>
<IntFile>$(IntDir)importlib_zipimport.g.h</IntFile>
<OutFile>$(PySourcePath)Python\importlib_zipimport.h</OutFile>
</None>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
<Target Name="_RebuildImportLib"> <Target Name="_RebuildImportLib">
<Exec Command='"$(TargetPath)" "%(None.FullPath)" "%(None.IntFile)"' /> <Exec Command='"$(TargetPath)" "%(None.ModName)" "%(None.FullPath)" "%(None.IntFile)"' />
<PropertyGroup> <PropertyGroup>
<_OldContent Condition="Exists($(OutTargetPath))"></_OldContent> <_OldContent Condition="Exists($(OutTargetPath))"></_OldContent>
...@@ -114,6 +121,7 @@ ...@@ -114,6 +121,7 @@
<ItemGroup> <ItemGroup>
<Clean Include="$(IntDir)importlib.g.h" /> <Clean Include="$(IntDir)importlib.g.h" />
<Clean Include="$(IntDir)importlib_external.g.h" /> <Clean Include="$(IntDir)importlib_external.g.h" />
<Clean Include="$(IntDir)importlib_zipimport.g.h" />
</ItemGroup> </ItemGroup>
</Target> </Target>
</Project> </Project>
...@@ -282,7 +282,6 @@ ...@@ -282,7 +282,6 @@
<ClCompile Include="..\Modules\timemodule.c" /> <ClCompile Include="..\Modules\timemodule.c" />
<ClCompile Include="..\Modules\xxsubtype.c" /> <ClCompile Include="..\Modules\xxsubtype.c" />
<ClCompile Include="..\Modules\_xxsubinterpretersmodule.c" /> <ClCompile Include="..\Modules\_xxsubinterpretersmodule.c" />
<ClCompile Include="..\Modules\zipimport.c" />
<ClCompile Include="..\Modules\_io\fileio.c" /> <ClCompile Include="..\Modules\_io\fileio.c" />
<ClCompile Include="..\Modules\_io\bytesio.c" /> <ClCompile Include="..\Modules\_io\bytesio.c" />
<ClCompile Include="..\Modules\_io\stringio.c" /> <ClCompile Include="..\Modules\_io\stringio.c" />
......
...@@ -617,9 +617,6 @@ ...@@ -617,9 +617,6 @@
<ClCompile Include="..\Modules\xxsubtype.c"> <ClCompile Include="..\Modules\xxsubtype.c">
<Filter>Modules</Filter> <Filter>Modules</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Modules\zipimport.c">
<Filter>Modules</Filter>
</ClCompile>
<ClCompile Include="..\Modules\zlibmodule.c"> <ClCompile Include="..\Modules\zlibmodule.c">
<Filter>Modules</Filter> <Filter>Modules</Filter>
</ClCompile> </ClCompile>
......
...@@ -27,28 +27,30 @@ static const struct _frozen _PyImport_FrozenModules[] = { ...@@ -27,28 +27,30 @@ static const struct _frozen _PyImport_FrozenModules[] = {
const struct _frozen *PyImport_FrozenModules; const struct _frozen *PyImport_FrozenModules;
#endif #endif
const char header[] = "/* Auto-generated by Programs/_freeze_importlib.c */"; static const char header[] =
"/* Auto-generated by Programs/_freeze_importlib.c */";
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *inpath, *outpath, *code_name; const char *name, *inpath, *outpath;
char buf[100];
FILE *infile = NULL, *outfile = NULL; FILE *infile = NULL, *outfile = NULL;
struct _Py_stat_struct status; struct _Py_stat_struct status;
size_t text_size, data_size, n; size_t text_size, data_size, i, n;
char *text = NULL; char *text = NULL;
unsigned char *data; unsigned char *data;
PyObject *code = NULL, *marshalled = NULL; PyObject *code = NULL, *marshalled = NULL;
int is_bootstrap = 1;
PyImport_FrozenModules = _PyImport_FrozenModules; PyImport_FrozenModules = _PyImport_FrozenModules;
if (argc != 3) { if (argc != 4) {
fprintf(stderr, "need to specify input and output paths\n"); fprintf(stderr, "need to specify the name, input and output paths\n");
return 2; return 2;
} }
inpath = argv[1]; name = argv[1];
outpath = argv[2]; inpath = argv[2];
outpath = argv[3];
infile = fopen(inpath, "rb"); infile = fopen(inpath, "rb");
if (infile == NULL) { if (infile == NULL) {
fprintf(stderr, "cannot open '%s' for reading\n", inpath); fprintf(stderr, "cannot open '%s' for reading\n", inpath);
...@@ -90,14 +92,8 @@ main(int argc, char *argv[]) ...@@ -90,14 +92,8 @@ main(int argc, char *argv[])
_Py_FatalInitError(err); _Py_FatalInitError(err);
} }
if (strstr(inpath, "_external") != NULL) { sprintf(buf, "<frozen %s>", name);
is_bootstrap = 0; code = Py_CompileStringExFlags(text, buf, Py_file_input, NULL, 0);
}
code_name = is_bootstrap ?
"<frozen importlib._bootstrap>" :
"<frozen importlib._bootstrap_external>";
code = Py_CompileStringExFlags(text, code_name, Py_file_input, NULL, 0);
if (code == NULL) if (code == NULL)
goto error; goto error;
free(text); free(text);
...@@ -120,11 +116,13 @@ main(int argc, char *argv[]) ...@@ -120,11 +116,13 @@ main(int argc, char *argv[])
goto error; goto error;
} }
fprintf(outfile, "%s\n", header); fprintf(outfile, "%s\n", header);
if (is_bootstrap) for (i = n = 0; name[i] != '\0'; i++) {
fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n"); if (name[i] != '.') {
else buf[n++] = name[i];
fprintf(outfile, }
"const unsigned char _Py_M__importlib_external[] = {\n"); }
buf[n] = '\0';
fprintf(outfile, "const unsigned char _Py_M__%s[] = {\n", buf);
for (n = 0; n < data_size; n += 16) { for (n = 0; n < data_size; n += 16) {
size_t i, end = Py_MIN(n + 16, data_size); size_t i, end = Py_MIN(n + 16, data_size);
fprintf(outfile, " "); fprintf(outfile, " ");
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "Python.h" #include "Python.h"
#include "importlib.h" #include "importlib.h"
#include "importlib_external.h" #include "importlib_external.h"
#include "importlib_zipimport.h"
/* In order to test the support for frozen modules, by default we /* In order to test the support for frozen modules, by default we
define a single frozen module, __hello__. Loading it will print define a single frozen module, __hello__. Loading it will print
...@@ -29,9 +30,12 @@ static unsigned char M___hello__[] = { ...@@ -29,9 +30,12 @@ static unsigned char M___hello__[] = {
static const struct _frozen _PyImport_FrozenModules[] = { static const struct _frozen _PyImport_FrozenModules[] = {
/* importlib */ /* importlib */
{"_frozen_importlib", _Py_M__importlib, (int)sizeof(_Py_M__importlib)}, {"_frozen_importlib", _Py_M__importlib_bootstrap,
{"_frozen_importlib_external", _Py_M__importlib_external, (int)sizeof(_Py_M__importlib_bootstrap)},
(int)sizeof(_Py_M__importlib_external)}, {"_frozen_importlib_external", _Py_M__importlib_bootstrap_external,
(int)sizeof(_Py_M__importlib_bootstrap_external)},
{"zipimport", _Py_M__zipimport,
(int)sizeof(_Py_M__zipimport)},
/* Test module */ /* Test module */
{"__hello__", M___hello__, SIZE}, {"__hello__", M___hello__, SIZE},
/* Test package (negative size indicates package-ness) */ /* Test package (negative size indicates package-ness) */
......
/* Auto-generated by Programs/_freeze_importlib.c */ /* Auto-generated by Programs/_freeze_importlib.c */
const unsigned char _Py_M__importlib[] = { const unsigned char _Py_M__importlib_bootstrap[] = {
99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,
0,64,0,0,0,115,208,1,0,0,100,0,90,0,100,1, 0,64,0,0,0,115,208,1,0,0,100,0,90,0,100,1,
97,1,100,2,100,3,132,0,90,2,100,4,100,5,132,0, 97,1,100,2,100,3,132,0,90,2,100,4,100,5,132,0,
......
This diff is collapsed.
This diff is collapsed.
...@@ -191,7 +191,6 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) ...@@ -191,7 +191,6 @@ initimport(PyInterpreterState *interp, PyObject *sysmod)
PyObject *importlib; PyObject *importlib;
PyObject *impmod; PyObject *impmod;
PyObject *value; PyObject *value;
_PyInitError err;
/* Import _importlib through its frozen version, _frozen_importlib. */ /* Import _importlib through its frozen version, _frozen_importlib. */
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) { if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
...@@ -233,11 +232,6 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) ...@@ -233,11 +232,6 @@ initimport(PyInterpreterState *interp, PyObject *sysmod)
Py_DECREF(value); Py_DECREF(value);
Py_DECREF(impmod); Py_DECREF(impmod);
err = _PyImportZip_Init();
if (_Py_INIT_FAILED(err)) {
return err;
}
return _Py_INIT_OK(); return _Py_INIT_OK();
} }
...@@ -252,7 +246,7 @@ initexternalimport(PyInterpreterState *interp) ...@@ -252,7 +246,7 @@ initexternalimport(PyInterpreterState *interp)
return _Py_INIT_ERR("external importer setup failed"); return _Py_INIT_ERR("external importer setup failed");
} }
Py_DECREF(value); Py_DECREF(value);
return _Py_INIT_OK(); return _PyImportZip_Init();
} }
/* Helper functions to better handle the legacy C locale /* Helper functions to better handle the legacy C locale
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment