DebugClients/Python3/coverage/misc.py

branch
Py2 comp.
changeset 3495
fac17a82b431
parent 29
391dc0bc4ae5
child 4489
d0d6e4ad31bd
--- a/DebugClients/Python3/coverage/misc.py	Fri Apr 04 22:57:07 2014 +0200
+++ b/DebugClients/Python3/coverage/misc.py	Thu Apr 10 23:02:20 2014 +0200
@@ -1,5 +1,14 @@
 """Miscellaneous stuff for Coverage."""
 
+import errno
+import inspect
+import os
+import sys
+
+from .backward import md5, sorted       # pylint: disable=W0622
+from .backward import string_class, to_bytes
+
+
 def nice_pair(pair):
     """Make a nice string representation of a pair of numbers.
 
@@ -29,6 +38,8 @@
     i = 0
     j = 0
     start = None
+    statements = sorted(statements)
+    lines = sorted(lines)
     while i < len(statements) and j < len(lines):
         if statements[i] == lines[j]:
             if start == None:
@@ -45,6 +56,12 @@
     return ret
 
 
+def short_stack():
+    """Return a string summarizing the call stack."""
+    stack = inspect.stack()[:0:-1]
+    return "\n".join(["%30s : %s @%d" % (t[3],t[1],t[2]) for t in stack])
+
+
 def expensive(fn):
     """A decorator to cache the result of an expensive operation.
 
@@ -60,10 +77,91 @@
     return _wrapped
 
 
+def bool_or_none(b):
+    """Return bool(b), but preserve None."""
+    if b is None:
+        return None
+    else:
+        return bool(b)
+
+
+def join_regex(regexes):
+    """Combine a list of regexes into one that matches any of them."""
+    if len(regexes) > 1:
+        return "|".join(["(%s)" % r for r in regexes])
+    elif regexes:
+        return regexes[0]
+    else:
+        return ""
+
+
+def file_be_gone(path):
+    """Remove a file, and don't get annoyed if it doesn't exist."""
+    try:
+        os.remove(path)
+    except OSError:
+        _, e, _ = sys.exc_info()
+        if e.errno != errno.ENOENT:
+            raise
+
+
+class Hasher(object):
+    """Hashes Python data into md5."""
+    def __init__(self):
+        self.md5 = md5()
+
+    def update(self, v):
+        """Add `v` to the hash, recursively if needed."""
+        self.md5.update(to_bytes(str(type(v))))
+        if isinstance(v, string_class):
+            self.md5.update(to_bytes(v))
+        elif v is None:
+            pass
+        elif isinstance(v, (int, float)):
+            self.md5.update(to_bytes(str(v)))
+        elif isinstance(v, (tuple, list)):
+            for e in v:
+                self.update(e)
+        elif isinstance(v, dict):
+            keys = v.keys()
+            for k in sorted(keys):
+                self.update(k)
+                self.update(v[k])
+        else:
+            for k in dir(v):
+                if k.startswith('__'):
+                    continue
+                a = getattr(v, k)
+                if inspect.isroutine(a):
+                    continue
+                self.update(k)
+                self.update(a)
+
+    def digest(self):
+        """Retrieve the digest of the hash."""
+        return self.md5.digest()
+
+
 class CoverageException(Exception):
     """An exception specific to Coverage."""
     pass
 
 class NoSource(CoverageException):
-    """Used to indicate we couldn't find the source for a module."""
+    """We couldn't find the source for a module."""
+    pass
+
+class NoCode(NoSource):
+    """We couldn't find any code at all."""
     pass
+
+class NotPython(CoverageException):
+    """A source file turned out not to be parsable Python."""
+    pass
+
+class ExceptionDuringRun(CoverageException):
+    """An exception happened while running customer code.
+
+    Construct it with three arguments, the values from `sys.exc_info`.
+
+    """
+    pass

eric ide

mercurial