1  """Test that sys.modules is used properly by import."""
       2  from test.test_importlib import util
       3  import sys
       4  from types import MethodType
       5  import unittest
       6  import warnings
       7  
       8  
       9  class ESC[4;38;5;81mUseCache:
      10  
      11      """When it comes to sys.modules, import prefers it over anything else.
      12  
      13      Once a name has been resolved, sys.modules is checked to see if it contains
      14      the module desired. If so, then it is returned [use cache]. If it is not
      15      found, then the proper steps are taken to perform the import, but
      16      sys.modules is still used to return the imported module (e.g., not what a
      17      loader returns) [from cache on return]. This also applies to imports of
      18      things contained within a package and thus get assigned as an attribute
      19      [from cache to attribute] or pulled in thanks to a fromlist import
      20      [from cache for fromlist]. But if sys.modules contains None then
      21      ImportError is raised [None in cache].
      22  
      23      """
      24  
      25      def test_using_cache(self):
      26          # [use cache]
      27          module_to_use = "some module found!"
      28          with util.uncache('some_module'):
      29              sys.modules['some_module'] = module_to_use
      30              module = self.__import__('some_module')
      31              self.assertEqual(id(module_to_use), id(module))
      32  
      33      def test_None_in_cache(self):
      34          #[None in cache]
      35          name = 'using_None'
      36          with util.uncache(name):
      37              sys.modules[name] = None
      38              with self.assertRaises(ImportError) as cm:
      39                  self.__import__(name)
      40              self.assertEqual(cm.exception.name, name)
      41  
      42  
      43  (Frozen_UseCache,
      44   Source_UseCache
      45   ) = util.test_both(UseCache, __import__=util.__import__)
      46  
      47  
      48  class ESC[4;38;5;81mImportlibUseCache(ESC[4;38;5;149mUseCache, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      49  
      50      # Pertinent only to PEP 302; exec_module() doesn't return a module.
      51  
      52      __import__ = util.__import__['Source']
      53  
      54      def create_mock(self, *names, return_=None):
      55          mock = util.mock_spec(*names)
      56          original_spec = mock.find_spec
      57          def find_spec(self, fullname, path, target=None):
      58              return original_spec(fullname)
      59          mock.find_spec = MethodType(find_spec, mock)
      60          return mock
      61  
      62      # __import__ inconsistent between loaders and built-in import when it comes
      63      #   to when to use the module in sys.modules and when not to.
      64      def test_using_cache_after_loader(self):
      65          # [from cache on return]
      66          with warnings.catch_warnings():
      67              warnings.simplefilter("ignore", ImportWarning)
      68              with self.create_mock('module') as mock:
      69                  with util.import_state(meta_path=[mock]):
      70                      module = self.__import__('module')
      71                      self.assertEqual(id(module), id(sys.modules['module']))
      72  
      73      # See test_using_cache_after_loader() for reasoning.
      74      def test_using_cache_for_assigning_to_attribute(self):
      75          # [from cache to attribute]
      76          with warnings.catch_warnings():
      77              warnings.simplefilter("ignore", ImportWarning)
      78              with self.create_mock('pkg.__init__', 'pkg.module') as importer:
      79                  with util.import_state(meta_path=[importer]):
      80                      module = self.__import__('pkg.module')
      81                      self.assertTrue(hasattr(module, 'module'))
      82                      self.assertEqual(id(module.module),
      83                                      id(sys.modules['pkg.module']))
      84  
      85      # See test_using_cache_after_loader() for reasoning.
      86      def test_using_cache_for_fromlist(self):
      87          # [from cache for fromlist]
      88          with self.create_mock('pkg.__init__', 'pkg.module') as importer:
      89              with util.import_state(meta_path=[importer]):
      90                  module = self.__import__('pkg', fromlist=['module'])
      91                  self.assertTrue(hasattr(module, 'module'))
      92                  self.assertEqual(id(module.module),
      93                                   id(sys.modules['pkg.module']))
      94  
      95  
      96  if __name__ == '__main__':
      97      unittest.main()