summaryrefslogtreecommitdiff
path: root/coverage/misc.py
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-10-06 07:14:18 -0400
committerNed Batchelder <ned@nedbatchelder.com>2015-10-06 07:14:18 -0400
commit56e61431209ac76911f25eee3374c9a0b7d7b8ed (patch)
tree5d1b41892bd26b552dead0878b96f0cdec75d68b /coverage/misc.py
parentfb6c870536dbfe556429ac6af34e72459b6c8f32 (diff)
downloadpython-coveragepy-56e61431209ac76911f25eee3374c9a0b7d7b8ed.tar.gz
Protect ourselves from mock'ed os. #416
Diffstat (limited to 'coverage/misc.py')
-rw-r--r--coverage/misc.py24
1 files changed, 24 insertions, 0 deletions
diff --git a/coverage/misc.py b/coverage/misc.py
index 44f8977..36e4fe9 100644
--- a/coverage/misc.py
+++ b/coverage/misc.py
@@ -7,10 +7,34 @@ import errno
import hashlib
import inspect
import os
+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.