eric7/DebugClients/Python/coverage/execfile.py

branch
eric7
changeset 8775
0802ae193343
parent 8312
800c432b34c8
child 8929
fcca2fa618bf
--- a/eric7/DebugClients/Python/coverage/execfile.py	Fri Nov 19 19:28:47 2021 +0100
+++ b/eric7/DebugClients/Python/coverage/execfile.py	Sat Nov 20 16:47:38 2021 +0100
@@ -3,6 +3,8 @@
 
 """Execute files of Python code."""
 
+import importlib.machinery
+import importlib.util
 import inspect
 import marshal
 import os
@@ -11,17 +13,18 @@
 import types
 
 from coverage import env
-from coverage.backward import BUILTINS
-from coverage.backward import PYC_MAGIC_NUMBER, imp, importlib_util_find_spec
+from coverage.exceptions import CoverageException, ExceptionDuringRun, NoCode, NoSource
 from coverage.files import canonical_filename, python_reported_file
-from coverage.misc import CoverageException, ExceptionDuringRun, NoCode, NoSource, isolate_module
+from coverage.misc import isolate_module
 from coverage.phystokens import compile_unicode
 from coverage.python import get_python_source
 
 os = isolate_module(os)
 
 
-class DummyLoader(object):
+PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER
+
+class DummyLoader:
     """A shim for the pep302 __loader__, emulating pkgutil.ImpLoader.
 
     Currently only implements the .fullname attribute
@@ -30,79 +33,35 @@
         self.fullname = fullname
 
 
-if importlib_util_find_spec:
-    def find_module(modulename):
-        """Find the module named `modulename`.
+def find_module(modulename):
+    """Find the module named `modulename`.
 
-        Returns the file path of the module, the name of the enclosing
-        package, and the spec.
-        """
-        try:
-            spec = importlib_util_find_spec(modulename)
-        except ImportError as err:
-            raise NoSource(str(err))
+    Returns the file path of the module, the name of the enclosing
+    package, and the spec.
+    """
+    try:
+        spec = importlib.util.find_spec(modulename)
+    except ImportError as err:
+        raise NoSource(str(err)) from err
+    if not spec:
+        raise NoSource(f"No module named {modulename!r}")
+    pathname = spec.origin
+    packagename = spec.name
+    if spec.submodule_search_locations:
+        mod_main = modulename + ".__main__"
+        spec = importlib.util.find_spec(mod_main)
         if not spec:
-            raise NoSource("No module named %r" % (modulename,))
+            raise NoSource(
+                f"No module named {mod_main}; " +
+                f"{modulename!r} is a package and cannot be directly executed"
+            )
         pathname = spec.origin
         packagename = spec.name
-        if spec.submodule_search_locations:
-            mod_main = modulename + ".__main__"
-            spec = importlib_util_find_spec(mod_main)
-            if not spec:
-                raise NoSource(
-                    "No module named %s; "
-                    "%r is a package and cannot be directly executed"
-                    % (mod_main, modulename)
-                )
-            pathname = spec.origin
-            packagename = spec.name
-        packagename = packagename.rpartition(".")[0]
-        return pathname, packagename, spec
-else:
-    def find_module(modulename):
-        """Find the module named `modulename`.
-
-        Returns the file path of the module, the name of the enclosing
-        package, and None (where a spec would have been).
-        """
-        openfile = None
-        glo, loc = globals(), locals()
-        try:
-            # Search for the module - inside its parent package, if any - using
-            # standard import mechanics.
-            if '.' in modulename:
-                packagename, name = modulename.rsplit('.', 1)
-                package = __import__(packagename, glo, loc, ['__path__'])
-                searchpath = package.__path__
-            else:
-                packagename, name = None, modulename
-                searchpath = None  # "top-level search" in imp.find_module()
-            openfile, pathname, _ = imp.find_module(name, searchpath)
-
-            # Complain if this is a magic non-file module.
-            if openfile is None and pathname is None:
-                raise NoSource(
-                    "module does not live in a file: %r" % modulename
-                    )
-
-            # If `modulename` is actually a package, not a mere module, then we
-            # pretend to be Python 2.7 and try running its __main__.py script.
-            if openfile is None:
-                packagename = modulename
-                name = '__main__'
-                package = __import__(packagename, glo, loc, ['__path__'])
-                searchpath = package.__path__
-                openfile, pathname, _ = imp.find_module(name, searchpath)
-        except ImportError as err:
-            raise NoSource(str(err))
-        finally:
-            if openfile:
-                openfile.close()
-
-        return pathname, packagename, None
+    packagename = packagename.rpartition(".")[0]
+    return pathname, packagename, spec
 
 
-class PyRunner(object):
+class PyRunner:
     """Multi-stage execution of Python code.
 
     This is meant to emulate real Python execution as closely as possible.
@@ -176,29 +135,25 @@
             # directory.
             for ext in [".py", ".pyc", ".pyo"]:
                 try_filename = os.path.join(self.arg0, "__main__" + ext)
+                # 3.8.10 changed how files are reported when running a
+                # directory.  But I'm not sure how far this change is going to
+                # spread, so I'll just hard-code it here for now.
+                if env.PYVERSION >= (3, 8, 10):
+                    try_filename = os.path.abspath(try_filename)
                 if os.path.exists(try_filename):
                     self.arg0 = try_filename
                     break
             else:
                 raise NoSource("Can't find '__main__' module in '%s'" % self.arg0)
 
-            if env.PY2:
-                self.arg0 = os.path.abspath(self.arg0)
-
             # Make a spec. I don't know if this is the right way to do it.
-            try:
-                import importlib.machinery
-            except ImportError:
-                pass
-            else:
-                try_filename = python_reported_file(try_filename)
-                self.spec = importlib.machinery.ModuleSpec("__main__", None, origin=try_filename)
-                self.spec.has_location = True
+            try_filename = python_reported_file(try_filename)
+            self.spec = importlib.machinery.ModuleSpec("__main__", None, origin=try_filename)
+            self.spec.has_location = True
             self.package = ""
             self.loader = DummyLoader("__main__")
         else:
-            if env.PY3:
-                self.loader = DummyLoader("__main__")
+            self.loader = DummyLoader("__main__")
 
         self.arg0 = python_reported_file(self.arg0)
 
@@ -220,7 +175,7 @@
         if self.spec is not None:
             main_mod.__spec__ = self.spec
 
-        main_mod.__builtins__ = BUILTINS
+        main_mod.__builtins__ = sys.modules['builtins']
 
         sys.modules['__main__'] = main_mod
 
@@ -236,8 +191,8 @@
         except CoverageException:
             raise
         except Exception as exc:
-            msg = "Couldn't run '{filename}' as Python code: {exc.__class__.__name__}: {exc}"
-            raise CoverageException(msg.format(filename=self.arg0, exc=exc))
+            msg = f"Couldn't run '{self.arg0}' as Python code: {exc.__class__.__name__}: {exc}"
+            raise CoverageException(msg) from exc
 
         # Execute the code object.
         # Return to the original directory in case the test code exits in
@@ -265,22 +220,20 @@
 
             # Call the excepthook.
             try:
-                if hasattr(err, "__traceback__"):
-                    err.__traceback__ = err.__traceback__.tb_next
+                err.__traceback__ = err.__traceback__.tb_next
                 sys.excepthook(typ, err, tb.tb_next)
             except SystemExit:                      # pylint: disable=try-except-raise
                 raise
-            except Exception:
+            except Exception as exc:
                 # 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
+                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)
+                raise ExceptionDuringRun(typ, err, tb.tb_next) from exc
             else:
                 sys.exit(1)
         finally:
@@ -321,8 +274,8 @@
     # Open the source file.
     try:
         source = get_python_source(filename)
-    except (IOError, NoSource):
-        raise NoSource("No file to run: '%s'" % filename)
+    except (OSError, NoSource) as exc:
+        raise NoSource(f"No file to run: '{filename}'") from exc
 
     code = compile_unicode(source, filename, "exec")
     return code
@@ -332,15 +285,15 @@
     """Get a code object from a .pyc file."""
     try:
         fpyc = open(filename, "rb")
-    except IOError:
-        raise NoCode("No file to run: '%s'" % filename)
+    except OSError as exc:
+        raise NoCode(f"No file to run: '{filename}'") from exc
 
     with fpyc:
         # First four bytes are a version-specific magic number.  It has to
         # match or we won't run the file.
         magic = fpyc.read(4)
         if magic != PYC_MAGIC_NUMBER:
-            raise NoCode("Bad magic number in .pyc file: {} != {}".format(magic, PYC_MAGIC_NUMBER))
+            raise NoCode(f"Bad magic number in .pyc file: {magic} != {PYC_MAGIC_NUMBER}")
 
         date_based = True
         if env.PYBEHAVIOR.hashed_pyc_pep552:
@@ -352,9 +305,8 @@
         if date_based:
             # Skip the junk in the header that we don't need.
             fpyc.read(4)            # Skip the moddate.
-            if env.PYBEHAVIOR.size_in_pyc:
-                # 3.3 added another long to the header (size), skip it.
-                fpyc.read(4)
+            # 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