4 """Miscellaneous stuff for coverage.py.""" |
4 """Miscellaneous stuff for coverage.py.""" |
5 |
5 |
6 import errno |
6 import errno |
7 import hashlib |
7 import hashlib |
8 import inspect |
8 import inspect |
|
9 import locale |
9 import os |
10 import os |
|
11 import sys |
|
12 import types |
10 |
13 |
11 from coverage import env |
14 from coverage import env |
12 from coverage.backward import string_class, to_bytes, unicode_class |
15 from coverage.backward import string_class, to_bytes, unicode_class |
|
16 |
|
17 ISOLATED_MODULES = {} |
|
18 |
|
19 |
|
20 def isolate_module(mod): |
|
21 """Copy a module so that we are isolated from aggressive mocking. |
|
22 |
|
23 If a test suite mocks os.path.exists (for example), and then we need to use |
|
24 it during the test, everything will get tangled up if we use their mock. |
|
25 Making a copy of the module when we import it will isolate coverage.py from |
|
26 those complications. |
|
27 """ |
|
28 if mod not in ISOLATED_MODULES: |
|
29 new_mod = types.ModuleType(mod.__name__) |
|
30 ISOLATED_MODULES[mod] = new_mod |
|
31 for name in dir(mod): |
|
32 value = getattr(mod, name) |
|
33 if isinstance(value, types.ModuleType): |
|
34 value = isolate_module(value) |
|
35 setattr(new_mod, name, value) |
|
36 return ISOLATED_MODULES[mod] |
|
37 |
|
38 os = isolate_module(os) |
13 |
39 |
14 |
40 |
15 # Use PyContracts for assertion testing on parameters and returns, but only if |
41 # Use PyContracts for assertion testing on parameters and returns, but only if |
16 # we are running our own test suite. |
42 # we are running our own test suite. |
17 if env.TESTING: |
43 if env.TESTING: |
18 from contracts import contract # pylint: disable=unused-import |
44 from contracts import contract # pylint: disable=unused-import |
19 from contracts import new_contract |
45 from contracts import new_contract as raw_new_contract |
20 |
46 |
21 try: |
47 def new_contract(*args, **kwargs): |
22 # Define contract words that PyContract doesn't have. |
48 """A proxy for contracts.new_contract that doesn't mind happening twice.""" |
23 new_contract('bytes', lambda v: isinstance(v, bytes)) |
49 try: |
24 if env.PY3: |
50 return raw_new_contract(*args, **kwargs) |
25 new_contract('unicode', lambda v: isinstance(v, unicode_class)) |
51 except ValueError: |
26 except ValueError: |
52 # During meta-coverage, this module is imported twice, and |
27 # During meta-coverage, this module is imported twice, and PyContracts |
53 # PyContracts doesn't like redefining contracts. It's OK. |
28 # doesn't like redefining contracts. It's OK. |
54 pass |
29 pass |
55 |
|
56 # Define contract words that PyContract doesn't have. |
|
57 new_contract('bytes', lambda v: isinstance(v, bytes)) |
|
58 if env.PY3: |
|
59 new_contract('unicode', lambda v: isinstance(v, unicode_class)) |
30 else: # pragma: not covered |
60 else: # pragma: not covered |
31 # We aren't using real PyContracts, so just define a no-op decorator as a |
61 # We aren't using real PyContracts, so just define a no-op decorator as a |
32 # stunt double. |
62 # stunt double. |
33 def contract(**unused): |
63 def contract(**unused): |
34 """Dummy no-op implementation of `contract`.""" |
64 """Dummy no-op implementation of `contract`.""" |
35 return lambda func: func |
65 return lambda func: func |
|
66 |
|
67 def new_contract(*args_unused, **kwargs_unused): |
|
68 """Dummy no-op implementation of `new_contract`.""" |
|
69 pass |
36 |
70 |
37 |
71 |
38 def nice_pair(pair): |
72 def nice_pair(pair): |
39 """Make a nice string representation of a pair of numbers. |
73 """Make a nice string representation of a pair of numbers. |
40 |
74 |