~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Lib/test/test_importlib/test_api.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from . import util
 
2
 
 
3
frozen_init, source_init = util.import_importlib('importlib')
 
4
frozen_util, source_util = util.import_importlib('importlib.util')
 
5
frozen_machinery, source_machinery = util.import_importlib('importlib.machinery')
 
6
 
 
7
import os.path
 
8
import sys
 
9
from test import support
 
10
import types
 
11
import unittest
 
12
 
 
13
 
 
14
class ImportModuleTests:
 
15
 
 
16
    """Test importlib.import_module."""
 
17
 
 
18
    def test_module_import(self):
 
19
        # Test importing a top-level module.
 
20
        with util.mock_modules('top_level') as mock:
 
21
            with util.import_state(meta_path=[mock]):
 
22
                module = self.init.import_module('top_level')
 
23
                self.assertEqual(module.__name__, 'top_level')
 
24
 
 
25
    def test_absolute_package_import(self):
 
26
        # Test importing a module from a package with an absolute name.
 
27
        pkg_name = 'pkg'
 
28
        pkg_long_name = '{0}.__init__'.format(pkg_name)
 
29
        name = '{0}.mod'.format(pkg_name)
 
30
        with util.mock_modules(pkg_long_name, name) as mock:
 
31
            with util.import_state(meta_path=[mock]):
 
32
                module = self.init.import_module(name)
 
33
                self.assertEqual(module.__name__, name)
 
34
 
 
35
    def test_shallow_relative_package_import(self):
 
36
        # Test importing a module from a package through a relative import.
 
37
        pkg_name = 'pkg'
 
38
        pkg_long_name = '{0}.__init__'.format(pkg_name)
 
39
        module_name = 'mod'
 
40
        absolute_name = '{0}.{1}'.format(pkg_name, module_name)
 
41
        relative_name = '.{0}'.format(module_name)
 
42
        with util.mock_modules(pkg_long_name, absolute_name) as mock:
 
43
            with util.import_state(meta_path=[mock]):
 
44
                self.init.import_module(pkg_name)
 
45
                module = self.init.import_module(relative_name, pkg_name)
 
46
                self.assertEqual(module.__name__, absolute_name)
 
47
 
 
48
    def test_deep_relative_package_import(self):
 
49
        modules = ['a.__init__', 'a.b.__init__', 'a.c']
 
50
        with util.mock_modules(*modules) as mock:
 
51
            with util.import_state(meta_path=[mock]):
 
52
                self.init.import_module('a')
 
53
                self.init.import_module('a.b')
 
54
                module = self.init.import_module('..c', 'a.b')
 
55
                self.assertEqual(module.__name__, 'a.c')
 
56
 
 
57
    def test_absolute_import_with_package(self):
 
58
        # Test importing a module from a package with an absolute name with
 
59
        # the 'package' argument given.
 
60
        pkg_name = 'pkg'
 
61
        pkg_long_name = '{0}.__init__'.format(pkg_name)
 
62
        name = '{0}.mod'.format(pkg_name)
 
63
        with util.mock_modules(pkg_long_name, name) as mock:
 
64
            with util.import_state(meta_path=[mock]):
 
65
                self.init.import_module(pkg_name)
 
66
                module = self.init.import_module(name, pkg_name)
 
67
                self.assertEqual(module.__name__, name)
 
68
 
 
69
    def test_relative_import_wo_package(self):
 
70
        # Relative imports cannot happen without the 'package' argument being
 
71
        # set.
 
72
        with self.assertRaises(TypeError):
 
73
            self.init.import_module('.support')
 
74
 
 
75
 
 
76
    def test_loaded_once(self):
 
77
        # Issue #13591: Modules should only be loaded once when
 
78
        # initializing the parent package attempts to import the
 
79
        # module currently being imported.
 
80
        b_load_count = 0
 
81
        def load_a():
 
82
            self.init.import_module('a.b')
 
83
        def load_b():
 
84
            nonlocal b_load_count
 
85
            b_load_count += 1
 
86
        code = {'a': load_a, 'a.b': load_b}
 
87
        modules = ['a.__init__', 'a.b']
 
88
        with util.mock_modules(*modules, module_code=code) as mock:
 
89
            with util.import_state(meta_path=[mock]):
 
90
                self.init.import_module('a.b')
 
91
        self.assertEqual(b_load_count, 1)
 
92
 
 
93
class Frozen_ImportModuleTests(ImportModuleTests, unittest.TestCase):
 
