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:
Brett Cannon 2012-07-02 14:35:34 -04:00
parent d57caf36bd
commit 1e331560ee
5 changed files with 21 additions and 3 deletions

View File

@ -455,6 +455,10 @@ are also provided to help in implementing the core ABCs.
:class:`PyLoader`. Do note that this solution will not support
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)
An abstract method which returns the modification time for the source

View File

@ -282,7 +282,12 @@ class PyPycLoader(PyLoader):
if len(raw_timestamp) < 4:
raise EOFError("bad timestamp in {}".format(fullname))
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.
if imp.get_magic() != magic:
raise ImportError(
@ -318,6 +323,7 @@ class PyPycLoader(PyLoader):
if not sys.dont_write_bytecode:
data = bytearray(imp.get_magic())
data.extend(_bootstrap._w_long(source_timestamp))
data.extend(_bootstrap._w_long(len(source) & 0xFFFFFFFF))
data.extend(marshal.dumps(code_object))
self.write_bytecode(fullname, data)
return code_object

View File

@ -148,11 +148,12 @@ class PyPycLoaderMock(abc.PyPycLoader, PyLoaderMock):
self.bytecode_to_path[name] = data['path']
magic = data.get('magic', imp.get_magic())
mtime = importlib._w_long(data.get('mtime', self.default_mtime))
source_size = importlib._w_long(len(self.source) & 0xFFFFFFFF)
if 'bc' in data:
bc = data['bc']
else:
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):
source_path = self.module_paths.get(name, '<test>') or '<test>'
@ -344,7 +345,10 @@ class PyPycLoaderTests(PyLoaderTests):
self.assertEqual(magic, imp.get_magic())
mtime = importlib._r_long(mock.module_bytecode[name][4:8])
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))
def test_module(self):

View File

@ -587,6 +587,7 @@ Vladimir Kushnir
Ross Lagerwall
Cameron Laird
Jean-Baptiste "Jiba" Lamy
Ronan Lamy
Torsten Landschoff
Łukasz Langa
Tino Lange

View File

@ -17,6 +17,9 @@ Core and Builtins
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
files on flush().