Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 1 | """Test that sys.modules is used properly by import.""" |
Brett Cannon | bcb26c5 | 2009-02-01 04:00:05 +0000 | [diff] [blame] | 2 | from .. import util |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 3 | from . import util as import_util |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 4 | import sys |
| 5 | from types import MethodType |
| 6 | import unittest |
| 7 | |
| 8 | |
| 9 | class UseCache(unittest.TestCase): |
| 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 |
Brett Cannon | 4d75fc1 | 2009-08-30 03:47:36 +0000 | [diff] [blame] | 20 | [from cache for fromlist]. But if sys.modules contains None then |
| 21 | ImportError is raised [None in cache]. |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 22 | |
| 23 | """ |
| 24 | def test_using_cache(self): |
| 25 | # [use cache] |
| 26 | module_to_use = "some module found!" |
Brett Cannon | 4d75fc1 | 2009-08-30 03:47:36 +0000 | [diff] [blame] | 27 | with util.uncache(module_to_use): |
| 28 | sys.modules['some_module'] = module_to_use |
| 29 | module = import_util.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): |
| 38 | import_util.import_(name) |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 39 | |
| 40 | def create_mock(self, *names, return_=None): |
Brett Cannon | bcb26c5 | 2009-02-01 04:00:05 +0000 | [diff] [blame] | 41 | mock = util.mock_modules(*names) |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 42 | original_load = mock.load_module |
| 43 | def load_module(self, fullname): |
| 44 | original_load(fullname) |
| 45 | return return_ |
| 46 | mock.load_module = MethodType(load_module, mock) |
| 47 | return mock |
| 48 | |
| 49 | # __import__ inconsistent between loaders and built-in import when it comes |
| 50 | # to when to use the module in sys.modules and when not to. |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 51 | @import_util.importlib_only |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 52 | def test_using_cache_after_loader(self): |
| 53 | # [from cache on return] |
| 54 | with self.create_mock('module') as mock: |
Brett Cannon | bcb26c5 | 2009-02-01 04:00:05 +0000 | [diff] [blame] | 55 | with util.import_state(meta_path=[mock]): |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 56 | module = import_util.import_('module') |
Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame^] | 57 | self.assertEqual(id(module), id(sys.modules['module'])) |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 58 | |
| 59 | # See test_using_cache_after_loader() for reasoning. |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 60 | @import_util.importlib_only |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 61 | def test_using_cache_for_assigning_to_attribute(self): |
| 62 | # [from cache to attribute] |
| 63 | with self.create_mock('pkg.__init__', 'pkg.module') as importer: |
Brett Cannon | bcb26c5 | 2009-02-01 04:00:05 +0000 | [diff] [blame] | 64 | with util.import_state(meta_path=[importer]): |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 65 | module = import_util.import_('pkg.module') |
Benjamin Peterson | c9c0f20 | 2009-06-30 23:06:06 +0000 | [diff] [blame] | 66 | self.assertTrue(hasattr(module, 'module')) |
| 67 | self.assertTrue(id(module.module), id(sys.modules['pkg.module'])) |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 68 | |
| 69 | # See test_using_cache_after_loader() for reasoning. |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 70 | @import_util.importlib_only |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 71 | def test_using_cache_for_fromlist(self): |
| 72 | # [from cache for fromlist] |
| 73 | with self.create_mock('pkg.__init__', 'pkg.module') as importer: |
Brett Cannon | bcb26c5 | 2009-02-01 04:00:05 +0000 | [diff] [blame] | 74 | with util.import_state(meta_path=[importer]): |
Brett Cannon | d720b36 | 2009-02-01 04:28:04 +0000 | [diff] [blame] | 75 | module = import_util.import_('pkg', fromlist=['module']) |
Benjamin Peterson | c9c0f20 | 2009-06-30 23:06:06 +0000 | [diff] [blame] | 76 | self.assertTrue(hasattr(module, 'module')) |
Ezio Melotti | b3aedd4 | 2010-11-20 19:04:17 +0000 | [diff] [blame^] | 77 | self.assertEqual(id(module.module), |
| 78 | id(sys.modules['pkg.module'])) |
Brett Cannon | 23cbd8a | 2009-01-18 00:24:28 +0000 | [diff] [blame] | 79 | |
| 80 | |
| 81 | def test_main(): |
| 82 | from test.support import run_unittest |
| 83 | run_unittest(UseCache) |
| 84 | |
| 85 | if __name__ == '__main__': |
| 86 | test_main() |