-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-34022: Stop forcing of hash-based invalidation with SOURCE_DATE_EPOCH #9607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,10 +54,10 @@ byte-code cache files in the directory containing the source code. | |
level of the current interpreter. | ||
|
||
*invalidation_mode* should be a member of the :class:`PycInvalidationMode` | ||
enum and controls how the generated ``.pyc`` files are invalidated at | ||
runtime. If the :envvar:`SOURCE_DATE_EPOCH` environment variable is set, | ||
*invalidation_mode* will be forced to | ||
:attr:`PycInvalidationMode.CHECKED_HASH`. | ||
enum and controls how the generated bytecode cache is invalidated at | ||
runtime. The default is :attr:`PycInvalidationMode.CHECKED_HASH` if | ||
the :envvar:`SOURCE_DATE_EPOCH` environment variable is set, otherwise | ||
the default is :attr:`PycInvalidationMode.TIMESTAMP`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a reference to the PEP 552 somewhere (you can use syntax :pep: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PEP 552 actually has no mention of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. invalidation_mode is a new thing coming from the PEP 552. Moreover, I proposed to update the PEP: |
||
|
||
.. versionchanged:: 3.2 | ||
Changed default value of *cfile* to be :PEP:`3147`-compliant. Previous | ||
|
@@ -77,6 +77,11 @@ byte-code cache files in the directory containing the source code. | |
*invalidation_mode* will be forced to | ||
:attr:`PycInvalidationMode.CHECKED_HASH`. | ||
|
||
.. versionchanged:: 3.7.2 | ||
The :envvar:`SOURCE_DATE_EPOCH` environment variable no longer | ||
overrides the value of the *invalidation_mode* argument, and determines | ||
its default value instead. | ||
|
||
|
||
.. class:: PycInvalidationMode | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import functools | ||
import importlib.util | ||
import os | ||
import py_compile | ||
|
@@ -10,7 +11,44 @@ | |
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') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there at least one unit test for SOURCE_DATE_EPOCH set to an empty string? |
||
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 @@ def test_bad_coding(self): | |
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 @@ def test_invalidation_mode(self): | |
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() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
The :envvar:`SOURCE_DATE_EPOCH` environment variable no longer overrides the | ||
value of the *invalidation_mode* argument to :func:`py_compile.compile`, and | ||
determines its default value instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"is set": I suggest "is set to a non-empty string". See other existing examples:
https://docs.python.org/dev/using/cmdline.html#envvar-PYTHONOPTIMIZE
Maybe add a reference to the PEP 552 somewhere (you can use syntax :pep:
552
).By the way, should we mention SOURCE_DATE_EPOCH somewhere in https://docs.python.org/dev/using/cmdline.html ? The variable is not specific to Python, but it changes its behavior.