mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 c3d9ac8b34
			
		
	
	
		c3d9ac8b34
		
			
		
	
	
	
	
		
			
			Before this change we end up duplicating effort and throwing away data in FrozenImporter.find_spec(). Now we do the work once in find_spec() and the only thing we do in FrozenImporter.exec_module() is turn the raw frozen data into a code object and then exec it. We've added _imp.find_frozen(), add an arg to _imp.get_frozen_object(), and updated FrozenImporter. We've also moved some code around to reduce duplication, get a little more consistency in outcomes, and be more efficient. Note that this change is mostly necessary if we want to set __file__ on frozen stdlib modules. (See https://bugs.python.org/issue21736.) https://bugs.python.org/issue45324
		
			
				
	
	
		
			174 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from .. import abc
 | |
| from .. import util
 | |
| 
 | |
| machinery = util.import_importlib('importlib.machinery')
 | |
| 
 | |
| import _imp
 | |
| import marshal
 | |
| import os.path
 | |
| import unittest
 | |
| import warnings
 | |
| 
 | |
| from test.support import import_helper, REPO_ROOT
 | |
| 
 | |
| 
 | |
| class FindSpecTests(abc.FinderTests):
 | |
| 
 | |
|     """Test finding frozen modules."""
 | |
| 
 | |
|     def find(self, name, **kwargs):
 | |
|         finder = self.machinery.FrozenImporter
 | |
|         with import_helper.frozen_modules():
 | |
|             return finder.find_spec(name, **kwargs)
 | |
| 
 | |
|     def check_basic(self, spec, name, ispkg=False):
 | |
|         self.assertEqual(spec.name, name)
 | |
|         self.assertIs(spec.loader, self.machinery.FrozenImporter)
 | |
|         self.assertEqual(spec.origin, 'frozen')
 | |
|         self.assertFalse(spec.has_location)
 | |
|         if ispkg:
 | |
|             self.assertIsNotNone(spec.submodule_search_locations)
 | |
|         else:
 | |
|             self.assertIsNone(spec.submodule_search_locations)
 | |
|         self.assertIsNotNone(spec.loader_state)
 | |
| 
 | |
|     def check_search_location(self, spec, source=None):
 | |
|         # Frozen packages do not have any path entries.
 | |
|         # (See https://bugs.python.org/issue21736.)
 | |
|         expected = []
 | |
|         self.assertListEqual(spec.submodule_search_locations, expected)
 | |
| 
 | |
|     def check_data(self, spec, source=None, ispkg=None):
 | |
|         with import_helper.frozen_modules():
 | |
|             expected = _imp.get_frozen_object(spec.name)
 | |
|         data = spec.loader_state
 | |
|         # We can't compare the marshaled data directly because
 | |
|         # marshal.dumps() would mark "expected" as a ref, which slightly
 | |
|         # changes the output.  (See https://bugs.python.org/issue34093.)
 | |
|         code = marshal.loads(data)
 | |
|         self.assertEqual(code, expected)
 | |
| 
 | |
|     def test_module(self):
 | |
|         modules = {
 | |
|             '__hello__': None,
 | |
|             '__phello__.__init__': None,
 | |
|             '__phello__.spam': None,
 | |
|             '__phello__.ham.__init__': None,
 | |
|             '__phello__.ham.eggs': None,
 | |
|             '__hello_alias__': '__hello__',
 | |
|             }
 | |
|         for name, source in modules.items():
 | |
|             with self.subTest(name):
 | |
|                 spec = self.find(name)
 | |
|                 self.check_basic(spec, name)
 | |
|                 self.check_data(spec, source)
 | |
| 
 | |
|     def test_package(self):
 | |
|         modules = {
 | |
|             '__phello__': None,
 | |
|             '__phello__.ham': None,
 | |
|             '__phello_alias__': '__hello__',
 | |
|         }
 | |
|         for name, source in modules.items():
 | |
|             with self.subTest(name):
 | |
|                 spec = self.find(name)
 | |
|                 self.check_basic(spec, name, ispkg=True)
 | |
|                 self.check_search_location(spec, source)
 | |
|                 self.check_data(spec, source, ispkg=True)
 | |
| 
 | |
|     def test_frozen_only(self):
 | |
|         name = '__hello_only__'
 | |
|         source = os.path.join(REPO_ROOT, 'Tools', 'freeze', 'flag.py')
 | |
|         spec = self.find(name)
 | |
|         self.check_basic(spec, name)
 | |
|         self.check_data(spec, source)
 | |
| 
 | |
|     # These are covered by test_module() and test_package().
 | |
|     test_module_in_package = None
 | |
|     test_package_in_package = None
 | |
| 
 | |
|     # No easy way to test.
 | |
|     test_package_over_module = None
 | |
| 
 | |
|     def test_path_ignored(self):
 | |
|         for name in ('__hello__', '__phello__', '__phello__.spam'):
 | |
|             actual = self.find(name)
 | |
|             for path in (None, object(), '', 'eggs', [], [''], ['eggs']):
 | |
|                 with self.subTest((name, path)):
 | |
|                     spec = self.find(name, path=path)
 | |
|                     self.assertEqual(spec, actual)
 | |
| 
 | |
|     def test_target_ignored(self):
 | |
|         imported = ('__hello__', '__phello__')
 | |
|         with import_helper.CleanImport(*imported, usefrozen=True):
 | |
|             import __hello__ as match
 | |
|             import __phello__ as nonmatch
 | |
|         name = '__hello__'
 | |
|         actual = self.find(name)
 | |
|         for target in (None, match, nonmatch, object(), 'not-a-module-object'):
 | |
|             with self.subTest(target):
 | |
|                 spec = self.find(name, target=target)
 | |
|                 self.assertEqual(spec, actual)
 | |
| 
 | |
|     def test_failure(self):
 | |
|         spec = self.find('<not real>')
 | |
|         self.assertIsNone(spec)
 | |
| 
 | |
|     def test_not_using_frozen(self):
 | |
|         finder = self.machinery.FrozenImporter
 | |
|         with import_helper.frozen_modules(enabled=False):
 | |
|             # both frozen and not frozen
 | |
|             spec1 = finder.find_spec('__hello__')
 | |
|             # only frozen
 | |
|             spec2 = finder.find_spec('__hello_only__')
 | |
|         self.assertIsNone(spec1)
 | |
|         self.assertIsNone(spec2)
 | |
| 
 | |
| 
 | |
| (Frozen_FindSpecTests,
 | |
|  Source_FindSpecTests
 | |
|  ) = util.test_both(FindSpecTests, machinery=machinery)
 | |
| 
 | |
| 
 | |
| class FinderTests(abc.FinderTests):
 | |
| 
 | |
|     """Test finding frozen modules."""
 | |
| 
 | |
|     def find(self, name, path=None):
 | |
|         finder = self.machinery.FrozenImporter
 | |
|         with warnings.catch_warnings():
 | |
|             warnings.simplefilter("ignore", DeprecationWarning)
 | |
|             with import_helper.frozen_modules():
 | |
|                 return finder.find_module(name, path)
 | |
| 
 | |
|     def test_module(self):
 | |
|         name = '__hello__'
 | |
|         loader = self.find(name)
 | |
|         self.assertTrue(hasattr(loader, 'load_module'))
 | |
| 
 | |
|     def test_package(self):
 | |
|         loader = self.find('__phello__')
 | |
|         self.assertTrue(hasattr(loader, 'load_module'))
 | |
| 
 | |
|     def test_module_in_package(self):
 | |
|         loader = self.find('__phello__.spam', ['__phello__'])
 | |
|         self.assertTrue(hasattr(loader, 'load_module'))
 | |
| 
 | |
|     # No frozen package within another package to test with.
 | |
|     test_package_in_package = None
 | |
| 
 | |
|     # No easy way to test.
 | |
|     test_package_over_module = None
 | |
| 
 | |
|     def test_failure(self):
 | |
|         loader = self.find('<not real>')
 | |
|         self.assertIsNone(loader)
 | |
| 
 | |
| 
 | |
| (Frozen_FinderTests,
 | |
|  Source_FinderTests
 | |
|  ) = util.test_both(FinderTests, machinery=machinery)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest.main()
 |