blob: 0fe31a1e20ac1155af4e0e62cd63effa05316c1d [file] [log] [blame]
Brett Cannon23cbd8a2009-01-18 00:24:28 +00001from contextlib import contextmanager
Brett Cannon23cbd8a2009-01-18 00:24:28 +00002import imp
3import os.path
Brett Cannona3d056e2009-04-02 05:17:54 +00004from test import support
Brett Cannon534b2cd2009-02-07 02:06:43 +00005import unittest
Brett Cannon23cbd8a2009-01-18 00:24:28 +00006import sys
Brett Cannon23cbd8a2009-01-18 00:24:28 +00007
8
Brett Cannon2c5c79c2009-01-18 06:55:05 +00009def case_insensitive_tests(class_):
10 """Class decorator that nullifies tests that require a case-insensitive
11 file system."""
12 if sys.platform not in ('win32', 'darwin', 'cygwin'):
Brett Cannona3d056e2009-04-02 05:17:54 +000013 original_name = os.path.listdir('.')[0]
14 if name.upper() != name:
15 changed_name = name.upper()
16 else:
17 changed_name = name.lower()
18 if os.path.exists(changed_name):
19 return class_
Brett Cannon534b2cd2009-02-07 02:06:43 +000020 return unittest.TestCase
Brett Cannon2c5c79c2009-01-18 06:55:05 +000021 else:
22 return class_
23
24
Brett Cannon23cbd8a2009-01-18 00:24:28 +000025@contextmanager
26def uncache(*names):
27 """Uncache a module from sys.modules.
28
29 A basic sanity check is performed to prevent uncaching modules that either
30 cannot/shouldn't be uncached.
31
32 """
33 for name in names:
34 if name in ('sys', 'marshal', 'imp'):
35 raise ValueError(
36 "cannot uncache {0} as it will break _importlib".format(name))
37 try:
38 del sys.modules[name]
39 except KeyError:
40 pass
41 try:
42 yield
43 finally:
44 for name in names:
45 try:
46 del sys.modules[name]
47 except KeyError:
48 pass
49
50@contextmanager
51def import_state(**kwargs):
52 """Context manager to manage the various importers and stored state in the
53 sys module.
54
55 The 'modules' attribute is not supported as the interpreter state stores a
56 pointer to the dict that the interpreter uses internally;
57 reassigning to sys.modules does not have the desired effect.
58
59 """
60 originals = {}
61 try:
62 for attr, default in (('meta_path', []), ('path', []),
63 ('path_hooks', []),
64 ('path_importer_cache', {})):
65 originals[attr] = getattr(sys, attr)
66 if attr in kwargs:
67 new_value = kwargs[attr]
68 del kwargs[attr]
69 else:
70 new_value = default
71 setattr(sys, attr, new_value)
72 if len(kwargs):
73 raise ValueError(
74 'unrecognized arguments: {0}'.format(kwargs.keys()))
75 yield
76 finally:
77 for attr, value in originals.items():
78 setattr(sys, attr, value)
79
80
Brett Cannon23cbd8a2009-01-18 00:24:28 +000081class mock_modules:
82
83 """A mock importer/loader."""
84
85 def __init__(self, *names):
86 self.modules = {}
87 for name in names:
88 if not name.endswith('.__init__'):
89 import_name = name
90 else:
91 import_name = name[:-len('.__init__')]
92 if '.' not in name:
93 package = None
94 elif import_name == name:
95 package = name.rsplit('.', 1)[0]
96 else:
97 package = import_name
98 module = imp.new_module(import_name)
99 module.__loader__ = self
100 module.__file__ = '<mock __file__>'
101 module.__package__ = package
102 module.attr = name
103 if import_name != name:
104 module.__path__ = ['<mock __path__>']
105 self.modules[import_name] = module
106
107 def __getitem__(self, name):
108 return self.modules[name]
109
110 def find_module(self, fullname, path=None):
111 if fullname not in self.modules:
112 return None
113 else:
114 return self
115
116 def load_module(self, fullname):
117 if fullname not in self.modules:
118 raise ImportError
119 else:
120 sys.modules[fullname] = self.modules[fullname]
121 return self.modules[fullname]
122
123 def __enter__(self):
124 self._uncache = uncache(*self.modules.keys())
125 self._uncache.__enter__()
126 return self
127
128 def __exit__(self, *exc_info):
129 self._uncache.__exit__(None, None, None)