summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_py_compile.py
diff options
context:
space:
mode:
authorElvis Pranskevichus <elvis@magic.io>2018-10-10 16:43:14 (GMT)
committerVictor Stinner <vstinner@redhat.com>2018-10-10 16:43:14 (GMT)
commita6b3ec5b6d4f6387820fccc570eea08b9615620d (patch)
tree0a4cda67f41ce3e6237f4614c890e73d666e69b5 /Lib/test/test_py_compile.py
parent7e18deef652a9d413d5dbd19d61073ba7eb5460e (diff)
downloadcpython-a6b3ec5b6d4f6387820fccc570eea08b9615620d.zip
cpython-a6b3ec5b6d4f6387820fccc570eea08b9615620d.tar.gz
cpython-a6b3ec5b6d4f6387820fccc570eea08b9615620d.tar.bz2
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.
Diffstat (limited to 'Lib/test/test_py_compile.py')
-rw-r--r--Lib/test/test_py_compile.py66
1 files changed, 60 insertions, 6 deletions
diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py
index 8fc0b33..f86abe2 100644
--- a/Lib/test/test_py_compile.py
+++ b/Lib/test/test_py_compile.py
@@ -1,3 +1,4 @@
+import functools
import importlib.util
import os
import py_compile
@@ -10,7 +11,44 @@ import unittest
from test import support
-class PyCompileTests(unittest.TestCase):
+def without_source_date_epoch(fxn):
+ """Runs function with SOURCE_DATE_EPOCH unset."""
+ @functools.wraps(fxn)
+ def wrapper(*args, **kwargs):
+ with support.EnvironmentVarGuard() as env:
+ env.unset('SOURCE_DATE_EPOCH')
+ return fxn(*args, **kwargs)
+ return wrapper
+
+
+def with_source_date_epoch(fxn):
+ """Runs function with SOURCE_DATE_EPOCH set."""
+ @functools.wraps(fxn)
+ def wrapper(*args, **kwargs):
+ with support.EnvironmentVarGuard() as env:
+ env['SOURCE_DATE_EPOCH'] = '123456789'
+ return fxn(*args, **kwargs)
+ return wrapper
+
+
+# Run tests with SOURCE_DATE_EPOCH set or unset explicitly.
+class SourceDateEpochTestMeta(type(unittest.TestCase)):
+ def __new__(mcls, name, bases, dct, *, source_date_epoch):
+ cls = super().__new__(mcls, name, bases, dct)
+
+ for attr in dir(cls):
+ if attr.startswith('test_'):
+ meth = getattr(cls, attr)
+ if source_date_epoch:
+ wrapper = with_source_date_epoch(meth)
+ else:
+ wrapper = without_source_date_epoch(meth)
+ setattr(cls, attr, wrapper)
+
+ return cls
+
+
+class PyCompileTestsBase:
def setUp(self):
self.directory = tempfile.mkdtemp()
@@ -99,16 +137,18 @@ class PyCompileTests(unittest.TestCase):
importlib.util.cache_from_source(bad_coding)))
def test_source_date_epoch(self):
- testtime = 123456789
- with support.EnvironmentVarGuard() as env:
- env["SOURCE_DATE_EPOCH"] = str(testtime)
- py_compile.compile(self.source_path, self.pyc_path)
+ py_compile.compile(self.source_path, self.pyc_path)
self.assertTrue(os.path.exists(self.pyc_path))
self.assertFalse(os.path.exists(self.cache_path))
with open(self.pyc_path, 'rb') as fp:
flags = importlib._bootstrap_external._classify_pyc(
fp.read(), 'test', {})
- self.assertEqual(flags, 0b11)
+ if os.environ.get('SOURCE_DATE_EPOCH'):
+ expected_flags = 0b11
+ else:
+ expected_flags = 0b00
+
+ self.assertEqual(flags, expected_flags)
@unittest.skipIf(sys.flags.optimize > 0, 'test does not work with -O')
def test_double_dot_no_clobber(self):
@@ -153,5 +193,19 @@ class PyCompileTests(unittest.TestCase):
self.assertEqual(flags, 0b1)
+class PyCompileTestsWithSourceEpoch(PyCompileTestsBase,
+ unittest.TestCase,
+ metaclass=SourceDateEpochTestMeta,
+ source_date_epoch=True):
+ pass
+
+
+class PyCompileTestsWithoutSourceEpoch(PyCompileTestsBase,
+ unittest.TestCase,
+ metaclass=SourceDateEpochTestMeta,
+ source_date_epoch=False):
+ pass
+
+
if __name__ == "__main__":
unittest.main()