94
    init = frozen_init
 
95
 
 
96
class Source_ImportModuleTests(ImportModuleTests, unittest.TestCase):
 
97
    init = source_init
 
98
 
 
99
 
 
100
class FindLoaderTests:
 
101
 
 
102
    class FakeMetaFinder:
 
103
        @staticmethod
 
104
        def find_module(name, path=None): return name, path
 
105
 
 
106
    def test_sys_modules(self):
 
107
        # If a module with __loader__ is in sys.modules, then return it.
 
108
        name = 'some_mod'
 
109
        with util.uncache(name):
 
110
            module = types.ModuleType(name)
 
111
            loader = 'a loader!'
 
112
            module.__loader__ = loader
 
113
            sys.modules[name] = module
 
114
            found = self.init.find_loader(name)
 
115
            self.assertEqual(loader, found)
 
116
 
 
117
    def test_sys_modules_loader_is_None(self):
 
118
        # If sys.modules[name].__loader__ is None, raise ValueError.
 
119
        name = 'some_mod'
 
120
        with util.uncache(name):
 
121
            module = types.ModuleType(name)
 
122
            module.__loader__ = None
 
123
            sys.modules[name] = module
 
124
            with self.assertRaises(ValueError):
 
125
                self.init.find_loader(name)
 
126
 
 
127
    def test_sys_modules_loader_is_not_set(self):
 
128
        # Should raise ValueError
 
129
        # Issue #17099
 
130
        name = 'some_mod'
 
131
        with util.uncache(name):
 
132
            module = types.ModuleType(name)
 
133
            try:
 
134
                del module.__loader__
 
135
            except AttributeError:
 
136
                pass
 
137
            sys.modules[name] = module
 
138
            with self.assertRaises(ValueError):
 
139
                self.init.find_loader(name)
 
140
 
 
141
    def test_success(self):
 
142
        # Return the loader found on sys.meta_path.
 
143
        name = 'some_mod'
 
144
        with util.uncache(name):
 
145
            with util.import_state(meta_path=[self.FakeMetaFinder]):
 
146
                self.assertEqual((name, None), self.init.find_loader(name))
 
147
 
 
148
    def test_success_path(self):
 
149
        # Searching on a path should work.
 
150
        name = 'some_mod'
 
151
        path = 'path to some place'
 
152
        with util.uncache(name):
 
153
            with util.import_state(meta_path=[self.FakeMetaFinder]):
 
154
                self.assertEqual((name, path),
 
155
                                 self.init.find_loader(name, path))
 
156
 
 
157
    def test_nothing(self):
 
158
        # None is returned upon failure to find a loader.
 
159
        self.assertIsNone(self.init.find_loader('nevergoingtofindthismodule'))
 
160
 
 
161
class Frozen_FindLoaderTests(FindLoaderTests, unittest.TestCase):
 
162
    init = frozen_init
 
163
 
 
164
class Source_FindLoaderTests(FindLoaderTests, unittest.TestCase):
 
165
    init = source_init
 
166
 
 
167
 
 
168
class FindSpecTests:
 
169
 
 
170
    class FakeMetaFinder:
 
171
        @staticmethod
 
172
        def find_spec(name, path=None, target=None): return name, path, target
 
173
 
 
174
    def test_sys_modules(self):
 
175
        name = 'some_mod'
 
176
        with util.uncache(name):
 
177
            module = types.ModuleType(name)
 
178
            loader = 'a loader!'
 
179
            spec = self.machinery.ModuleSpec(name, loader)
 
180
            module.__loader__ = loader
 
181
            module.__spec__ = spec
 
182
            sys.modules[name] = module
 
183
            found = self.init.find_spec(name)
 
184
            self.assertEqual(found, spec)
 
185
 
 
186
    def test_sys_modules_without___loader__(self):
 
187
        name = 'some_mod'
 
188
        with util.uncache(name):
 
189
            module = types.ModuleType(name)
 
190
            del module.__loader__
 
191
            loader = 'a loader!'
 
192
            spec = self.machinery.ModuleSpec(name, loader)
 
193
            module.__spec__ = spec
 
194
            sys.modules[name] = module
 
195
            found = self.init.find_spec(name)
 
196
            self.assertEqual(found, spec)
 
197
 
 
198
    def test_sys_modules_spec_is_None(self):
 
199
        name = 'some_mod'
 
200
        with util.uncache(name):
 
201
            module = types.ModuleType(name)
 
202
            module.__spec__ = None
 
203
            sys.modules[name] = module
 
204
            with self.assertRaises(ValueError):
 
205
                self.init.find_spec(name)
 
206
 
 
207
    def test_sys_modules_loader_is_None(self):
 
208
        name = 'some_mod'
 
209
        with util.uncache(name):
 
210
            module = types.ModuleType(name)
 
211
            spec = self.machinery.ModuleSpec(name, None)
 
212
            module.__spec__ = spec
 
213
            sys.modules[name] = module
 
214
            found = self.init.find_spec(name)
 
215
            self.assertEqual(found, spec)
 
216
 
 
217
    def test_sys_modules_spec_is_not_set(self):
 
218
        name = 'some_mod'
 
219
        with util.uncache(name):
 
220
            module = types.ModuleType(name)
 
221
            try:
 
222
                del module.__spec__
 
223
            except AttributeError:
 
224
                pass
 
225
            sys.modules[name] = module
 
226
            with self.assertRaises(ValueError):
 
227
                self.init.find_spec(name)
 
228
 
 
229
    def test_success(self):
 
230
        name = 'some_mod'
 
231
        with util.uncache(name):
 
232
            with util.import_state(meta_path=[self.FakeMetaFinder]):
 
233
                self.assertEqual((name, None, None),
 
234
                                 self.init.find_spec(name))
 
235
 
 
236
    def test_success_path(self):
 
237
        # Searching on a path should work.
 
238
        name = 'some_mod'
 
239
        path = 'path to some place'
 
240
        with util.uncache(name):
 
241
            with util.import_state(meta_path=[self.FakeMetaFinder]):
 
242
                self.assertEqual((name, path, None),
 
243
                                 self.init.find_spec(name, path))
 
244
 
 
245
    def test_nothing(self):
 
246
        # None is returned upon failure to find a loader.
 
247
        self.assertIsNone(self.init.find_spec('nevergoingtofindthismodule'))
 
248
 
 
249
class Frozen_FindSpecTests(FindSpecTests, unittest.TestCase):
 
250
    init = frozen_init
 
251
    machinery = frozen_machinery
 
252
 
 
253
class Source_FindSpecTests(FindSpecTests, unittest.TestCase):
 
254
    init = source_init
 
255
    machinery = source_machinery
 
256
 
 
257
 
 
258
class ReloadTests:
 
259
 
 
260
    """Test module reloading for builtin and extension modules."""
 
261
 
 
262
    def test_reload_modules(self):
 
263
        for mod in ('tokenize', 'time', 'marshal'):
 
264
            with self.subTest(module=mod):
 
265
                with support.CleanImport(mod):
 
266
                    module = self.init.import_module(mod)
 
267
                    self.init.reload(module)
 
268
 
 
269
    def test_module_replaced(self):
 
270
        def code():
 
271
            import sys
 
272
            module = type(sys)('top_level')
 
273
            module.spam = 3
 
274
            sys.modules['top_level'] = module
 
275
        mock = util.mock_modules('top_level',
 
276
                                 module_code={'top_level': code})
 
277
        with mock:
 
278
            with util.import_state(meta_path=[mock]):
 
279
                module = self.init.import_module('top_level')
 
280
                reloaded = self.init.reload(module)
 
281
                actual = sys.modules['top_level']
 
282
                self.assertEqual(actual.spam, 3)
 
283
                self.assertEqual(reloaded.spam, 3)
 
284
 
 
285
    def test_reload_missing_loader(self):
 
286
        with support.CleanImport('types'):
 
287
            import types
 
288
            loader = types.__loader__
 
289
            del types.__loader__
 
290
            reloaded = self.init.reload(types)
 
291
 
 
292
            self.assertIs(reloaded, types)
 
293
            self.assertIs(sys.modules['types'], types)
 
294
            self.assertEqual(reloaded.__loader__.path, loader.path)
 
295
 
 
296
    def test_reload_loader_replaced(self):
 
297
        with support.CleanImport('types'):
 
298
            import types
 
299
            types.__loader__ = None
 
300
            self.init.invalidate_caches()
 
301
            reloaded = self.init.reload(types)
 
302
 
 
303
            self.assertIsNot(reloaded.__loader__, None)
 
304
            self.assertIs(reloaded, types)
 
305
            self.assertIs(sys.modules['types'], types)
 
306
 
 
307
    def test_reload_location_changed(self):
 
308
        name = 'spam'
 
309
        with support.temp_cwd(None) as cwd:
 
