DebugClients/Python3/coverage/misc.py

changeset 5051
3586ebd9fac8
parent 4489
d0d6e4ad31bd
--- a/DebugClients/Python3/coverage/misc.py	Sat Jul 23 13:33:54 2016 +0200
+++ b/DebugClients/Python3/coverage/misc.py	Sun Jul 24 12:01:01 2016 +0200
@@ -6,27 +6,57 @@
 import errno
 import hashlib
 import inspect
+import locale
 import os
+import sys
+import types
 
 from coverage import env
 from coverage.backward import string_class, to_bytes, unicode_class
 
+ISOLATED_MODULES = {}
+
+
+def isolate_module(mod):
+    """Copy a module so that we are isolated from aggressive mocking.
+
+    If a test suite mocks os.path.exists (for example), and then we need to use
+    it during the test, everything will get tangled up if we use their mock.
+    Making a copy of the module when we import it will isolate coverage.py from
+    those complications.
+    """
+    if mod not in ISOLATED_MODULES:
+        new_mod = types.ModuleType(mod.__name__)
+        ISOLATED_MODULES[mod] = new_mod
+        for name in dir(mod):
+            value = getattr(mod, name)
+            if isinstance(value, types.ModuleType):
+                value = isolate_module(value)
+            setattr(new_mod, name, value)
+    return ISOLATED_MODULES[mod]
+
+os = isolate_module(os)
+
 
 # Use PyContracts for assertion testing on parameters and returns, but only if
 # we are running our own test suite.
 if env.TESTING:
     from contracts import contract              # pylint: disable=unused-import
-    from contracts import new_contract
+    from contracts import new_contract as raw_new_contract
 
-    try:
-        # Define contract words that PyContract doesn't have.
-        new_contract('bytes', lambda v: isinstance(v, bytes))
-        if env.PY3:
-            new_contract('unicode', lambda v: isinstance(v, unicode_class))
-    except ValueError:
-        # During meta-coverage, this module is imported twice, and PyContracts
-        # doesn't like redefining contracts. It's OK.
-        pass
+    def new_contract(*args, **kwargs):
+        """A proxy for contracts.new_contract that doesn't mind happening twice."""
+        try:
+            return raw_new_contract(*args, **kwargs)
+        except ValueError:
+            # During meta-coverage, this module is imported twice, and
+            # PyContracts doesn't like redefining contracts. It's OK.
+            pass
+
+    # Define contract words that PyContract doesn't have.
+    new_contract('bytes', lambda v: isinstance(v, bytes))
+    if env.PY3:
+        new_contract('unicode', lambda v: isinstance(v, unicode_class))
 else:                                           # pragma: not covered
     # We aren't using real PyContracts, so just define a no-op decorator as a
     # stunt double.
@@ -34,6 +64,10 @@
         """Dummy no-op implementation of `contract`."""
         return lambda func: func
 
+    def new_contract(*args_unused, **kwargs_unused):
+        """Dummy no-op implementation of `new_contract`."""
+        pass
+
 
 def nice_pair(pair):
     """Make a nice string representation of a pair of numbers.
@@ -125,6 +159,18 @@
             raise
 
 
+def output_encoding(outfile=None):
+    """Determine the encoding to use for output written to `outfile` or stdout."""
+    if outfile is None:
+        outfile = sys.stdout
+    encoding = (
+        getattr(outfile, "encoding", None) or
+        getattr(sys.__stdout__, "encoding", None) or
+        locale.getpreferredencoding()
+    )
+    return encoding
+
+
 class Hasher(object):
     """Hashes Python data into md5."""
     def __init__(self):

eric ide

mercurial