DebugClients/Python/coverage/execfile.py

changeset 6219
d6c795b5ce33
parent 5178
878ce843ca9f
child 6649
f1b3a73831c9
diff -r bedab77d0fa3 -r d6c795b5ce33 DebugClients/Python/coverage/execfile.py
--- a/DebugClients/Python/coverage/execfile.py	Sat Apr 07 13:17:06 2018 +0200
+++ b/DebugClients/Python/coverage/execfile.py	Sat Apr 07 13:35:10 2018 +0200
@@ -5,12 +5,13 @@
 
 import marshal
 import os
+import struct
 import sys
 import types
 
 from coverage.backward import BUILTINS
 from coverage.backward import PYC_MAGIC_NUMBER, imp, importlib_util_find_spec
-from coverage.misc import ExceptionDuringRun, NoCode, NoSource, isolate_module
+from coverage.misc import CoverageException, ExceptionDuringRun, NoCode, NoSource, isolate_module
 from coverage.phystokens import compile_unicode
 from coverage.python import get_python_source
 
@@ -166,11 +167,17 @@
     sys.path[0] = path0 if path0 is not None else my_path0
 
     try:
-        # Make a code object somehow.
-        if filename.endswith((".pyc", ".pyo")):
-            code = make_code_from_pyc(filename)
-        else:
-            code = make_code_from_py(filename)
+        try:
+            # Make a code object somehow.
+            if filename.endswith((".pyc", ".pyo")):
+                code = make_code_from_pyc(filename)
+            else:
+                code = make_code_from_py(filename)
+        except CoverageException:
+            raise
+        except Exception as exc:
+            msg = "Couldn't run {filename!r} as Python code: {exc.__class__.__name__}: {exc}"
+            raise CoverageException(msg.format(filename=filename, exc=exc))
 
         # Execute the code object.
         try:
@@ -179,7 +186,7 @@
             # The user called sys.exit().  Just pass it along to the upper
             # layers, where it will be handled.
             raise
-        except:
+        except Exception:
             # Something went wrong while executing the user code.
             # Get the exc_info, and pack them into an exception that we can
             # throw up to the outer loop.  We peel one layer off the traceback
@@ -193,7 +200,27 @@
             # it somehow? https://bitbucket.org/pypy/pypy/issue/1903
             getattr(err, '__context__', None)
 
-            raise ExceptionDuringRun(typ, err, tb.tb_next)
+            # Call the excepthook.
+            try:
+                if hasattr(err, "__traceback__"):
+                    err.__traceback__ = err.__traceback__.tb_next
+                sys.excepthook(typ, err, tb.tb_next)
+            except SystemExit:
+                raise
+            except Exception:
+                # Getting the output right in the case of excepthook
+                # shenanigans is kind of involved.
+                sys.stderr.write("Error in sys.excepthook:\n")
+                typ2, err2, tb2 = sys.exc_info()
+                err2.__suppress_context__ = True
+                if hasattr(err2, "__traceback__"):
+                    err2.__traceback__ = err2.__traceback__.tb_next
+                sys.__excepthook__(typ2, err2, tb2.tb_next)
+                sys.stderr.write("\nOriginal exception was:\n")
+                raise ExceptionDuringRun(typ, err, tb.tb_next)
+            else:
+                sys.exit(1)
+
     finally:
         # Restore the old __main__, argv, and path.
         sys.modules['__main__'] = old_main_mod
@@ -227,11 +254,19 @@
         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, 0, 'alpha', 4):
+            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)

eric ide

mercurial