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.
diff --git a/Lib/compileall.py b/Lib/compileall.py
index 7259212..7be23a6 100644
--- a/Lib/compileall.py
+++ b/Lib/compileall.py
@@ -53,7 +53,7 @@
def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None,
quiet=0, legacy=False, optimize=-1, workers=1,
- invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP):
+ invalidation_mode=None):
"""Byte-compile all modules in the given directory tree.
Arguments (only dir is required):
@@ -96,7 +96,7 @@
def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0,
legacy=False, optimize=-1,
- invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP):
+ invalidation_mode=None):
"""Byte-compile one file.
Arguments (only fullname is required):
@@ -182,7 +182,7 @@
def compile_path(skip_curdir=1, maxlevels=0, force=False, quiet=0,
legacy=False, optimize=-1,
- invalidation_mode=py_compile.PycInvalidationMode.TIMESTAMP):
+ invalidation_mode=None):
"""Byte-compile all module on sys.path.
Arguments (all optional):
@@ -255,9 +255,12 @@
type=int, help='Run compileall concurrently')
invalidation_modes = [mode.name.lower().replace('_', '-')
for mode in py_compile.PycInvalidationMode]
- parser.add_argument('--invalidation-mode', default='timestamp',
+ parser.add_argument('--invalidation-mode',
choices=sorted(invalidation_modes),
- help='How the pycs will be invalidated at runtime')
+ help=('set .pyc invalidation mode; defaults to '
+ '"checked-hash" if the SOURCE_DATE_EPOCH '
+ 'environment variable is set, and '
+ '"timestamp" otherwise.'))
args = parser.parse_args()
compile_dests = args.compile_dest
@@ -286,8 +289,11 @@
if args.workers is not None:
args.workers = args.workers or None
- ivl_mode = args.invalidation_mode.replace('-', '_').upper()
- invalidation_mode = py_compile.PycInvalidationMode[ivl_mode]
+ if args.invalidation_mode:
+ ivl_mode = args.invalidation_mode.replace('-', '_').upper()
+ invalidation_mode = py_compile.PycInvalidationMode[ivl_mode]
+ else:
+ invalidation_mode = None
success = True
try: