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