310
            with util.uncache('spam'):
 
311
                with support.DirsOnSysPath(cwd):
 
312
                    # Start as a plain module.
 
313
                    self.init.invalidate_caches()
 
314
                    path = os.path.join(cwd, name + '.py')
 
315
                    cached = self.util.cache_from_source(path)
 
316
                    expected = {'__name__': name,
 
317
                                '__package__': '',
 
318
                                '__file__': path,
 
319
                                '__cached__': cached,
 
320
                                '__doc__': None,
 
321
                                '__builtins__': __builtins__,
 
322
                                }
 
323
                    support.create_empty_file(path)
 
324
                    module = self.init.import_module(name)
 
325
                    ns = vars(module)
 
326
                    loader = ns.pop('__loader__')
 
327
                    spec = ns.pop('__spec__')
 
328
                    self.assertEqual(spec.name, name)
 
329
                    self.assertEqual(spec.loader, loader)
 
330
                    self.assertEqual(loader.path, path)
 
331
                    self.assertEqual(ns, expected)
 
332
 
 
333
                    # Change to a package.
 
334
                    self.init.invalidate_caches()
 
335
                    init_path = os.path.join(cwd, name, '__init__.py')
 
336
                    cached = self.util.cache_from_source(init_path)
 
337
                    expected = {'__name__': name,
 
338
                                '__package__': name,
 
339
                                '__file__': init_path,
 
340
                                '__cached__': cached,
 
341
                                '__path__': [os.path.dirname(init_path)],
 
342
                                '__doc__': None,
 
343
                                '__builtins__': __builtins__,
 
344
                                }
 
345
                    os.mkdir(name)
 
346
                    os.rename(path, init_path)
 
347
                    reloaded = self.init.reload(module)
 
348
                    ns = vars(reloaded)
 
349
                    loader = ns.pop('__loader__')
 
350
                    spec = ns.pop('__spec__')
 
351
                    self.assertEqual(spec.name, name)
 
352
                    self.assertEqual(spec.loader, loader)
 
353
                    self.assertIs(reloaded, module)
 
354
                    self.assertEqual(loader.path, init_path)
 
355
                    self.maxDiff = None
 
356
                    self.assertEqual(ns, expected)
 
357
 
 
358
    def test_reload_namespace_changed(self):
 
359
        name = 'spam'
 
360
        with support.temp_cwd(None) as cwd:
 
361
            with util.uncache('spam'):
 
362
                with support.DirsOnSysPath(cwd):
 
363
                    # Start as a namespace package.
 
364
                    self.init.invalidate_caches()
 
365
                    bad_path = os.path.join(cwd, name, '__init.py')
 
366
                    cached = self.util.cache_from_source(bad_path)
 
367
                    expected = {'__name__': name,
 
368
                                '__package__': name,
 
369
                                '__doc__': None,
 
370
                                }
 
371
                    os.mkdir(name)
 
372
                    with open(bad_path, 'w') as init_file:
 
373
                        init_file.write('eggs = None')
 
374
                    module = self.init.import_module(name)
 
375
                    ns = vars(module)
 
376
                    loader = ns.pop('__loader__')
 
377
                    path = ns.pop('__path__')
 
378
                    spec = ns.pop('__spec__')
 
379
                    self.assertEqual(spec.name, name)
 
380
                    self.assertIs(spec.loader, None)
 
381
                    self.assertIsNot(loader, None)
 
382
                    self.assertEqual(set(path),
 
383
                                     set([os.path.dirname(bad_path)]))
 
384
                    with self.assertRaises(AttributeError):
 
385
                        # a NamespaceLoader
 
386
                        loader.path
 
387
                    self.assertEqual(ns, expected)
 
388
 
 
389
                    # Change to a regular package.
 
390
                    self.init.invalidate_caches()
 
391
                    init_path = os.path.join(cwd, name, '__init__.py')
 
392
                    cached = self.util.cache_from_source(init_path)
 
393
                    expected = {'__name__': name,
 
394
                                '__package__': name,
 
395
                                '__file__': init_path,
 
396
                                '__cached__': cached,
 
397
                                '__path__': [os.path.dirname(init_path)],
 
398
                                '__doc__': None,
 
399
                                '__builtins__': __builtins__,
 
400
                                'eggs': None,
 
401
                                }
 
402
                    os.rename(bad_path, init_path)
 
403
                    reloaded = self.init.reload(module)
 
404
                    ns = vars(reloaded)
 
405
                    loader = ns.pop('__loader__')
 
