Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ccbe581

Browse filesBrowse files
bmwiedemannbrettcannon
authored andcommitted
bpo-29708: Setting SOURCE_DATE_EPOCH forces hash-based .pyc files (GH-5200)
To support reproducible builds, the setting of of SOURCE_DATE_EPOCH triggers the py_compile module -- and by extension, compileall -- to forcibly compile with hash-based .pyc files. This eliminates the possibility of timestamp-based .pyc files which vary between builds.
1 parent 6f6eb35 commit ccbe581
Copy full SHA for ccbe581

File tree

4 files changed

+22
-1
lines changed
Filter options

4 files changed

+22
-1
lines changed

‎Doc/library/py_compile.rst

Copy file name to clipboardExpand all lines: Doc/library/py_compile.rst
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ byte-code cache files in the directory containing the source code.
5555

5656
*invalidation_mode* should be a member of the :class:`PycInvalidationMode`
5757
enum and controls how the generated ``.pyc`` files are invalidated at
58-
runtime.
58+
runtime. If the :envvar:`SOURCE_DATE_EPOCH` environment variable is set,
59+
*invalidation_mode* will be forced to
60+
:attr:`PycInvalidationMode.CHECKED_HASH`.
5961

6062
.. versionchanged:: 3.2
6163
Changed default value of *cfile* to be :PEP:`3147`-compliant. Previous
@@ -71,6 +73,9 @@ byte-code cache files in the directory containing the source code.
7173

7274
.. versionchanged:: 3.7
7375
The *invalidation_mode* parameter was added as specified in :pep:`552`.
76+
If the :envvar:`SOURCE_DATE_EPOCH` environment variable is set,
77+
*invalidation_mode* will be forced to
78+
:attr:`PycInvalidationMode.CHECKED_HASH`.
7479

7580

7681
.. class:: PycInvalidationMode

‎Lib/py_compile.py

Copy file name to clipboardExpand all lines: Lib/py_compile.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1,
112112
the resulting file would be regular and thus not the same type of file as
113113
it was previously.
114114
"""
115+
if os.environ.get('SOURCE_DATE_EPOCH'):
116+
invalidation_mode = PycInvalidationMode.CHECKED_HASH
115117
if cfile is None:
116118
if optimize >= 0:
117119
optimization = optimize if optimize >= 1 else ''

‎Lib/test/test_py_compile.py

Copy file name to clipboardExpand all lines: Lib/test/test_py_compile.py
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ def test_bad_coding(self):
9898
self.assertFalse(os.path.exists(
9999
importlib.util.cache_from_source(bad_coding)))
100100

101+
def test_source_date_epoch(self):
102+
testtime = 123456789
103+
with support.EnvironmentVarGuard() as env:
104+
env["SOURCE_DATE_EPOCH"] = str(testtime)
105+
py_compile.compile(self.source_path, self.pyc_path)
106+
self.assertTrue(os.path.exists(self.pyc_path))
107+
self.assertFalse(os.path.exists(self.cache_path))
108+
with open(self.pyc_path, 'rb') as fp:
109+
flags = importlib._bootstrap_external._classify_pyc(
110+
fp.read(), 'test', {})
111+
self.assertEqual(flags, 0b11)
112+
101113
@unittest.skipIf(sys.flags.optimize > 0, 'test does not work with -O')
102114
def test_double_dot_no_clobber(self):
103115
# http://bugs.python.org/issue22966
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
If the :envvar:`SOURCE_DATE_EPOCH` environment variable is set,
2+
:mod:`py_compile` will always create hash-based ``.pyc`` files.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.