(root)/
Python-3.11.7/
Lib/
test/
test_importlib/
test_lazy.py
       1  import importlib
       2  from importlib import abc
       3  from importlib import util
       4  import sys
       5  import types
       6  import unittest
       7  
       8  from test.test_importlib import util as test_util
       9  
      10  
      11  class ESC[4;38;5;81mCollectInit:
      12  
      13      def __init__(self, *args, **kwargs):
      14          self.args = args
      15          self.kwargs = kwargs
      16  
      17      def exec_module(self, module):
      18          return self
      19  
      20  
      21  class ESC[4;38;5;81mLazyLoaderFactoryTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      22  
      23      def test_init(self):
      24          factory = util.LazyLoader.factory(CollectInit)
      25          # E.g. what importlib.machinery.FileFinder instantiates loaders with
      26          # plus keyword arguments.
      27          lazy_loader = factory('module name', 'module path', kw='kw')
      28          loader = lazy_loader.loader
      29          self.assertEqual(('module name', 'module path'), loader.args)
      30          self.assertEqual({'kw': 'kw'}, loader.kwargs)
      31  
      32      def test_validation(self):
      33          # No exec_module(), no lazy loading.
      34          with self.assertRaises(TypeError):
      35              util.LazyLoader.factory(object)
      36  
      37  
      38  class ESC[4;38;5;81mTestingImporter(ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mMetaPathFinder, ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mLoader):
      39  
      40      module_name = 'lazy_loader_test'
      41      mutated_name = 'changed'
      42      loaded = None
      43      source_code = 'attr = 42; __name__ = {!r}'.format(mutated_name)
      44  
      45      def find_spec(self, name, path, target=None):
      46          if name != self.module_name:
      47              return None
      48          return util.spec_from_loader(name, util.LazyLoader(self))
      49  
      50      def exec_module(self, module):
      51          exec(self.source_code, module.__dict__)
      52          self.loaded = module
      53  
      54  
      55  class ESC[4;38;5;81mLazyLoaderTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      56  
      57      def test_init(self):
      58          with self.assertRaises(TypeError):
      59              # Classes that don't define exec_module() trigger TypeError.
      60              util.LazyLoader(object)
      61  
      62      def new_module(self, source_code=None):
      63          loader = TestingImporter()
      64          if source_code is not None:
      65              loader.source_code = source_code
      66          spec = util.spec_from_loader(TestingImporter.module_name,
      67                                       util.LazyLoader(loader))
      68          module = spec.loader.create_module(spec)
      69          if module is None:
      70              module = types.ModuleType(TestingImporter.module_name)
      71          module.__spec__ = spec
      72          module.__loader__ = spec.loader
      73          spec.loader.exec_module(module)
      74          # Module is now lazy.
      75          self.assertIsNone(loader.loaded)
      76          return module
      77  
      78      def test_e2e(self):
      79          # End-to-end test to verify the load is in fact lazy.
      80          importer = TestingImporter()
      81          assert importer.loaded is None
      82          with test_util.uncache(importer.module_name):
      83              with test_util.import_state(meta_path=[importer]):
      84                  module = importlib.import_module(importer.module_name)
      85          self.assertIsNone(importer.loaded)
      86          # Trigger load.
      87          self.assertEqual(module.__loader__, importer)
      88          self.assertIsNotNone(importer.loaded)
      89          self.assertEqual(module, importer.loaded)
      90  
      91      def test_attr_unchanged(self):
      92          # An attribute only mutated as a side-effect of import should not be
      93          # changed needlessly.
      94          module = self.new_module()
      95          self.assertEqual(TestingImporter.mutated_name, module.__name__)
      96  
      97      def test_new_attr(self):
      98          # A new attribute should persist.
      99          module = self.new_module()
     100          module.new_attr = 42
     101          self.assertEqual(42, module.new_attr)
     102  
     103      def test_mutated_preexisting_attr(self):
     104          # Changing an attribute that already existed on the module --
     105          # e.g. __name__ -- should persist.
     106          module = self.new_module()
     107          module.__name__ = 'bogus'
     108          self.assertEqual('bogus', module.__name__)
     109  
     110      def test_mutated_attr(self):
     111          # Changing an attribute that comes into existence after an import
     112          # should persist.
     113          module = self.new_module()
     114          module.attr = 6
     115          self.assertEqual(6, module.attr)
     116  
     117      def test_delete_eventual_attr(self):
     118          # Deleting an attribute should stay deleted.
     119          module = self.new_module()
     120          del module.attr
     121          self.assertFalse(hasattr(module, 'attr'))
     122  
     123      def test_delete_preexisting_attr(self):
     124          module = self.new_module()
     125          del module.__name__
     126          self.assertFalse(hasattr(module, '__name__'))
     127  
     128      def test_module_substitution_error(self):
     129          with test_util.uncache(TestingImporter.module_name):
     130              fresh_module = types.ModuleType(TestingImporter.module_name)
     131              sys.modules[TestingImporter.module_name] = fresh_module
     132              module = self.new_module()
     133              with self.assertRaisesRegex(ValueError, "substituted"):
     134                  module.__name__
     135  
     136      def test_module_already_in_sys(self):
     137          with test_util.uncache(TestingImporter.module_name):
     138              module = self.new_module()
     139              sys.modules[TestingImporter.module_name] = module
     140              # Force the load; just care that no exception is raised.
     141              module.__name__
     142  
     143  
     144  if __name__ == '__main__':
     145      unittest.main()