406
                    spec = ns.pop('__spec__')
 
407
                    self.assertEqual(spec.name, name)
 
408
                    self.assertEqual(spec.loader, loader)
 
409
                    self.assertIs(reloaded, module)
 
410
                    self.assertEqual(loader.path, init_path)
 
411
                    self.assertEqual(ns, expected)
 
412
 
 
413
 
 
414
class Frozen_ReloadTests(ReloadTests, unittest.TestCase):
 
415
    init = frozen_init
 
416
    util = frozen_util
 
417
 
 
418
class Source_ReloadTests(ReloadTests, unittest.TestCase):
 
419
    init = source_init
 
420
    util = source_util
 
421
 
 
422
 
 
423
class InvalidateCacheTests:
 
424
 
 
425
    def test_method_called(self):
 
426
        # If defined the method should be called.
 
427
        class InvalidatingNullFinder:
 
428
            def __init__(self, *ignored):
 
429
                self.called = False
 
430
            def find_module(self, *args):
 
431
                return None
 
432
            def invalidate_caches(self):
 
433
                self.called = True
 
434
 
 
435
        key = 'gobledeegook'
 
436
        meta_ins = InvalidatingNullFinder()
 
437
        path_ins = InvalidatingNullFinder()
 
438
        sys.meta_path.insert(0, meta_ins)
 
439
        self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
 
440
        sys.path_importer_cache[key] = path_ins
 
441
        self.addCleanup(lambda: sys.meta_path.remove(meta_ins))
 
442
        self.init.invalidate_caches()
 
443
        self.assertTrue(meta_ins.called)
 
444
        self.assertTrue(path_ins.called)
 
445
 
 
446
    def test_method_lacking(self):
 
447
        # There should be no issues if the method is not defined.
 
448
        key = 'gobbledeegook'
 
449
        sys.path_importer_cache[key] = None
 
450
        self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
 
451
        self.init.invalidate_caches()  # Shouldn't trigger an exception.
 
452
 
 
453
class Frozen_InvalidateCacheTests(InvalidateCacheTests, unittest.TestCase):
 
454
    init = frozen_init
 
455
 
 
456
class Source_InvalidateCacheTests(InvalidateCacheTests, unittest.TestCase):
 
457
    init = source_init
 
458
 
 
459
 
 
460
class FrozenImportlibTests(unittest.TestCase):
 
461
 
 
462
    def test_no_frozen_importlib(self):
 
463
        # Should be able to import w/o _frozen_importlib being defined.
 
464
        # Can't do an isinstance() check since separate copies of importlib
 
465
        # may have been used for import, so just check the name is not for the
 
466
        # frozen loader.
 
467
        self.assertNotEqual(source_init.__loader__.__class__.__name__,
 
468
                            'FrozenImporter')
 
469
 
 
470
 
 
471
class StartupTests:
 
472
 
 
473
    def test_everyone_has___loader__(self):
 
474
        # Issue #17098: all modules should have __loader__ defined.
 
475
        for name, module in sys.modules.items():
 
476
            if isinstance(module, types.ModuleType):
 
477
                with self.subTest(name=name):
 
478
                    self.assertTrue(hasattr(module, '__loader__'),
 
479
                                    '{!r} lacks a __loader__ attribute'.format(name))
 
480
                    if self.machinery.BuiltinImporter.find_module(name):
 
481
                        self.assertIsNot(module.__loader__, None)
 
482
                    elif self.machinery.FrozenImporter.find_module(name):
 
483
                        self.assertIsNot(module.__loader__, None)
 
484
 
 
485
    def test_everyone_has___spec__(self):
 
486
        for name, module in sys.modules.items():
 
487
            if isinstance(module, types.ModuleType):
 
488
                with self.subTest(name=name):
 
489
                    self.assertTrue(hasattr(module, '__spec__'))
 
490
                    if self.machinery.BuiltinImporter.find_module(name):
 
491
                        self.assertIsNot(module.__spec__, None)
 
492
                    elif self.machinery.FrozenImporter.find_module(name):
 
493
                        self.assertIsNot(module.__spec__, None)
 
494
 
 
495
class Frozen_StartupTests(StartupTests, unittest.TestCase):
 
496
    machinery = frozen_machinery
 
497
 
 
498
class Source_StartupTests(StartupTests, unittest.TestCase):
 
499
    machinery = source_machinery
 
500
 
 
501
 
 
502
if __name__ == '__main__':
 
503
    unittest.main()