summaryrefslogtreecommitdiff
path: root/src/_pytest
diff options
context:
space:
mode:
authorRan Benita <ran@unusedvar.com>2020-11-14 23:38:45 +0200
committerGitHub <noreply@github.com>2020-11-14 23:38:45 +0200
commit825b81ba523cb660a3bfc8d68317dab61f5a4753 (patch)
tree9af5a5abeab3802578ddda5d1aeabf6ed4da5adc /src/_pytest
parent767cbeb0865fd0b3bdf4b1161755183eadf5d2aa (diff)
parent1d532da49ec7e25ff9d78509a61c3aa82a29b482 (diff)
downloadpytest-825b81ba523cb660a3bfc8d68317dab61f5a4753.tar.gz
Merge pull request #8014 from bluetech/pyc-pep552
assertion/rewrite: write pyc's according to PEP-552 on Python>=3.7
Diffstat (limited to 'src/_pytest')
-rw-r--r--src/_pytest/assertion/rewrite.py34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py
index 649726727..805d4c8b3 100644
--- a/src/_pytest/assertion/rewrite.py
+++ b/src/_pytest/assertion/rewrite.py
@@ -281,12 +281,16 @@ def _write_pyc_fp(
) -> None:
# Technically, we don't have to have the same pyc format as
# (C)Python, since these "pycs" should never be seen by builtin
- # import. However, there's little reason deviate.
+ # import. However, there's little reason to deviate.
fp.write(importlib.util.MAGIC_NUMBER)
+ # https://www.python.org/dev/peps/pep-0552/
+ if sys.version_info >= (3, 7):
+ flags = b"\x00\x00\x00\x00"
+ fp.write(flags)
# as of now, bytecode header expects 32-bit numbers for size and mtime (#4903)
mtime = int(source_stat.st_mtime) & 0xFFFFFFFF
size = source_stat.st_size & 0xFFFFFFFF
- # "<LL" stands for 2 unsigned longs, little-ending
+ # "<LL" stands for 2 unsigned longs, little-endian.
fp.write(struct.pack("<LL", mtime, size))
fp.write(marshal.dumps(co))
@@ -365,21 +369,33 @@ def _read_pyc(
except OSError:
return None
with fp:
+ # https://www.python.org/dev/peps/pep-0552/
+ has_flags = sys.version_info >= (3, 7)
try:
stat_result = os.stat(os.fspath(source))
mtime = int(stat_result.st_mtime)
size = stat_result.st_size
- data = fp.read(12)
+ data = fp.read(16 if has_flags else 12)
except OSError as e:
trace(f"_read_pyc({source}): OSError {e}")
return None
# Check for invalid or out of date pyc file.
- if (
- len(data) != 12
- or data[:4] != importlib.util.MAGIC_NUMBER
- or struct.unpack("<LL", data[4:]) != (mtime & 0xFFFFFFFF, size & 0xFFFFFFFF)
- ):
- trace("_read_pyc(%s): invalid or out of date pyc" % source)
+ if len(data) != (16 if has_flags else 12):
+ trace("_read_pyc(%s): invalid pyc (too short)" % source)
+ return None
+ if data[:4] != importlib.util.MAGIC_NUMBER:
+ trace("_read_pyc(%s): invalid pyc (bad magic number)" % source)
+ return None
+ if has_flags and data[4:8] != b"\x00\x00\x00\x00":
+ trace("_read_pyc(%s): invalid pyc (unsupported flags)" % source)
+ return None
+ mtime_data = data[8 if has_flags else 4 : 12 if has_flags else 8]
+ if int.from_bytes(mtime_data, "little") != mtime & 0xFFFFFFFF:
+ trace("_read_pyc(%s): out of date" % source)
+ return None
+ size_data = data[12 if has_flags else 8 : 16 if has_flags else 12]
+ if int.from_bytes(size_data, "little") != size & 0xFFFFFFFF:
+ trace("_read_pyc(%s): invalid pyc (incorrect size)" % source)
return None
try:
co = marshal.load(fp)