mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-34022: Stop forcing of hash-based invalidation with SOURCE_DATE_EPOCH (GH-9607)
Unconditional forcing of ``CHECKED_HASH`` invalidation was introduced in 3.7.0 in bpo-29708. The change is bad, as it unconditionally overrides *invalidation_mode*, even if it was passed as an explicit argument to ``py_compile.compile()`` or ``compileall``. An environment variable should *never* override an explicit argument to a library function. That change leads to multiple test failures if the ``SOURCE_DATE_EPOCH`` environment variable is set. This changes ``py_compile.compile()`` to only look at ``SOURCE_DATE_EPOCH`` if no explicit *invalidation_mode* was specified. I also made various relevant tests run with explicit control over the value of ``SOURCE_DATE_EPOCH``. While looking at this, I noticed that ``zipimport`` does not work with hash-based .pycs _at all_, though I left the fixes for subsequent commits.
This commit is contained in:
parent
7e18deef65
commit
a6b3ec5b6d
8 changed files with 161 additions and 30 deletions
|
@ -22,7 +22,11 @@ except ImportError:
|
|||
from test import support
|
||||
from test.support import script_helper
|
||||
|
||||
class CompileallTests(unittest.TestCase):
|
||||
from .test_py_compile import without_source_date_epoch
|
||||
from .test_py_compile import SourceDateEpochTestMeta
|
||||
|
||||
|
||||
class CompileallTestsBase:
|
||||
|
||||
def setUp(self):
|
||||
self.directory = tempfile.mkdtemp()
|
||||
|
@ -46,7 +50,7 @@ class CompileallTests(unittest.TestCase):
|
|||
with open(self.bad_source_path, 'w') as file:
|
||||
file.write('x (\n')
|
||||
|
||||
def data(self):
|
||||
def timestamp_metadata(self):
|
||||
with open(self.bc_path, 'rb') as file:
|
||||
data = file.read(12)
|
||||
mtime = int(os.stat(self.source_path).st_mtime)
|
||||
|
@ -57,16 +61,18 @@ class CompileallTests(unittest.TestCase):
|
|||
def recreation_check(self, metadata):
|
||||
"""Check that compileall recreates bytecode when the new metadata is
|
||||
used."""
|
||||
if os.environ.get('SOURCE_DATE_EPOCH'):
|
||||
raise unittest.SkipTest('SOURCE_DATE_EPOCH is set')
|
||||
py_compile.compile(self.source_path)
|
||||
self.assertEqual(*self.data())
|
||||
self.assertEqual(*self.timestamp_metadata())
|
||||
with open(self.bc_path, 'rb') as file:
|
||||
bc = file.read()[len(metadata):]
|
||||
with open(self.bc_path, 'wb') as file:
|
||||
file.write(metadata)
|
||||
file.write(bc)
|
||||
self.assertNotEqual(*self.data())
|
||||
self.assertNotEqual(*self.timestamp_metadata())
|
||||
compileall.compile_dir(self.directory, force=False, quiet=True)
|
||||
self.assertTrue(*self.data())
|
||||
self.assertTrue(*self.timestamp_metadata())
|
||||
|
||||
def test_mtime(self):
|
||||
# Test a change in mtime leads to a new .pyc.
|
||||
|
@ -189,6 +195,21 @@ class CompileallTests(unittest.TestCase):
|
|||
compileall.compile_dir(self.directory, quiet=True, workers=5)
|
||||
self.assertTrue(compile_file_mock.called)
|
||||
|
||||
|
||||
class CompileallTestsWithSourceEpoch(CompileallTestsBase,
|
||||
unittest.TestCase,
|
||||
metaclass=SourceDateEpochTestMeta,
|
||||
source_date_epoch=True):
|
||||
pass
|
||||
|
||||
|
||||
class CompileallTestsWithoutSourceEpoch(CompileallTestsBase,
|
||||
unittest.TestCase,
|
||||
metaclass=SourceDateEpochTestMeta,
|
||||
source_date_epoch=False):
|
||||
pass
|
||||
|
||||
|
||||
class EncodingTest(unittest.TestCase):
|
||||
"""Issue 6716: compileall should escape source code when printing errors
|
||||
to stdout."""
|
||||
|
@ -212,7 +233,7 @@ class EncodingTest(unittest.TestCase):
|
|||
sys.stdout = orig_stdout
|
||||
|
||||
|
||||
class CommandLineTests(unittest.TestCase):
|
||||
class CommandLineTestsBase:
|
||||
"""Test compileall's CLI."""
|
||||
|
||||
@classmethod
|
||||
|
@ -285,6 +306,7 @@ class CommandLineTests(unittest.TestCase):
|
|||
self.assertNotCompiled(self.initfn)
|
||||
self.assertNotCompiled(self.barfn)
|
||||
|
||||
@without_source_date_epoch # timestamp invalidation test
|
||||
def test_no_args_respects_force_flag(self):
|
||||
self._skip_if_sys_path_not_writable()
|
||||
bazfn = script_helper.make_script(self.directory, 'baz', '')
|
||||
|
@ -353,6 +375,7 @@ class CommandLineTests(unittest.TestCase):
|
|||
self.assertTrue(os.path.exists(self.pkgdir_cachedir))
|
||||
self.assertFalse(os.path.exists(cachecachedir))
|
||||
|
||||
@without_source_date_epoch # timestamp invalidation test
|
||||
def test_force(self):
|
||||
self.assertRunOK('-q', self.pkgdir)
|
||||
pycpath = importlib.util.cache_from_source(self.barfn)
|
||||
|
@ -556,5 +579,20 @@ class CommandLineTests(unittest.TestCase):
|
|||
self.assertEqual(compile_dir.call_args[-1]['workers'], None)
|
||||
|
||||
|
||||
class CommmandLineTestsWithSourceEpoch(CommandLineTestsBase,
|
||||
unittest.TestCase,
|
||||
metaclass=SourceDateEpochTestMeta,
|
||||
source_date_epoch=True):
|
||||
pass
|
||||
|
||||
|
||||
class CommmandLineTestsNoSourceEpoch(CommandLineTestsBase,
|
||||
unittest.TestCase,
|
||||
metaclass=SourceDateEpochTestMeta,
|
||||
source_date_epoch=False):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue