eric7/DebugClients/Python/coverage/collector.py

branch
eric7
changeset 8775
0802ae193343
parent 8527
2bd1325d727e
child 8929
fcca2fa618bf
--- a/eric7/DebugClients/Python/coverage/collector.py	Fri Nov 19 19:28:47 2021 +0100
+++ b/eric7/DebugClients/Python/coverage/collector.py	Sat Nov 20 16:47:38 2021 +0100
@@ -7,10 +7,10 @@
 import sys
 
 from coverage import env
-from coverage.backward import litems, range     # pylint: disable=redefined-builtin
 from coverage.debug import short_stack
 from coverage.disposition import FileDisposition
-from coverage.misc import CoverageException, isolate_module
+from coverage.exceptions import CoverageException
+from coverage.misc import human_sorted, isolate_module
 from coverage.pytracer import PyTracer
 
 os = isolate_module(os)
@@ -21,7 +21,7 @@
     from coverage.tracer import CTracer, CFileDisposition
 except ImportError:
     # Couldn't import the C extension, maybe it isn't built.
-    if os.getenv('COVERAGE_TEST_TRACER') == 'c':
+    if os.getenv('COVERAGE_TEST_TRACER') == 'c':        # pragma: part covered
         # During testing, we use the COVERAGE_TEST_TRACER environment variable
         # to indicate that we've fiddled with the environment to test this
         # fallback code.  If we thought we had a C tracer, but couldn't import
@@ -33,7 +33,7 @@
     CTracer = None
 
 
-class Collector(object):
+class Collector:
     """Collects trace data.
 
     Creates a Tracer object for each thread, since they track stack
@@ -116,7 +116,7 @@
         # We can handle a few concurrency options here, but only one at a time.
         these_concurrencies = self.SUPPORTED_CONCURRENCIES.intersection(concurrency)
         if len(these_concurrencies) > 1:
-            raise CoverageException("Conflicting concurrency settings: %s" % concurrency)
+            raise CoverageException(f"Conflicting concurrency settings: {concurrency}")
         self.concurrency = these_concurrencies.pop() if these_concurrencies else ''
 
         try:
@@ -136,13 +136,13 @@
                 import threading
                 self.threading = threading
             else:
-                raise CoverageException("Don't understand concurrency=%s" % concurrency)
-        except ImportError:
+                raise CoverageException(f"Don't understand concurrency={concurrency}")
+        except ImportError as ex:
             raise CoverageException(
-                "Couldn't trace with concurrency=%s, the module isn't installed." % (
+                "Couldn't trace with concurrency={}, the module isn't installed.".format(
                     self.concurrency,
                 )
-            )
+            ) from ex
 
         self.reset()
 
@@ -157,12 +157,14 @@
         if self._trace_class is CTracer:
             self.file_disposition_class = CFileDisposition
             self.supports_plugins = True
+            self.packed_arcs = True
         else:
             self.file_disposition_class = FileDisposition
             self.supports_plugins = False
+            self.packed_arcs = False
 
     def __repr__(self):
-        return "<Collector at 0x%x: %s>" % (id(self), self.tracer_name())
+        return f"<Collector at 0x{id(self):x}: {self.tracer_name()}>"
 
     def use_data(self, covdata, context):
         """Use `covdata` for recording data."""
@@ -244,7 +246,7 @@
             tracer.concur_id_func = self.concur_id_func
         elif self.concur_id_func:
             raise CoverageException(
-                "Can't support concurrency=%s with %s, only threads are supported" % (
+                "Can't support concurrency={} with {}, only threads are supported".format(
                     self.concurrency, self.tracer_name(),
                 )
             )
@@ -318,8 +320,8 @@
             (frame, event, arg), lineno = args
             try:
                 fn(frame, event, arg, lineno=lineno)
-            except TypeError:
-                raise Exception("fullcoverage must be run with the C trace function.")
+            except TypeError as ex:
+                raise Exception("fullcoverage must be run with the C trace function.") from ex
 
         # Install our installation tracer in threading, to jump-start other
         # threads.
@@ -332,9 +334,9 @@
         if self._collectors[-1] is not self:
             print("self._collectors:")
             for c in self._collectors:
-                print("  {!r}\n{}".format(c, c.origin))
+                print(f"  {c!r}\n{c.origin}")
         assert self._collectors[-1] is self, (
-            "Expected current collector to be %r, but it's %r" % (self, self._collectors[-1])
+            f"Expected current collector to be {self!r}, but it's {self._collectors[-1]!r}"
         )
 
         self.pause()
@@ -352,8 +354,8 @@
             stats = tracer.get_stats()
             if stats:
                 print("\nCoverage.py tracer stats:")
-                for k in sorted(stats.keys()):
-                    print("%20s: %s" % (k, stats[k]))
+                for k in human_sorted(stats.keys()):
+                    print(f"{k:>20}: {stats[k]}")
         if self.threading:
             self.threading.settrace(None)
 
@@ -390,7 +392,7 @@
         file_tracer = disposition.file_tracer
         plugin = file_tracer._coverage_plugin
         plugin_name = plugin._coverage_plugin_name
-        self.warn("Disabling plug-in {!r} due to previous exception".format(plugin_name))
+        self.warn(f"Disabling plug-in {plugin_name!r} due to previous exception")
         plugin._coverage_enabled = False
         disposition.trace = False
 
@@ -404,22 +406,22 @@
 
     def mapped_file_dict(self, d):
         """Return a dict like d, but with keys modified by file_mapper."""
-        # The call to litems() ensures that the GIL protects the dictionary
+        # The call to list(items()) ensures that the GIL protects the dictionary
         # iterator against concurrent modifications by tracers running
         # in other threads. We try three times in case of concurrent
         # access, hoping to get a clean copy.
         runtime_err = None
-        for _ in range(3):
+        for _ in range(3):                      # pragma: part covered
             try:
-                items = litems(d)
-            except RuntimeError as ex:
+                items = list(d.items())
+            except RuntimeError as ex:          # pragma: cant happen
                 runtime_err = ex
             else:
                 break
         else:
-            raise runtime_err
+            raise runtime_err                   # pragma: cant happen
 
-        return dict((self.cached_mapped_file(k), v) for k, v in items if v)
+        return {self.cached_mapped_file(k): v for k, v in items if v}
 
     def plugin_was_disabled(self, plugin):
         """Record that `plugin` was disabled during the run."""
@@ -437,7 +439,25 @@
             return False
 
         if self.branch:
-            self.covdata.add_arcs(self.mapped_file_dict(self.data))
+            if self.packed_arcs:
+                # Unpack the line number pairs packed into integers.  See
+                # tracer.c:CTracer_record_pair for the C code that creates
+                # these packed ints.
+                data = {}
+                for fname, packeds in self.data.items():
+                    tuples = []
+                    for packed in packeds:
+                        l1 = packed & 0xFFFFF
+                        l2 = (packed & (0xFFFFF << 20)) >> 20
+                        if packed & (1 << 40):
+                            l1 *= -1
+                        if packed & (1 << 41):
+                            l2 *= -1
+                        tuples.append((l1, l2))
+                    data[fname] = tuples
+            else:
+                data = self.data
+            self.covdata.add_arcs(self.mapped_file_dict(data))
         else:
             self.covdata.add_lines(self.mapped_file_dict(self.data))
 

eric ide

mercurial