Home | History | Annotate | Download | only in import_
      1 from .. import util
      2 
      3 importlib = util.import_importlib('importlib')
      4 machinery = util.import_importlib('importlib.machinery')
      5 
      6 import os
      7 import sys
      8 import tempfile
      9 from types import ModuleType
     10 import unittest
     11 import warnings
     12 import zipimport
     13 
     14 
     15 class FinderTests:
     16 
     17     """Tests for PathFinder."""
     18 
     19     find = None
     20     check_found = None
     21 
     22     def test_failure(self):
     23         # Test None returned upon not finding a suitable loader.
     24         module = '<test module>'
     25         with util.import_state():
     26             self.assertIsNone(self.find(module))
     27 
     28     def test_sys_path(self):
     29         # Test that sys.path is used when 'path' is None.
     30         # Implicitly tests that sys.path_importer_cache is used.
     31         module = '<test module>'
     32         path = '<test path>'
     33         importer = util.mock_spec(module)
     34         with util.import_state(path_importer_cache={path: importer},
     35                                path=[path]):
     36             found = self.find(module)
     37             self.check_found(found, importer)
     38 
     39     def test_path(self):
     40         # Test that 'path' is used when set.
     41         # Implicitly tests that sys.path_importer_cache is used.
     42         module = '<test module>'
     43         path = '<test path>'
     44         importer = util.mock_spec(module)
     45         with util.import_state(path_importer_cache={path: importer}):
     46             found = self.find(module, [path])
     47             self.check_found(found, importer)
     48 
     49     def test_empty_list(self):
     50         # An empty list should not count as asking for sys.path.
     51         module = 'module'
     52         path = '<test path>'
     53         importer = util.mock_spec(module)
     54         with util.import_state(path_importer_cache={path: importer},
     55                                path=[path]):
     56             self.assertIsNone(self.find('module', []))
     57 
     58     def test_path_hooks(self):
     59         # Test that sys.path_hooks is used.
     60         # Test that sys.path_importer_cache is set.
     61         module = '<test module>'
     62         path = '<test path>'
     63         importer = util.mock_spec(module)
     64         hook = util.mock_path_hook(path, importer=importer)
     65         with util.import_state(path_hooks=[hook]):
     66             found = self.find(module, [path])
     67             self.check_found(found, importer)
     68             self.assertIn(path, sys.path_importer_cache)
     69             self.assertIs(sys.path_importer_cache[path], importer)
     70 
     71     def test_empty_path_hooks(self):
     72         # Test that if sys.path_hooks is empty a warning is raised,
     73         # sys.path_importer_cache gets None set, and PathFinder returns None.
     74         path_entry = 'bogus_path'
     75         with util.import_state(path_importer_cache={}, path_hooks=[],
     76                                path=[path_entry]):
     77             with warnings.catch_warnings(record=True) as w:
     78                 warnings.simplefilter('always')
     79                 self.assertIsNone(self.find('os'))
     80                 self.assertIsNone(sys.path_importer_cache[path_entry])
     81                 self.assertEqual(len(w), 1)
     82                 self.assertTrue(issubclass(w[-1].category, ImportWarning))
     83 
     84     def test_path_importer_cache_empty_string(self):
     85         # The empty string should create a finder using the cwd.
     86         path = ''
     87         module = '<test module>'
     88         importer = util.mock_spec(module)
     89         hook = util.mock_path_hook(os.getcwd(), importer=importer)
     90         with util.import_state(path=[path], path_hooks=[hook]):
     91             found = self.find(module)
     92             self.check_found(found, importer)
     93             self.assertIn(os.getcwd(), sys.path_importer_cache)
     94 
     95     def test_None_on_sys_path(self):
     96         # Putting None in sys.path[0] caused an import regression from Python
     97         # 3.2: http://bugs.python.org/issue16514
     98         new_path = sys.path[:]
     99         new_path.insert(0, None)
    100         new_path_importer_cache = sys.path_importer_cache.copy()
    101         new_path_importer_cache.pop(None, None)
    102         new_path_hooks = [zipimport.zipimporter,
    103                           self.machinery.FileFinder.path_hook(
    104                               *self.importlib._bootstrap_external._get_supported_file_loaders())]
    105         missing = object()
    106         email = sys.modules.pop('email', missing)
    107         try:
    108             with util.import_state(meta_path=sys.meta_path[:],
    109                                    path=new_path,
    110                                    path_importer_cache=new_path_importer_cache,
    111                                    path_hooks=new_path_hooks):
    112                 module = self.importlib.import_module('email')
    113                 self.assertIsInstance(module, ModuleType)
    114         finally:
    115             if email is not missing:
    116                 sys.modules['email'] = email
    117 
    118     def test_finder_with_find_module(self):
    119         class TestFinder:
    120             def find_module(self, fullname):
    121                 return self.to_return
    122         failing_finder = TestFinder()
    123         failing_finder.to_return = None
    124         path = 'testing path'
    125         with util.import_state(path_importer_cache={path: failing_finder}):
    126             self.assertIsNone(
    127                     self.machinery.PathFinder.find_spec('whatever', [path]))
    128         success_finder = TestFinder()
    129         success_finder.to_return = __loader__
    130         with util.import_state(path_importer_cache={path: success_finder}):
    131             spec = self.machinery.PathFinder.find_spec('whatever', [path])
    132         self.assertEqual(spec.loader, __loader__)
    133 
    134     def test_finder_with_find_loader(self):
    135         class TestFinder:
    136             loader = None
    137             portions = []
    138             def find_loader(self, fullname):
    139                 return self.loader, self.portions
    140         path = 'testing path'
    141         with util.import_state(path_importer_cache={path: TestFinder()}):
    142             self.assertIsNone(
    143                     self.machinery.PathFinder.find_spec('whatever', [path]))
    144         success_finder = TestFinder()
    145         success_finder.loader = __loader__
    146         with util.import_state(path_importer_cache={path: success_finder}):
    147             spec = self.machinery.PathFinder.find_spec('whatever', [path])
    148         self.assertEqual(spec.loader, __loader__)
    149 
    150     def test_finder_with_find_spec(self):
    151         class TestFinder:
    152             spec = None
    153             def find_spec(self, fullname, target=None):
    154                 return self.spec
    155         path = 'testing path'
    156         with util.import_state(path_importer_cache={path: TestFinder()}):
    157             self.assertIsNone(
    158                     self.machinery.PathFinder.find_spec('whatever', [path]))
    159         success_finder = TestFinder()
    160         success_finder.spec = self.machinery.ModuleSpec('whatever', __loader__)
    161         with util.import_state(path_importer_cache={path: success_finder}):
    162             got = self.machinery.PathFinder.find_spec('whatever', [path])
    163         self.assertEqual(got, success_finder.spec)
    164 
    165     def test_deleted_cwd(self):
    166         # Issue #22834
    167         old_dir = os.getcwd()
    168         self.addCleanup(os.chdir, old_dir)
    169         new_dir = tempfile.mkdtemp()
    170         try:
    171             os.chdir(new_dir)
    172             try:
    173                 os.rmdir(new_dir)
    174             except OSError:
    175                 # EINVAL on Solaris, EBUSY on AIX, ENOTEMPTY on Windows
    176                 self.skipTest("platform does not allow "
    177                               "the deletion of the cwd")
    178         except:
    179             os.chdir(old_dir)
    180             os.rmdir(new_dir)
    181             raise
    182 
    183         with util.import_state(path=['']):
    184             # Do not want FileNotFoundError raised.
    185             self.assertIsNone(self.machinery.PathFinder.find_spec('whatever'))
    186 
    187 
    188 class FindModuleTests(FinderTests):
    189     def find(self, *args, **kwargs):
    190         return self.machinery.PathFinder.find_module(*args, **kwargs)
    191     def check_found(self, found, importer):
    192         self.assertIs(found, importer)
    193 
    194 
    195 (Frozen_FindModuleTests,
    196  Source_FindModuleTests
    197 ) = util.test_both(FindModuleTests, importlib=importlib, machinery=machinery)
    198 
    199 
    200 class FindSpecTests(FinderTests):
    201     def find(self, *args, **kwargs):
    202         return self.machinery.PathFinder.find_spec(*args, **kwargs)
    203     def check_found(self, found, importer):
    204         self.assertIs(found.loader, importer)
    205 
    206 
    207 (Frozen_FindSpecTests,
    208  Source_FindSpecTests
    209  ) = util.test_both(FindSpecTests, importlib=importlib, machinery=machinery)
    210 
    211 
    212 class PathEntryFinderTests:
    213 
    214     def test_finder_with_failing_find_spec(self):
    215         # PathEntryFinder with find_module() defined should work.
    216         # Issue #20763.
    217         class Finder:
    218             path_location = 'test_finder_with_find_module'
    219             def __init__(self, path):
    220                 if path != self.path_location:
    221                     raise ImportError
    222 
    223             @staticmethod
    224             def find_module(fullname):
    225                 return None
    226 
    227 
    228         with util.import_state(path=[Finder.path_location]+sys.path[:],
    229                                path_hooks=[Finder]):
    230             self.machinery.PathFinder.find_spec('importlib')
    231 
    232     def test_finder_with_failing_find_module(self):
    233         # PathEntryFinder with find_module() defined should work.
    234         # Issue #20763.
    235         class Finder:
    236             path_location = 'test_finder_with_find_module'
    237             def __init__(self, path):
    238                 if path != self.path_location:
    239                     raise ImportError
    240 
    241             @staticmethod
    242             def find_module(fullname):
    243                 return None
    244 
    245 
    246         with util.import_state(path=[Finder.path_location]+sys.path[:],
    247                                path_hooks=[Finder]):
    248             self.machinery.PathFinder.find_module('importlib')
    249 
    250 
    251 (Frozen_PEFTests,
    252  Source_PEFTests
    253  ) = util.test_both(PathEntryFinderTests, machinery=machinery)
    254 
    255 
    256 if __name__ == '__main__':
    257     unittest.main()
    258