Closes #15030: Make importlib.abc.PyPycLoader respect the new .pyc
file size header field. Thanks to Marc Abramowitz and Ronan Lamy for helping out with various parts of the patch.
This commit is contained in:
parent
d57caf36bd
commit
1e331560ee
|
@ -455,6 +455,10 @@ are also provided to help in implementing the core ABCs.
|
||||||
:class:`PyLoader`. Do note that this solution will not support
|
:class:`PyLoader`. Do note that this solution will not support
|
||||||
sourceless/bytecode-only loading; only source *and* bytecode loading.
|
sourceless/bytecode-only loading; only source *and* bytecode loading.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3
|
||||||
|
Updated to parse (but not use) the new source size field in bytecode
|
||||||
|
files when reading and to write out the field properly when writing.
|
||||||
|
|
||||||
.. method:: source_mtime(fullname)
|
.. method:: source_mtime(fullname)
|
||||||
|
|
||||||
An abstract method which returns the modification time for the source
|
An abstract method which returns the modification time for the source
|
||||||
|
|
|
@ -282,7 +282,12 @@ class PyPycLoader(PyLoader):
|
||||||
if len(raw_timestamp) < 4:
|
if len(raw_timestamp) < 4:
|
||||||
raise EOFError("bad timestamp in {}".format(fullname))
|
raise EOFError("bad timestamp in {}".format(fullname))
|
||||||
pyc_timestamp = _bootstrap._r_long(raw_timestamp)
|
pyc_timestamp = _bootstrap._r_long(raw_timestamp)
|
||||||
bytecode = data[8:]
|
raw_source_size = data[8:12]
|
||||||
|
if len(raw_source_size) != 4:
|
||||||
|
raise EOFError("bad file size in {}".format(fullname))
|
||||||
|
# Source size is unused as the ABC does not provide a way to
|
||||||
|
# get the size of the source ahead of reading it.
|
||||||
|
bytecode = data[12:]
|
||||||
# Verify that the magic number is valid.
|
# Verify that the magic number is valid.
|
||||||
if imp.get_magic() != magic:
|
if imp.get_magic() != magic:
|
||||||
raise ImportError(
|
raise ImportError(
|
||||||
|
@ -318,6 +323,7 @@ class PyPycLoader(PyLoader):
|
||||||
if not sys.dont_write_bytecode:
|
if not sys.dont_write_bytecode:
|
||||||
data = bytearray(imp.get_magic())
|
data = bytearray(imp.get_magic())
|
||||||
data.extend(_bootstrap._w_long(source_timestamp))
|
data.extend(_bootstrap._w_long(source_timestamp))
|
||||||
|
data.extend(_bootstrap._w_long(len(source) & 0xFFFFFFFF))
|
||||||
data.extend(marshal.dumps(code_object))
|
data.extend(marshal.dumps(code_object))
|
||||||
self.write_bytecode(fullname, data)
|
self.write_bytecode(fullname, data)
|
||||||
return code_object
|
return code_object
|
||||||
|
|
|
@ -148,11 +148,12 @@ class PyPycLoaderMock(abc.PyPycLoader, PyLoaderMock):
|
||||||
self.bytecode_to_path[name] = data['path']
|
self.bytecode_to_path[name] = data['path']
|
||||||
magic = data.get('magic', imp.get_magic())
|
magic = data.get('magic', imp.get_magic())
|
||||||
mtime = importlib._w_long(data.get('mtime', self.default_mtime))
|
mtime = importlib._w_long(data.get('mtime', self.default_mtime))
|
||||||
|
source_size = importlib._w_long(len(self.source) & 0xFFFFFFFF)
|
||||||
if 'bc' in data:
|
if 'bc' in data:
|
||||||
bc = data['bc']
|
bc = data['bc']
|
||||||
else:
|
else:
|
||||||
bc = self.compile_bc(name)
|
bc = self.compile_bc(name)
|
||||||
self.module_bytecode[name] = magic + mtime + bc
|
self.module_bytecode[name] = magic + mtime + source_size + bc
|
||||||
|
|
||||||
def compile_bc(self, name):
|
def compile_bc(self, name):
|
||||||
source_path = self.module_paths.get(name, '<test>') or '<test>'
|
source_path = self.module_paths.get(name, '<test>') or '<test>'
|
||||||
|
@ -344,7 +345,10 @@ class PyPycLoaderTests(PyLoaderTests):
|
||||||
self.assertEqual(magic, imp.get_magic())
|
self.assertEqual(magic, imp.get_magic())
|
||||||
mtime = importlib._r_long(mock.module_bytecode[name][4:8])
|
mtime = importlib._r_long(mock.module_bytecode[name][4:8])
|
||||||
self.assertEqual(mtime, 1)
|
self.assertEqual(mtime, 1)
|
||||||
bc = mock.module_bytecode[name][8:]
|
source_size = mock.module_bytecode[name][8:12]
|
||||||
|
self.assertEqual(len(mock.source) & 0xFFFFFFFF,
|
||||||
|
importlib._r_long(source_size))
|
||||||
|
bc = mock.module_bytecode[name][12:]
|
||||||
self.assertEqual(bc, mock.compile_bc(name))
|
self.assertEqual(bc, mock.compile_bc(name))
|
||||||
|
|
||||||
def test_module(self):
|
def test_module(self):
|
||||||
|
|
|
@ -587,6 +587,7 @@ Vladimir Kushnir
|
||||||
Ross Lagerwall
|
Ross Lagerwall
|
||||||
Cameron Laird
|
Cameron Laird
|
||||||
Jean-Baptiste "Jiba" Lamy
|
Jean-Baptiste "Jiba" Lamy
|
||||||
|
Ronan Lamy
|
||||||
Torsten Landschoff
|
Torsten Landschoff
|
||||||
Łukasz Langa
|
Łukasz Langa
|
||||||
Tino Lange
|
Tino Lange
|
||||||
|
|
|
@ -17,6 +17,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #15030: importlib.abc.PyPycLoader now supports the new source size
|
||||||
|
header field in .pyc files.
|
||||||
|
|
||||||
- Issue #5346: Preserve permissions of mbox, MMDF and Babyl mailbox
|
- Issue #5346: Preserve permissions of mbox, MMDF and Babyl mailbox
|
||||||
files on flush().
|
files on flush().
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue