| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | from contextlib import contextmanager | 
					
						
							|  |  |  | import imp | 
					
						
							|  |  |  | import os.path | 
					
						
							| 
									
										
										
										
											2009-04-02 05:17:54 +00:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2009-02-07 02:06:43 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-20 01:05:40 +00:00
										 |  |  | CASE_INSENSITIVE_FS = True | 
					
						
							|  |  |  | # Windows is the only OS that is *always* case-insensitive | 
					
						
							|  |  |  | # (OS X *can* be case-sensitive). | 
					
						
							|  |  |  | if sys.platform not in ('win32', 'cygwin'): | 
					
						
							|  |  |  |     changed_name = __file__.upper() | 
					
						
							|  |  |  |     if changed_name == __file__: | 
					
						
							|  |  |  |         changed_name = __file__.lower() | 
					
						
							|  |  |  |     if not os.path.exists(changed_name): | 
					
						
							|  |  |  |         CASE_INSENSITIVE_FS = False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def case_insensitive_tests(test): | 
					
						
							| 
									
										
										
										
											2009-05-11 01:47:11 +00:00
										 |  |  |     """Class decorator that nullifies tests requiring a case-insensitive
 | 
					
						
							| 
									
										
										
										
											2009-01-18 06:55:05 +00:00
										 |  |  |     file system."""
 | 
					
						
							| 
									
										
										
										
											2009-07-20 01:05:40 +00:00
										 |  |  |     return unittest.skipIf(not CASE_INSENSITIVE_FS, | 
					
						
							|  |  |  |                             "requires a case-insensitive filesystem")(test) | 
					
						
							| 
									
										
										
										
											2009-01-18 06:55:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | @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) |