Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 79d1c2e

Browse files
bpo-25711: Rewrite zipimport in pure Python. (GH-6809)
1 parent 4ba3b50 commit 79d1c2e

23 files changed

+2998
-3408
lines changed

Lib/ctypes/test/test_values.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class struct_frozen(Structure):
6464
bootstrap_expected = [
6565
b'_frozen_importlib',
6666
b'_frozen_importlib_external',
67+
b'zipimport',
6768
]
6869
for entry in ft:
6970
# This is dangerous. We *can* iterate over a pointer, but

Lib/importlib/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
sys.modules['importlib._bootstrap_external'] = _bootstrap_external
4949

5050
# To simplify imports in test code
51-
_w_long = _bootstrap_external._w_long
52-
_r_long = _bootstrap_external._r_long
51+
_pack_uint32 = _bootstrap_external._pack_uint32
52+
_unpack_uint32 = _bootstrap_external._unpack_uint32
5353

5454
# Fully bootstrapped at this point, import whatever you like, circular
5555
# dependencies and startup overhead minimisation permitting :)

Lib/importlib/_bootstrap_external.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,20 @@ def _relax_case():
4343
return _relax_case
4444

4545

46-
def _w_long(x):
46+
def _pack_uint32(x):
4747
"""Convert a 32-bit integer to little-endian."""
4848
return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little')
4949

5050

51-
def _r_long(int_bytes):
51+
def _unpack_uint32(data):
5252
"""Convert 4 bytes in little-endian to an integer."""
53-
return int.from_bytes(int_bytes, 'little')
53+
assert len(data) == 4
54+
return int.from_bytes(data, 'little')
55+
56+
def _unpack_uint16(data):
57+
"""Convert 2 bytes in little-endian to an integer."""
58+
assert len(data) == 2
59+
return int.from_bytes(data, 'little')
5460

5561

5662
def _path_join(*path_parts):
@@ -503,7 +509,7 @@ def _classify_pyc(data, name, exc_details):
503509
message = f'reached EOF while reading pyc header of {name!r}'
504510
_bootstrap._verbose_message('{}', message)
505511
raise EOFError(message)
506-
flags = _r_long(data[4:8])
512+
flags = _unpack_uint32(data[4:8])
507513
# Only the first two flags are defined.
508514
if flags & ~0b11:
509515
message = f'invalid flags {flags!r} in {name!r}'
@@ -530,12 +536,12 @@ def _validate_timestamp_pyc(data, source_mtime, source_size, name,
530536
An ImportError is raised if the bytecode is stale.
531537
532538
"""
533-
if _r_long(data[8:12]) != (source_mtime & 0xFFFFFFFF):
539+
if _unpack_uint32(data[8:12]) != (source_mtime & 0xFFFFFFFF):
534540
message = f'bytecode is stale for {name!r}'
535541
_bootstrap._verbose_message('{}', message)
536542
raise ImportError(message, **exc_details)
537543
if (source_size is not None and
538-
_r_long(data[12:16]) != (source_size & 0xFFFFFFFF)):
544+
_unpack_uint32(data[12:16]) != (source_size & 0xFFFFFFFF)):
539545
raise ImportError(f'bytecode is stale for {name!r}', **exc_details)
540546

541547

@@ -579,9 +585,9 @@ def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None):
579585
def _code_to_timestamp_pyc(code, mtime=0, source_size=0):
580586
"Produce the data for a timestamp-based pyc."
581587
data = bytearray(MAGIC_NUMBER)
582-
data.extend(_w_long(0))
583-
data.extend(_w_long(mtime))
584-
data.extend(_w_long(source_size))
588+
data.extend(_pack_uint32(0))
589+
data.extend(_pack_uint32(mtime))
590+
data.extend(_pack_uint32(source_size))
585591
data.extend(marshal.dumps(code))
586592
return data
587593

@@ -590,7 +596,7 @@ def _code_to_hash_pyc(code, source_hash, checked=True):
590596
"Produce the data for a hash-based pyc."
591597
data = bytearray(MAGIC_NUMBER)
592598
flags = 0b1 | checked << 1
593-
data.extend(_w_long(flags))
599+
data.extend(_pack_uint32(flags))
594600
assert len(source_hash) == 8
595601
data.extend(source_hash)
596602
data.extend(marshal.dumps(code))

Lib/test/test_bdb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ def main():
726726
('line', 2, 'tfunc_import'), ('step', ),
727727
('line', 3, 'tfunc_import'), ('quit', ),
728728
]
729-
skip = ('importlib*', TEST_MODULE)
729+
skip = ('importlib*', 'zipimport', TEST_MODULE)
730730
with TracerRun(self, skip=skip) as tracer:
731731
tracer.runcall(tfunc_import)
732732

Lib/test/test_importlib/source/test_file_loader.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ def test_old_timestamp(self):
629629
bytecode_file.write(zeros)
630630
self.import_(mapping['_temp'], '_temp')
631631
source_mtime = os.path.getmtime(mapping['_temp'])
632-
source_timestamp = self.importlib._w_long(source_mtime)
632+
source_timestamp = self.importlib._pack_uint32(source_mtime)
633633
with open(bytecode_path, 'rb') as bytecode_file:
634634
bytecode_file.seek(8)
635635
self.assertEqual(bytecode_file.read(4), source_timestamp)

Lib/test/test_importlib/test_abc.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -712,9 +712,9 @@ def __init__(self, path, magic=None):
712712
if magic is None:
713713
magic = self.util.MAGIC_NUMBER
714714
data = bytearray(magic)
715-
data.extend(self.init._w_long(0))
716-
data.extend(self.init._w_long(self.source_mtime))
717-
data.extend(self.init._w_long(self.source_size))
715+
data.extend(self.init._pack_uint32(0))
716+
data.extend(self.init._pack_uint32(self.source_mtime))
717+
data.extend(self.init._pack_uint32(self.source_size))
718718
code_object = compile(self.source, self.path, 'exec',
719719
dont_inherit=True)
720720
data.extend(marshal.dumps(code_object))
@@ -876,9 +876,9 @@ def verify_code(self, code_object, *, bytecode_written=False):
876876
if bytecode_written:
877877
self.assertIn(self.cached, self.loader.written)
878878
data = bytearray(self.util.MAGIC_NUMBER)
879-
data.extend(self.init._w_long(0))
880-
data.extend(self.init._w_long(self.loader.source_mtime))
881-
data.extend(self.init._w_long(self.loader.source_size))
879+
data.extend(self.init._pack_uint32(0))
880+
data.extend(self.init._pack_uint32(self.loader.source_mtime))
881+
data.extend(self.init._pack_uint32(self.loader.source_size))
882882
data.extend(marshal.dumps(code_object))
883883
self.assertEqual(self.loader.written[self.cached], bytes(data))
884884

Lib/test/test_zipimport.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,12 @@ def replace(self, old, new):
551551
z.writestr(name, data)
552552
z.close()
553553
zi = zipimport.zipimporter(TEMP_ZIP)
554-
self.assertEqual(data, zi.get_data(FunnyStr(name)))
554+
try:
555+
data2 = zi.get_data(FunnyStr(name))
556+
except AttributeError:
557+
pass
558+
else:
559+
self.assertEqual(data2, data)
555560
finally:
556561
z.close()
557562
os.remove(TEMP_ZIP)
@@ -677,24 +682,24 @@ def testBytesPath(self):
677682

678683
zipimport.zipimporter(filename)
679684
zipimport.zipimporter(os.fsencode(filename))
680-
with self.assertWarns(DeprecationWarning):
685+
with self.assertRaises(TypeError):
681686
zipimport.zipimporter(bytearray(os.fsencode(filename)))
682-
with self.assertWarns(DeprecationWarning):
687+
with self.assertRaises(TypeError):
683688
zipimport.zipimporter(memoryview(os.fsencode(filename)))
684689

685690
@support.cpython_only
686691
def testUninitializedZipimporter(self):
687692
# The interpreter shouldn't crash in case of calling methods of an
688693
# uninitialized zipimport.zipimporter object.
689694
zi = zipimport.zipimporter.__new__(zipimport.zipimporter)
690-
self.assertRaises(ValueError, zi.find_module, 'foo')
691-
self.assertRaises(ValueError, zi.find_loader, 'foo')
692-
self.assertRaises(ValueError, zi.load_module, 'foo')
693-
self.assertRaises(ValueError, zi.get_filename, 'foo')
694-
self.assertRaises(ValueError, zi.is_package, 'foo')
695-
self.assertRaises(ValueError, zi.get_data, 'foo')
696-
self.assertRaises(ValueError, zi.get_code, 'foo')
697-
self.assertRaises(ValueError, zi.get_source, 'foo')
695+
self.assertRaises((ValueError, AttributeError), zi.find_module, 'foo')
696+
self.assertRaises((ValueError, AttributeError), zi.find_loader, 'foo')
697+
self.assertRaises((ValueError, AttributeError), zi.load_module, 'foo')
698+
self.assertRaises((ValueError, AttributeError), zi.get_filename, 'foo')
699+
self.assertRaises((ValueError, AttributeError), zi.is_package, 'foo')
700+
self.assertRaises((ValueError, AttributeError), zi.get_data, 'foo')
701+
self.assertRaises((ValueError, AttributeError), zi.get_code, 'foo')
702+
self.assertRaises((ValueError, AttributeError), zi.get_source, 'foo')
698703

699704

700705
@support.requires_zlib
@@ -712,7 +717,7 @@ def bad_decompress(*args):
712717
zip_file.writestr('bar.py', b'print("hello world")', ZIP_DEFLATED)
713718
zi = zipimport.zipimporter(TEMP_ZIP)
714719
with support.swap_attr(zlib, 'decompress', bad_decompress):
715-
self.assertRaises(TypeError, zi.get_source, 'bar')
720+
self.assertRaises((TypeError, AttributeError), zi.get_source, 'bar')
716721

717722

718723
class BadFileZipImportTestCase(unittest.TestCase):

0 commit comments

Comments
 (0)