| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  | import abc | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | import builtins | 
					
						
							|  |  |  | import contextlib | 
					
						
							|  |  |  | import errno | 
					
						
							|  |  |  | import functools | 
					
						
							|  |  |  | import importlib | 
					
						
							|  |  |  | from importlib import machinery, util, invalidate_caches | 
					
						
							| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  | from importlib.abc import ResourceReader | 
					
						
							|  |  |  | import io | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | import os.path | 
					
						
							| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  | from pathlib import Path, PurePath | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | import tempfile | 
					
						
							| 
									
										
										
										
											2013-06-15 18:39:21 -04:00
										 |  |  | import types | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  | from . import data01 | 
					
						
							|  |  |  | from . import zipdata01 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | BUILTINS = types.SimpleNamespace() | 
					
						
							|  |  |  | BUILTINS.good_name = None | 
					
						
							|  |  |  | BUILTINS.bad_name = None | 
					
						
							|  |  |  | if 'errno' in sys.builtin_module_names: | 
					
						
							|  |  |  |     BUILTINS.good_name = 'errno' | 
					
						
							|  |  |  | if 'importlib' not in sys.builtin_module_names: | 
					
						
							|  |  |  |     BUILTINS.bad_name = 'importlib' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EXTENSIONS = types.SimpleNamespace() | 
					
						
							|  |  |  | EXTENSIONS.path = None | 
					
						
							|  |  |  | EXTENSIONS.ext = None | 
					
						
							|  |  |  | EXTENSIONS.filename = None | 
					
						
							|  |  |  | EXTENSIONS.file_path = None | 
					
						
							|  |  |  | EXTENSIONS.name = '_testcapi' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _extension_details(): | 
					
						
							|  |  |  |     global EXTENSIONS | 
					
						
							|  |  |  |     for path in sys.path: | 
					
						
							|  |  |  |         for ext in machinery.EXTENSION_SUFFIXES: | 
					
						
							|  |  |  |             filename = EXTENSIONS.name + ext | 
					
						
							|  |  |  |             file_path = os.path.join(path, filename) | 
					
						
							|  |  |  |             if os.path.exists(file_path): | 
					
						
							|  |  |  |                 EXTENSIONS.path = path | 
					
						
							|  |  |  |                 EXTENSIONS.ext = ext | 
					
						
							|  |  |  |                 EXTENSIONS.filename = filename | 
					
						
							|  |  |  |                 EXTENSIONS.file_path = file_path | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _extension_details() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-04 14:47:14 -04:00
										 |  |  | def import_importlib(module_name): | 
					
						
							|  |  |  |     """Import a module from importlib both w/ and w/o _frozen_importlib.""" | 
					
						
							|  |  |  |     fresh = ('importlib',) if '.' in module_name else () | 
					
						
							|  |  |  |     frozen = support.import_fresh_module(module_name) | 
					
						
							|  |  |  |     source = support.import_fresh_module(module_name, fresh=fresh, | 
					
						
							| 
									
										
										
										
											2015-05-15 21:54:59 -06:00
										 |  |  |                                          blocked=('_frozen_importlib', '_frozen_importlib_external')) | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  |     return {'Frozen': frozen, 'Source': source} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def specialize_class(cls, kind, base=None, **kwargs): | 
					
						
							|  |  |  |     # XXX Support passing in submodule names--load (and cache) them? | 
					
						
							|  |  |  |     # That would clean up the test modules a bit more. | 
					
						
							|  |  |  |     if base is None: | 
					
						
							|  |  |  |         base = unittest.TestCase | 
					
						
							|  |  |  |     elif not isinstance(base, type): | 
					
						
							|  |  |  |         base = base[kind] | 
					
						
							|  |  |  |     name = '{}_{}'.format(kind, cls.__name__) | 
					
						
							|  |  |  |     bases = (cls, base) | 
					
						
							|  |  |  |     specialized = types.new_class(name, bases) | 
					
						
							|  |  |  |     specialized.__module__ = cls.__module__ | 
					
						
							|  |  |  |     specialized._NAME = cls.__name__ | 
					
						
							|  |  |  |     specialized._KIND = kind | 
					
						
							|  |  |  |     for attr, values in kwargs.items(): | 
					
						
							|  |  |  |         value = values[kind] | 
					
						
							|  |  |  |         setattr(specialized, attr, value) | 
					
						
							|  |  |  |     return specialized | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def split_frozen(cls, base=None, **kwargs): | 
					
						
							|  |  |  |     frozen = specialize_class(cls, 'Frozen', base, **kwargs) | 
					
						
							|  |  |  |     source = specialize_class(cls, 'Source', base, **kwargs) | 
					
						
							| 
									
										
										
										
											2013-10-04 14:47:14 -04:00
										 |  |  |     return frozen, source | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  | def test_both(test_class, base=None, **kwargs): | 
					
						
							|  |  |  |     return split_frozen(test_class, base, **kwargs) | 
					
						
							| 
									
										
										
										
											2013-10-18 15:40:11 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  | source_importlib = import_importlib('importlib')['Source'] | 
					
						
							|  |  |  | __import__ = {'Frozen': staticmethod(builtins.__import__), | 
					
						
							|  |  |  |               'Source': staticmethod(source_importlib.__import__)} | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-20 01:05:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:46 -07:00
										 |  |  | def submodule(parent, name, pkg_dir, content=''): | 
					
						
							|  |  |  |     path = os.path.join(pkg_dir, name + '.py') | 
					
						
							|  |  |  |     with open(path, 'w') as subfile: | 
					
						
							|  |  |  |         subfile.write(content) | 
					
						
							|  |  |  |     return '{}.{}'.format(parent, name), path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | @contextlib.contextmanager | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 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( | 
					
						
							| 
									
										
										
										
											2012-04-14 14:10:13 -04:00
										 |  |  |                 "cannot uncache {0}".format(name)) | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             del sys.modules[name] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         yield | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         for name in names: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 del sys.modules[name] | 
					
						
							|  |  |  |             except KeyError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:46 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | @contextlib.contextmanager | 
					
						
							| 
									
										
										
										
											2014-01-25 15:32:46 -07:00
										 |  |  | def temp_module(name, content='', *, pkg=False): | 
					
						
							|  |  |  |     conflicts = [n for n in sys.modules if n.partition('.')[0] == name] | 
					
						
							|  |  |  |     with support.temp_cwd(None) as cwd: | 
					
						
							|  |  |  |         with uncache(name, *conflicts): | 
					
						
							|  |  |  |             with support.DirsOnSysPath(cwd): | 
					
						
							|  |  |  |                 invalidate_caches() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 location = os.path.join(cwd, name) | 
					
						
							|  |  |  |                 if pkg: | 
					
						
							|  |  |  |                     modpath = os.path.join(location, '__init__.py') | 
					
						
							|  |  |  |                     os.mkdir(name) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     modpath = location + '.py' | 
					
						
							|  |  |  |                     if content is None: | 
					
						
							|  |  |  |                         # Make sure the module file gets created. | 
					
						
							|  |  |  |                         content = '' | 
					
						
							|  |  |  |                 if content is not None: | 
					
						
							|  |  |  |                     # not a namespace package | 
					
						
							|  |  |  |                     with open(modpath, 'w') as modfile: | 
					
						
							|  |  |  |                         modfile.write(content) | 
					
						
							|  |  |  |                 yield location | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | @contextlib.contextmanager | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-06 12:07:25 -05:00
										 |  |  | class _ImporterMock: | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-06 12:07:25 -05:00
										 |  |  |     """Base class to help with creating importer mocks.""" | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-14 22:23:46 -06:00
										 |  |  |     def __init__(self, *names, module_code={}): | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  |         self.modules = {} | 
					
						
							| 
									
										
										
										
											2011-12-14 22:23:46 -06:00
										 |  |  |         self.module_code = {} | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  |         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 | 
					
						
							| 
									
										
										
										
											2013-06-15 18:39:21 -04:00
										 |  |  |             module = types.ModuleType(import_name) | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  |             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 | 
					
						
							| 
									
										
										
										
											2011-12-14 22:23:46 -06:00
										 |  |  |             if import_name in module_code: | 
					
						
							|  |  |  |                 self.module_code[import_name] = module_code[import_name] | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getitem__(self, name): | 
					
						
							|  |  |  |         return self.modules[name] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-06 12:07:25 -05:00
										 |  |  |     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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class mock_modules(_ImporterMock): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """Importer mock using PEP 302 APIs.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  |     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] | 
					
						
							| 
									
										
										
										
											2011-12-14 22:23:46 -06:00
										 |  |  |             if fullname in self.module_code: | 
					
						
							| 
									
										
										
										
											2012-05-07 21:41:59 +02:00
										 |  |  |                 try: | 
					
						
							|  |  |  |                     self.module_code[fullname]() | 
					
						
							|  |  |  |                 except Exception: | 
					
						
							|  |  |  |                     del sys.modules[fullname] | 
					
						
							|  |  |  |                     raise | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  |             return self.modules[fullname] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-06 12:07:25 -05:00
										 |  |  | class mock_spec(_ImporterMock): | 
					
						
							| 
									
										
										
										
											2009-01-18 00:24:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-06 12:07:25 -05:00
										 |  |  |     """Importer mock using PEP 451 APIs.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def find_spec(self, fullname, path=None, parent=None): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             module = self.modules[fullname] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  |         spec = util.spec_from_file_location( | 
					
						
							|  |  |  |                 fullname, module.__file__, loader=self, | 
					
						
							|  |  |  |                 submodule_search_locations=getattr(module, '__path__', None)) | 
					
						
							|  |  |  |         return spec | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_module(self, spec): | 
					
						
							|  |  |  |         if spec.name not in self.modules: | 
					
						
							|  |  |  |             raise ImportError | 
					
						
							|  |  |  |         return self.modules[spec.name] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def exec_module(self, module): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self.module_code[module.__spec__.name]() | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def writes_bytecode_files(fxn): | 
					
						
							|  |  |  |     """Decorator to protect sys.dont_write_bytecode from mutation and to skip
 | 
					
						
							|  |  |  |     tests that require it to be set to False."""
 | 
					
						
							|  |  |  |     if sys.dont_write_bytecode: | 
					
						
							|  |  |  |         return lambda *args, **kwargs: None | 
					
						
							|  |  |  |     @functools.wraps(fxn) | 
					
						
							|  |  |  |     def wrapper(*args, **kwargs): | 
					
						
							|  |  |  |         original = sys.dont_write_bytecode | 
					
						
							|  |  |  |         sys.dont_write_bytecode = False | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             to_return = fxn(*args, **kwargs) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             sys.dont_write_bytecode = original | 
					
						
							|  |  |  |         return to_return | 
					
						
							|  |  |  |     return wrapper | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def ensure_bytecode_path(bytecode_path): | 
					
						
							|  |  |  |     """Ensure that the __pycache__ directory for PEP 3147 pyc file exists.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     :param bytecode_path: File system path to PEP 3147 pyc file. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         os.mkdir(os.path.dirname(bytecode_path)) | 
					
						
							|  |  |  |     except OSError as error: | 
					
						
							|  |  |  |         if error.errno != errno.EEXIST: | 
					
						
							|  |  |  |             raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 22:40:56 -06:00
										 |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def temporary_pycache_prefix(prefix): | 
					
						
							|  |  |  |     """Adjust and restore sys.pycache_prefix.""" | 
					
						
							|  |  |  |     _orig_prefix = sys.pycache_prefix | 
					
						
							|  |  |  |     sys.pycache_prefix = prefix | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         yield | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         sys.pycache_prefix = _orig_prefix | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-09 14:32:57 -04:00
										 |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def create_modules(*names): | 
					
						
							|  |  |  |     """Temporarily create each named module with an attribute (named 'attr')
 | 
					
						
							|  |  |  |     that contains the name passed into the context manager that caused the | 
					
						
							|  |  |  |     creation of the module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     All files are created in a temporary directory returned by | 
					
						
							|  |  |  |     tempfile.mkdtemp(). This directory is inserted at the beginning of | 
					
						
							|  |  |  |     sys.path. When the context manager exits all created files (source and | 
					
						
							|  |  |  |     bytecode) are explicitly deleted. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     No magic is performed when creating packages! This means that if you create | 
					
						
							|  |  |  |     a module within a package you must also create the package's __init__ as | 
					
						
							|  |  |  |     well. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     source = 'attr = {0!r}' | 
					
						
							|  |  |  |     created_paths = [] | 
					
						
							|  |  |  |     mapping = {} | 
					
						
							|  |  |  |     state_manager = None | 
					
						
							|  |  |  |     uncache_manager = None | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         temp_dir = tempfile.mkdtemp() | 
					
						
							|  |  |  |         mapping['.root'] = temp_dir | 
					
						
							|  |  |  |         import_names = set() | 
					
						
							|  |  |  |         for name in names: | 
					
						
							|  |  |  |             if not name.endswith('__init__'): | 
					
						
							|  |  |  |                 import_name = name | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 import_name = name[:-len('.__init__')] | 
					
						
							|  |  |  |             import_names.add(import_name) | 
					
						
							|  |  |  |             if import_name in sys.modules: | 
					
						
							|  |  |  |                 del sys.modules[import_name] | 
					
						
							|  |  |  |             name_parts = name.split('.') | 
					
						
							|  |  |  |             file_path = temp_dir | 
					
						
							|  |  |  |             for directory in name_parts[:-1]: | 
					
						
							|  |  |  |                 file_path = os.path.join(file_path, directory) | 
					
						
							|  |  |  |                 if not os.path.exists(file_path): | 
					
						
							|  |  |  |                     os.mkdir(file_path) | 
					
						
							|  |  |  |                     created_paths.append(file_path) | 
					
						
							|  |  |  |             file_path = os.path.join(file_path, name_parts[-1] + '.py') | 
					
						
							|  |  |  |             with open(file_path, 'w') as file: | 
					
						
							|  |  |  |                 file.write(source.format(name)) | 
					
						
							|  |  |  |             created_paths.append(file_path) | 
					
						
							|  |  |  |             mapping[name] = file_path | 
					
						
							|  |  |  |         uncache_manager = uncache(*import_names) | 
					
						
							|  |  |  |         uncache_manager.__enter__() | 
					
						
							|  |  |  |         state_manager = import_state(path=[temp_dir]) | 
					
						
							|  |  |  |         state_manager.__enter__() | 
					
						
							|  |  |  |         yield mapping | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         if state_manager is not None: | 
					
						
							|  |  |  |             state_manager.__exit__(None, None, None) | 
					
						
							|  |  |  |         if uncache_manager is not None: | 
					
						
							|  |  |  |             uncache_manager.__exit__(None, None, None) | 
					
						
							|  |  |  |         support.rmtree(temp_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2016-07-16 10:44:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CASEOKTestBase: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def caseok_env_changed(self, *, should_exist): | 
					
						
							|  |  |  |         possibilities = b'PYTHONCASEOK', 'PYTHONCASEOK' | 
					
						
							|  |  |  |         if any(x in self.importlib._bootstrap_external._os.environ | 
					
						
							|  |  |  |                     for x in possibilities) != should_exist: | 
					
						
							|  |  |  |             self.skipTest('os.environ changes not reflected in _os.environ') | 
					
						
							| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create_package(file, path, is_package=True, contents=()): | 
					
						
							|  |  |  |     class Reader(ResourceReader): | 
					
						
							| 
									
										
										
										
											2018-01-15 15:07:11 -08:00
										 |  |  |         def get_resource_reader(self, package): | 
					
						
							|  |  |  |             return self | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  |         def open_resource(self, path): | 
					
						
							|  |  |  |             self._path = path | 
					
						
							|  |  |  |             if isinstance(file, Exception): | 
					
						
							|  |  |  |                 raise file | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 return file | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def resource_path(self, path_): | 
					
						
							|  |  |  |             self._path = path_ | 
					
						
							|  |  |  |             if isinstance(path, Exception): | 
					
						
							|  |  |  |                 raise path | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 return path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def is_resource(self, path_): | 
					
						
							|  |  |  |             self._path = path_ | 
					
						
							|  |  |  |             if isinstance(path, Exception): | 
					
						
							|  |  |  |                 raise path | 
					
						
							|  |  |  |             for entry in contents: | 
					
						
							|  |  |  |                 parts = entry.split('/') | 
					
						
							|  |  |  |                 if len(parts) == 1 and parts[0] == path_: | 
					
						
							|  |  |  |                     return True | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def contents(self): | 
					
						
							|  |  |  |             if isinstance(path, Exception): | 
					
						
							|  |  |  |                 raise path | 
					
						
							|  |  |  |             # There's no yield from in baseball, er, Python 2. | 
					
						
							|  |  |  |             for entry in contents: | 
					
						
							|  |  |  |                 yield entry | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     name = 'testingpackage' | 
					
						
							|  |  |  |     # Unforunately importlib.util.module_from_spec() was not introduced until | 
					
						
							|  |  |  |     # Python 3.5. | 
					
						
							|  |  |  |     module = types.ModuleType(name) | 
					
						
							|  |  |  |     loader = Reader() | 
					
						
							|  |  |  |     spec = machinery.ModuleSpec( | 
					
						
							|  |  |  |         name, loader, | 
					
						
							|  |  |  |         origin='does-not-exist', | 
					
						
							|  |  |  |         is_package=is_package) | 
					
						
							|  |  |  |     module.__spec__ = spec | 
					
						
							|  |  |  |     module.__loader__ = loader | 
					
						
							|  |  |  |     return module | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CommonResourceTests(abc.ABC): | 
					
						
							|  |  |  |     @abc.abstractmethod | 
					
						
							|  |  |  |     def execute(self, package, path): | 
					
						
							|  |  |  |         raise NotImplementedError | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_package_name(self): | 
					
						
							|  |  |  |         # Passing in the package name should succeed. | 
					
						
							|  |  |  |         self.execute(data01.__name__, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_package_object(self): | 
					
						
							|  |  |  |         # Passing in the package itself should succeed. | 
					
						
							|  |  |  |         self.execute(data01, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_string_path(self): | 
					
						
							|  |  |  |         # Passing in a string for the path should succeed. | 
					
						
							|  |  |  |         path = 'utf-8.file' | 
					
						
							|  |  |  |         self.execute(data01, path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @unittest.skipIf(sys.version_info < (3, 6), 'requires os.PathLike support') | 
					
						
							|  |  |  |     def test_pathlib_path(self): | 
					
						
							|  |  |  |         # Passing in a pathlib.PurePath object for the path should succeed. | 
					
						
							|  |  |  |         path = PurePath('utf-8.file') | 
					
						
							|  |  |  |         self.execute(data01, path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_absolute_path(self): | 
					
						
							|  |  |  |         # An absolute path is a ValueError. | 
					
						
							|  |  |  |         path = Path(__file__) | 
					
						
							|  |  |  |         full_path = path.parent/'utf-8.file' | 
					
						
							|  |  |  |         with self.assertRaises(ValueError): | 
					
						
							|  |  |  |             self.execute(data01, full_path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_relative_path(self): | 
					
						
							|  |  |  |         # A reative path is a ValueError. | 
					
						
							|  |  |  |         with self.assertRaises(ValueError): | 
					
						
							|  |  |  |             self.execute(data01, '../data01/utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_importing_module_as_side_effect(self): | 
					
						
							|  |  |  |         # The anchor package can already be imported. | 
					
						
							|  |  |  |         del sys.modules[data01.__name__] | 
					
						
							|  |  |  |         self.execute(data01.__name__, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_non_package_by_name(self): | 
					
						
							|  |  |  |         # The anchor package cannot be a module. | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             self.execute(__name__, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_non_package_by_package(self): | 
					
						
							|  |  |  |         # The anchor package cannot be a module. | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             module = sys.modules['test.test_importlib.util'] | 
					
						
							|  |  |  |             self.execute(module, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') | 
					
						
							|  |  |  |     def test_resource_opener(self): | 
					
						
							|  |  |  |         bytes_data = io.BytesIO(b'Hello, world!') | 
					
						
							|  |  |  |         package = create_package(file=bytes_data, path=FileNotFoundError()) | 
					
						
							|  |  |  |         self.execute(package, 'utf-8.file') | 
					
						
							|  |  |  |         self.assertEqual(package.__loader__._path, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') | 
					
						
							|  |  |  |     def test_resource_path(self): | 
					
						
							|  |  |  |         bytes_data = io.BytesIO(b'Hello, world!') | 
					
						
							|  |  |  |         path = __file__ | 
					
						
							|  |  |  |         package = create_package(file=bytes_data, path=path) | 
					
						
							|  |  |  |         self.execute(package, 'utf-8.file') | 
					
						
							|  |  |  |         self.assertEqual(package.__loader__._path, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_useless_loader(self): | 
					
						
							|  |  |  |         package = create_package(file=FileNotFoundError(), | 
					
						
							|  |  |  |                                  path=FileNotFoundError()) | 
					
						
							|  |  |  |         with self.assertRaises(FileNotFoundError): | 
					
						
							|  |  |  |             self.execute(package, 'utf-8.file') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ZipSetupBase: | 
					
						
							|  |  |  |     ZIP_MODULE = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def setUpClass(cls): | 
					
						
							|  |  |  |         data_path = Path(cls.ZIP_MODULE.__file__) | 
					
						
							|  |  |  |         data_dir = data_path.parent | 
					
						
							|  |  |  |         cls._zip_path = str(data_dir / 'ziptestdata.zip') | 
					
						
							|  |  |  |         sys.path.append(cls._zip_path) | 
					
						
							|  |  |  |         cls.data = importlib.import_module('ziptestdata') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def tearDownClass(cls): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             sys.path.remove(cls._zip_path) | 
					
						
							|  |  |  |         except ValueError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             del sys.path_importer_cache[cls._zip_path] | 
					
						
							|  |  |  |             del sys.modules[cls.data.__name__] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             del cls.data | 
					
						
							|  |  |  |             del cls._zip_path | 
					
						
							|  |  |  |         except AttributeError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-05 09:40:45 -07:00
										 |  |  |     def setUp(self): | 
					
						
							|  |  |  |         modules = support.modules_setup() | 
					
						
							|  |  |  |         self.addCleanup(support.modules_cleanup, *modules) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-30 15:18:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ZipSetup(ZipSetupBase): | 
					
						
							|  |  |  |     ZIP_MODULE = zipdata01                          # type: ignore |