summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2018-01-10 21:47:09 -0500
committerNed Batchelder <ned@nedbatchelder.com>2018-01-10 21:47:09 -0500
commite3761571cfe9c21baa138d58c1f304bdbca572ae (patch)
treec621d6290307736ca8951296cd1135a91dae18d7
parent74e7651c2500eb4f39bf8bf8f39c591d20b81fe3 (diff)
downloadpython-coveragepy-git-e3761571cfe9c21baa138d58c1f304bdbca572ae.tar.gz
Python 3.7 tweaked the layout of .pyc files
-rw-r--r--coverage/execfile.py19
-rw-r--r--lab/show_pyc.py25
2 files changed, 32 insertions, 12 deletions
diff --git a/coverage/execfile.py b/coverage/execfile.py
index 693f54fb..ffe3ca18 100644
--- a/coverage/execfile.py
+++ b/coverage/execfile.py
@@ -5,6 +5,7 @@
import marshal
import os
+import struct
import sys
import types
@@ -253,11 +254,19 @@ def make_code_from_pyc(filename):
if magic != PYC_MAGIC_NUMBER:
raise NoCode("Bad magic number in .pyc file")
- # Skip the junk in the header that we don't need.
- fpyc.read(4) # Skip the moddate.
- if sys.version_info >= (3, 3):
- # 3.3 added another long to the header (size), skip it.
- fpyc.read(4)
+ date_based = True
+ if sys.version_info >= (3, 7):
+ flags = struct.unpack('<L', fpyc.read(4))[0]
+ hash_based = flags & 0x01
+ if hash_based:
+ fpyc.read(8) # Skip the hash.
+ date_based = False
+ if date_based:
+ # Skip the junk in the header that we don't need.
+ fpyc.read(4) # Skip the moddate.
+ if sys.version_info >= (3, 3):
+ # 3.3 added another long to the header (size), skip it.
+ fpyc.read(4)
# The rest of the file is the code object we want.
code = marshal.load(fpyc)
diff --git a/lab/show_pyc.py b/lab/show_pyc.py
index 0a28e4fb..525797a8 100644
--- a/lab/show_pyc.py
+++ b/lab/show_pyc.py
@@ -13,14 +13,25 @@ import types
def show_pyc_file(fname):
f = open(fname, "rb")
magic = f.read(4)
- moddate = f.read(4)
- modtime = time.asctime(time.localtime(struct.unpack('<L', moddate)[0]))
print("magic %s" % (binascii.hexlify(magic)))
- print("moddate %s (%s)" % (binascii.hexlify(moddate), modtime))
- if sys.version_info >= (3, 3):
- # 3.3 added another long to the header (size).
- size = f.read(4)
- print("pysize %s (%d)" % (binascii.hexlify(size), struct.unpack('<L', size)[0]))
+ read_date_and_size = True
+ if sys.version_info >= (3, 7):
+ # 3.7 added a flags word
+ flags = struct.unpack('<L', f.read(4))[0]
+ hash_based = flags & 0x01
+ check_source = flags & 0x02
+ print("flags 0x%08x" % (flags,))
+ if hash_based:
+ source_hash = f.read(8)
+ read_date_and_size = False
+ if read_date_and_size:
+ moddate = f.read(4)
+ modtime = time.asctime(time.localtime(struct.unpack('<L', moddate)[0]))
+ print("moddate %s (%s)" % (binascii.hexlify(moddate), modtime))
+ if sys.version_info >= (3, 3):
+ # 3.3 added another long to the header (size).
+ size = f.read(4)
+ print("pysize %s (%d)" % (binascii.hexlify(size), struct.unpack('<L', size)[0]))
code = marshal.load(f)
show_code(code)