diff options
author | Brett Cannon <bcannon@gmail.com> | 2009-02-01 04:00:05 (GMT) |
---|---|---|
committer | Brett Cannon <bcannon@gmail.com> | 2009-02-01 04:00:05 (GMT) |
commit | bcb26c53c095c7bcd0e5415088e25dbd27f12592 (patch) | |
tree | 35240e335dd91a385c13935ddc64b33d9c17a8ad /Lib/importlib/test/util.py | |
parent | ae9ad186d058c5700d0692e2f3b026e95639f5cf (diff) | |
download | cpython-bcb26c53c095c7bcd0e5415088e25dbd27f12592.zip cpython-bcb26c53c095c7bcd0e5415088e25dbd27f12592.tar.gz cpython-bcb26c53c095c7bcd0e5415088e25dbd27f12592.tar.bz2 |
Rename importlib.test.support to importlib.test.util.
Diffstat (limited to 'Lib/importlib/test/util.py')
-rw-r--r-- | Lib/importlib/test/util.py | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/Lib/importlib/test/util.py b/Lib/importlib/test/util.py new file mode 100644 index 0000000..1518d74 --- /dev/null +++ b/Lib/importlib/test/util.py @@ -0,0 +1,153 @@ +from importlib import Import + +from contextlib import contextmanager +from functools import update_wrapper +import imp +import os.path +from test.support import unlink +import sys + + +using___import__ = False + +def import_(*args, **kwargs): + """Delegate to allow for injecting different implementations of import.""" + if using___import__: + return __import__(*args, **kwargs) + return Import()(*args, **kwargs) + +def importlib_only(fxn): + """Decorator to mark which tests are not supported by the current + implementation of __import__().""" + def inner(*args, **kwargs): + if using___import__: + return + else: + return fxn(*args, **kwargs) + update_wrapper(inner, fxn) + return inner + + +def case_insensitive_tests(class_): + """Class decorator that nullifies tests that require a case-insensitive + file system.""" + if sys.platform not in ('win32', 'darwin', 'cygwin'): + return object() + else: + return class_ + + +@contextmanager +def uncache(*names): + """Uncache a module from sys.modules. + + A basic sanity check is performed to prevent uncaching modules that either + cannot/shouldn't be uncached. + + """ + for name in names: + if name in ('sys', 'marshal', 'imp'): + raise ValueError( + "cannot uncache {0} as it will break _importlib".format(name)) + try: + del sys.modules[name] + except KeyError: + pass + try: + yield + finally: + for name in names: + try: + del sys.modules[name] + except KeyError: + pass + +@contextmanager +def import_state(**kwargs): + """Context manager to manage the various importers and stored state in the + sys module. + + The 'modules' attribute is not supported as the interpreter state stores a + pointer to the dict that the interpreter uses internally; + reassigning to sys.modules does not have the desired effect. + + """ + originals = {} + try: + for attr, default in (('meta_path', []), ('path', []), + ('path_hooks', []), + ('path_importer_cache', {})): + originals[attr] = getattr(sys, attr) + if attr in kwargs: + new_value = kwargs[attr] + del kwargs[attr] + else: + new_value = default + setattr(sys, attr, new_value) + if len(kwargs): + raise ValueError( + 'unrecognized arguments: {0}'.format(kwargs.keys())) + yield + finally: + for attr, value in originals.items(): + setattr(sys, attr, value) + + +class mock_modules: + + """A mock importer/loader.""" + + def __init__(self, *names): + self.modules = {} + for name in names: + if not name.endswith('.__init__'): + import_name = name + else: + import_name = name[:-len('.__init__')] + if '.' not in name: + package = None + elif import_name == name: + package = name.rsplit('.', 1)[0] + else: + package = import_name + module = imp.new_module(import_name) + module.__loader__ = self + module.__file__ = '<mock __file__>' + module.__package__ = package + module.attr = name + if import_name != name: + module.__path__ = ['<mock __path__>'] + self.modules[import_name] = module + + def __getitem__(self, name): + return self.modules[name] + + def find_module(self, fullname, path=None): + if fullname not in self.modules: + return None + else: + return self + + def load_module(self, fullname): + if fullname not in self.modules: + raise ImportError + else: + sys.modules[fullname] = self.modules[fullname] + return self.modules[fullname] + + def __enter__(self): + self._uncache = uncache(*self.modules.keys()) + self._uncache.__enter__() + return self + + def __exit__(self, *exc_info): + self._uncache.__exit__(None, None, None) + + +def mock_path_hook(*entries, importer): + """A mock sys.path_hooks entry.""" + def hook(entry): + if entry not in entries: + raise ImportError + return importer + return hook |