test importlib importmodule def testmoduleimportself test importing a toplevel module with testutil mockspec toplevel as mock with testutil importstatemetapathmock module self init importmodule toplevel self assertequalmodule name toplevel def testabsolutepackageimportself test importing a module from a package with an absolute name pkgname pkg pkglongname 0 init formatpkgname name 0 mod formatpkgname with testutil mockspecpkglongname name as mock with testutil importstatemetapathmock module self init importmodulename self assertequalmodule name name def testshallowrelativepackageimportself test importing a module from a package through a relative import pkgname pkg pkglongname 0 init formatpkgname modulename mod absolutename 0 1 formatpkgname modulename relativename 0 formatmodulename with testutil mockspecpkglongname absolutename as mock with testutil importstatemetapathmock self init importmodulepkgname module self init importmodulerelativename pkgname self assertequalmodule name absolutename def testdeeprelativepackageimportself modules a init a b init a c with testutil mockspecmodules as mock with testutil importstatemetapathmock self init importmodule a self init importmodule a b module self init importmodule c a b self assertequalmodule name a c def testabsoluteimportwithpackageself test importing a module from a package with an absolute name with the package argument given pkgname pkg pkglongname 0 init formatpkgname name 0 mod formatpkgname with testutil mockspecpkglongname name as mock with testutil importstatemetapathmock self init importmodulepkgname module self init importmodulename pkgname self assertequalmodule name name def testrelativeimportwopackageself relative imports cannot happen without the package argument being set with self assertraisestypeerror self init importmodule support def testloadedonceself issue 13591 modules should only be loaded once when initializing the parent package attempts to import the module currently being imported bloadcount 0 def loada self init importmodule a b def loadb nonlocal bloadcount bloadcount 1 code a loada a b loadb modules a init a b with testutil mockspecmodules modulecodecode as mock with testutil importstatemetapathmock self init importmodule a b self assertequalbloadcount 1 frozenimportmoduletests sourceimportmoduletests testutil testboth importmoduletests initinit utilutil machinerymachinery class findloadertests fakemetafinder none def testsysmodulesself if a module with spec loader is in sys modules then return it name somemod with testutil uncachename module types moduletypename loader a loader module spec self machinery modulespecname loader sys modulesname module spec self util findspecname self assertisnotnonespec self assertequalspec loader loader def testsysmodulesloaderisnoneself if sys modulesname spec loader is none raise valueerror name somemod with testutil uncachename module types moduletypename module loader none sys modulesname module with self assertraisesvalueerror self util findspecname def testsysmodulesloaderisnotsetself should raise valueerror issue 17099 name somemod with testutil uncachename module types moduletypename try del module spec loader except attributeerror pass sys modulesname module with self assertraisesvalueerror self util findspecname def testsuccessself return the loader found on sys metapath name somemod with testutil uncachename with testutil importstatemetapathself fakemetafinder spec self util findspecname self assertequalname name none spec name spec loader def testsuccesspathself searching on a path should work name somemod path path to some place with testutil uncachename with testutil importstatemetapathself fakemetafinder spec self util findspecname path self assertequalname spec name def testnothingself none is returned upon failure to find a loader self assertisnoneself util findspec nevergoingtofindthismodule class findloaderpep451testsfindloadertests class fakemetafinder staticmethod def findspecname pathnone targetnone return machinery source modulespecname name path frozenfindloaderpep451tests sourcefindloaderpep451tests testutil testboth findloaderpep451tests initinit utilutil machinerymachinery class reloadtests def testreloadmodulesself for mod in tokenize time marshal with self subtestmodulemod with importhelper cleanimportmod module self init importmodulemod self init reloadmodule def testmodulereplacedself def code import sys module typesys toplevel module spam 3 sys modules toplevel module mock testutil mockspec toplevel modulecode toplevel code with mock with testutil importstatemetapathmock module self init importmodule toplevel reloaded self init reloadmodule actual sys modules toplevel self assertequalactual spam 3 self assertequalreloaded spam 3 def testreloadmissingloaderself with importhelper cleanimport types import types loader types loader del types loader reloaded self init reloadtypes self assertisreloaded types self assertissys modules types types self assertequalreloaded loader path loader path def testreloadloaderreplacedself with importhelper cleanimport types import types types loader none self init invalidatecaches reloaded self init reloadtypes self assertisnotreloaded loader none self assertisreloaded types self assertissys modules types types def testreloadlocationchangedself name spam with oshelper tempcwdnone as cwd with testutil uncache spam with importhelper dirsonsyspathcwd start as a plain module self init invalidatecaches path os path joincwd name py cached self util cachefromsourcepath expected name name package file path cached cached doc none oshelper createemptyfilepath module self init importmodulename ns varsmodule copy loader ns pop loader spec ns pop spec ns pop builtins none an implementation detail self assertequalspec name name self assertequalspec loader loader self assertequalloader path path self assertequalns expected change to a package self init invalidatecaches initpath os path joincwd name init py cached self util cachefromsourceinitpath expected name name package name file initpath cached cached path os path dirnameinitpath doc none os mkdirname os renamepath initpath reloaded self init reloadmodule ns varsreloaded copy loader ns pop loader spec ns pop spec ns pop builtins none an implementation detail self assertequalspec name name self assertequalspec loader loader self assertisreloaded module self assertequalloader path initpath self maxdiff none self assertequalns expected def testreloadnamespacechangedself name spam with oshelper tempcwdnone as cwd with testutil uncache spam with testutil importstatepathcwd self init bootstrapexternal installself init bootstrap start as a namespace package self init invalidatecaches badpath os path joincwd name init py cached self util cachefromsourcebadpath expected name name package name doc none file none os mkdirname with openbadpath w encoding utf8 as initfile initfile write eggs none module self init importmodulename ns varsmodule copy loader ns pop loader path ns pop path spec ns pop spec ns pop builtins none an implementation detail self assertequalspec name name self assertisnotnonespec loader self assertisnotnoneloader self assertequalspec loader loader self assertequalsetpath setos path dirnamebadpath with self assertraisesattributeerror a namespaceloader loader path self assertequalns expected change to a regular package self init invalidatecaches initpath os path joincwd name init py cached self util cachefromsourceinitpath expected name name package name file initpath cached cached path os path dirnameinitpath doc none eggs none os renamebadpath initpath reloaded self init reloadmodule ns varsreloaded copy loader ns pop loader spec ns pop spec ns pop builtins none an implementation detail self assertequalspec name name self assertequalspec loader loader self assertisreloaded module self assertequalloader path initpath self assertequalns expected def testreloadsubmoduleself see 19851 name spam subname ham with testutil tempmodulename pkgtrue as pkgdir fullname testutil submodulename subname pkgdir ham self init importmodulefullname reloaded self init reloadham self assertisreloaded ham def testmodulemissingspecself test that reload throws modulenotfounderror when reloading a module whose missing a spec bpo29851 name spam with testutil uncachename module sys modulesname types moduletypename sanity check by attempting an import module self init importmodulename self assertisnonemodule spec with self assertraisesmodulenotfounderror self init reloadmodule frozenreloadtests sourcereloadtests testutil testboth reloadtests initinit utilutil machinerymachinery class invalidatecachetests def testmethodcalledself if defined the method should be called class invalidatingnullfinder def initself ignored self called false def invalidatecachesself self called true key os path abspath gobledeegook metains invalidatingnullfinder pathins invalidatingnullfinder sys metapath insert0 metains self addcleanuplambda sys pathimportercache delitemkey sys pathimportercachekey pathins self addcleanuplambda sys metapath removemetains self init invalidatecaches self asserttruemetains called self asserttruepathins called def testmethodlackingself there should be no issues if the method is not defined key gobbledeegook sys pathimportercachekey none self addcleanuplambda sys pathimportercache popkey none self init invalidatecaches shouldn t trigger an exception frozeninvalidatecachetests sourceinvalidatecachetests testutil testboth invalidatecachetests initinit utilutil machinerymachinery class frozenimportlibtestsunittest testcase def testnofrozenimportlibself should be able to import wo frozenimportlib being defined can t do an isinstance check since separate copies of importlib may have been used for import so just check the name is not for the frozen loader sourceinit init source self assertnotequalsourceinit loader class name frozenimporter class startuptests def testeveryonehasloaderself issue 17098 all modules should have loader defined for name module in sys modules items if isinstancemodule types moduletype with self subtestnamename self asserttruehasattrmodule loader r lacks a loader attribute formatname if self machinery builtinimporter findspecname self assertisnotmodule loader none elif self machinery frozenimporter findspecname self assertisnotmodule loader none def testeveryonehasspecself for name module in sys modules items if isinstancemodule types moduletype with self subtestnamename self asserttruehasattrmodule spec if self machinery builtinimporter findspecname self assertisnotmodule spec none elif self machinery frozenimporter findspecname self assertisnotmodule spec none frozenstartuptests sourcestartuptests testutil testbothstartuptests machinerymachinery if name main unittest main test importlib import_module test importing a top level module test importing a module from a package with an absolute name test importing a module from a package through a relative import test importing a module from a package with an absolute name with the package argument given relative imports cannot happen without the package argument being set issue 13591 modules should only be loaded once when initializing the parent package attempts to import the module currently being imported if a module with __spec__ loader is in sys modules then return it if sys modules name __spec__ loader is none raise valueerror should raise valueerror issue 17099 return the loader found on sys meta_path searching on a path should work none is returned upon failure to find a loader start as a plain module an implementation detail change to a package an implementation detail start as a namespace package an implementation detail a namespaceloader change to a regular package an implementation detail see 19851 test that reload throws modulenotfounderror when reloading a module whose missing a spec bpo 29851 sanity check by attempting an import if defined the method should be called there should be no issues if the method is not defined shouldn t trigger an exception should be able to import w o _frozen_importlib being defined can t do an isinstance check since separate copies of importlib may have been used for import so just check the name is not for the frozen loader issue 17098 all modules should have __loader__ defined
from test.test_importlib import util as test_util

init = test_util.import_importlib('importlib')
util = test_util.import_importlib('importlib.util')
machinery = test_util.import_importlib('importlib.machinery')

import os.path
import sys
from test.support import import_helper
from test.support import os_helper
import types
import unittest


class ImportModuleTests:

    

    def test_module_import(self):
        
        with test_util.mock_spec('top_level') as mock:
            with test_util.import_state(meta_path=[mock]):
                module = self.init.import_module('top_level')
                self.assertEqual(module.__name__, 'top_level')

    def test_absolute_package_import(self):
        
        pkg_name = 'pkg'
        pkg_long_name = '{0}.__init__'.format(pkg_name)
        name = '{0}.mod'.format(pkg_name)
        with test_util.mock_spec(pkg_long_name, name) as mock:
            with test_util.import_state(meta_path=[mock]):
                module = self.init.import_module(name)
                self.assertEqual(module.__name__, name)

    def test_shallow_relative_package_import(self):
        
        pkg_name = 'pkg'
        pkg_long_name = '{0}.__init__'.format(pkg_name)
        module_name = 'mod'
        absolute_name = '{0}.{1}'.format(pkg_name, module_name)
        relative_name = '.{0}'.format(module_name)
        with test_util.mock_spec(pkg_long_name, absolute_name) as mock:
            with test_util.import_state(meta_path=[mock]):
                self.init.import_module(pkg_name)
                module = self.init.import_module(relative_name, pkg_name)
                self.assertEqual(module.__name__, absolute_name)

    def test_deep_relative_package_import(self):
        modules = ['a.__init__', 'a.b.__init__', 'a.c']
        with test_util.mock_spec(*modules) as mock:
            with test_util.import_state(meta_path=[mock]):
                self.init.import_module('a')
                self.init.import_module('a.b')
                module = self.init.import_module('..c', 'a.b')
                self.assertEqual(module.__name__, 'a.c')

    def test_absolute_import_with_package(self):
        
        
        pkg_name = 'pkg'
        pkg_long_name = '{0}.__init__'.format(pkg_name)
        name = '{0}.mod'.format(pkg_name)
        with test_util.mock_spec(pkg_long_name, name) as mock:
            with test_util.import_state(meta_path=[mock]):
                self.init.import_module(pkg_name)
                module = self.init.import_module(name, pkg_name)
                self.assertEqual(module.__name__, name)

    def test_relative_import_wo_package(self):
        
        
        with self.assertRaises(TypeError):
            self.init.import_module('.support')


    def test_loaded_once(self):
        
        
        
        b_load_count = 0
        def load_a():
            self.init.import_module('a.b')
        def load_b():
            nonlocal b_load_count
            b_load_count += 1
        code = {'a': load_a, 'a.b': load_b}
        modules = ['a.__init__', 'a.b']
        with test_util.mock_spec(*modules, module_code=code) as mock:
            with test_util.import_state(meta_path=[mock]):
                self.init.import_module('a.b')
        self.assertEqual(b_load_count, 1)


(Frozen_ImportModuleTests,
 Source_ImportModuleTests
 ) = test_util.test_both(
     ImportModuleTests, init=init, util=util, machinery=machinery)


class FindLoaderTests:

    FakeMetaFinder = None

    def test_sys_modules(self):
        
        name = 'some_mod'
        with test_util.uncache(name):
            module = types.ModuleType(name)
            loader = 'a loader!'
            module.__spec__ = self.machinery.ModuleSpec(name, loader)
            sys.modules[name] = module
            spec = self.util.find_spec(name)
            self.assertIsNotNone(spec)
            self.assertEqual(spec.loader, loader)

    def test_sys_modules_loader_is_None(self):
        
        name = 'some_mod'
        with test_util.uncache(name):
            module = types.ModuleType(name)
            module.__loader__ = None
            sys.modules[name] = module
            with self.assertRaises(ValueError):
                self.util.find_spec(name)

    def test_sys_modules_loader_is_not_set(self):
        
        
        name = 'some_mod'
        with test_util.uncache(name):
            module = types.ModuleType(name)
            try:
                del module.__spec__.loader
            except AttributeError:
                pass
            sys.modules[name] = module
            with self.assertRaises(ValueError):
                self.util.find_spec(name)

    def test_success(self):
        
        name = 'some_mod'
        with test_util.uncache(name):
            with test_util.import_state(meta_path=[self.FakeMetaFinder]):
                spec = self.util.find_spec(name)
                self.assertEqual((name, (name, None)), (spec.name, spec.loader))

    def test_success_path(self):
        
        name = 'some_mod'
        path = 'path to some place'
        with test_util.uncache(name):
            with test_util.import_state(meta_path=[self.FakeMetaFinder]):
                spec = self.util.find_spec(name, path)
                self.assertEqual(name, spec.name)

    def test_nothing(self):
        
        self.assertIsNone(self.util.find_spec('nevergoingtofindthismodule'))


class FindLoaderPEP451Tests(FindLoaderTests):

    class FakeMetaFinder:
        @staticmethod
        def find_spec(name, path=None, target=None):
            return machinery['Source'].ModuleSpec(name, (name, path))


(Frozen_FindLoaderPEP451Tests,
 Source_FindLoaderPEP451Tests
 ) = test_util.test_both(
     FindLoaderPEP451Tests, init=init, util=util, machinery=machinery)


class ReloadTests:

    def test_reload_modules(self):
        for mod in ('tokenize', 'time', 'marshal'):
            with self.subTest(module=mod):
                with import_helper.CleanImport(mod):
                    module = self.init.import_module(mod)
                    self.init.reload(module)

    def test_module_replaced(self):
        def code():
            import sys
            module = type(sys)('top_level')
            module.spam = 3
            sys.modules['top_level'] = module
        mock = test_util.mock_spec('top_level',
                                   module_code={'top_level': code})
        with mock:
            with test_util.import_state(meta_path=[mock]):
                module = self.init.import_module('top_level')
                reloaded = self.init.reload(module)
                actual = sys.modules['top_level']
                self.assertEqual(actual.spam, 3)
                self.assertEqual(reloaded.spam, 3)

    def test_reload_missing_loader(self):
        with import_helper.CleanImport('types'):
            import types
            loader = types.__loader__
            del types.__loader__
            reloaded = self.init.reload(types)

            self.assertIs(reloaded, types)
            self.assertIs(sys.modules['types'], types)
            self.assertEqual(reloaded.__loader__.path, loader.path)

    def test_reload_loader_replaced(self):
        with import_helper.CleanImport('types'):
            import types
            types.__loader__ = None
            self.init.invalidate_caches()
            reloaded = self.init.reload(types)

            self.assertIsNot(reloaded.__loader__, None)
            self.assertIs(reloaded, types)
            self.assertIs(sys.modules['types'], types)

    def test_reload_location_changed(self):
        name = 'spam'
        with os_helper.temp_cwd(None) as cwd:
            with test_util.uncache('spam'):
                with import_helper.DirsOnSysPath(cwd):
                    
                    self.init.invalidate_caches()
                    path = os.path.join(cwd, name + '.py')
                    cached = self.util.cache_from_source(path)
                    expected = {'__name__': name,
                                '__package__': '',
                                '__file__': path,
                                '__cached__': cached,
                                '__doc__': None,
                                }
                    os_helper.create_empty_file(path)
                    module = self.init.import_module(name)
                    ns = vars(module).copy()
                    loader = ns.pop('__loader__')
                    spec = ns.pop('__spec__')
                    ns.pop('__builtins__', None)  
                    self.assertEqual(spec.name, name)
                    self.assertEqual(spec.loader, loader)
                    self.assertEqual(loader.path, path)
                    self.assertEqual(ns, expected)

                    
                    self.init.invalidate_caches()
                    init_path = os.path.join(cwd, name, '__init__.py')
                    cached = self.util.cache_from_source(init_path)
                    expected = {'__name__': name,
                                '__package__': name,
                                '__file__': init_path,
                                '__cached__': cached,
                                '__path__': [os.path.dirname(init_path)],
                                '__doc__': None,
                                }
                    os.mkdir(name)
                    os.rename(path, init_path)
                    reloaded = self.init.reload(module)
                    ns = vars(reloaded).copy()
                    loader = ns.pop('__loader__')
                    spec = ns.pop('__spec__')
                    ns.pop('__builtins__', None)  
                    self.assertEqual(spec.name, name)
                    self.assertEqual(spec.loader, loader)
                    self.assertIs(reloaded, module)
                    self.assertEqual(loader.path, init_path)
                    self.maxDiff = None
                    self.assertEqual(ns, expected)

    def test_reload_namespace_changed(self):
        name = 'spam'
        with os_helper.temp_cwd(None) as cwd:
            with test_util.uncache('spam'):
                with test_util.import_state(path=[cwd]):
                    self.init._bootstrap_external._install(self.init._bootstrap)
                    
                    self.init.invalidate_caches()
                    bad_path = os.path.join(cwd, name, '__init.py')
                    cached = self.util.cache_from_source(bad_path)
                    expected = {'__name__': name,
                                '__package__': name,
                                '__doc__': None,
                                '__file__': None,
                                }
                    os.mkdir(name)
                    with open(bad_path, 'w', encoding='utf-8') as init_file:
                        init_file.write('eggs = None')
                    module = self.init.import_module(name)
                    ns = vars(module).copy()
                    loader = ns.pop('__loader__')
                    path = ns.pop('__path__')
                    spec = ns.pop('__spec__')
                    ns.pop('__builtins__', None)  
                    self.assertEqual(spec.name, name)
                    self.assertIsNotNone(spec.loader)
                    self.assertIsNotNone(loader)
                    self.assertEqual(spec.loader, loader)
                    self.assertEqual(set(path),
                                     set([os.path.dirname(bad_path)]))
                    with self.assertRaises(AttributeError):
                        
                        loader.path
                    self.assertEqual(ns, expected)

                    
                    self.init.invalidate_caches()
                    init_path = os.path.join(cwd, name, '__init__.py')
                    cached = self.util.cache_from_source(init_path)
                    expected = {'__name__': name,
                                '__package__': name,
                                '__file__': init_path,
                                '__cached__': cached,
                                '__path__': [os.path.dirname(init_path)],
                                '__doc__': None,
                                'eggs': None,
                                }
                    os.rename(bad_path, init_path)
                    reloaded = self.init.reload(module)
                    ns = vars(reloaded).copy()
                    loader = ns.pop('__loader__')
                    spec = ns.pop('__spec__')
                    ns.pop('__builtins__', None)  
                    self.assertEqual(spec.name, name)
                    self.assertEqual(spec.loader, loader)
                    self.assertIs(reloaded, module)
                    self.assertEqual(loader.path, init_path)
                    self.assertEqual(ns, expected)

    def test_reload_submodule(self):
        
        name = 'spam'
        subname = 'ham'
        with test_util.temp_module(name, pkg=True) as pkg_dir:
            fullname, _ = test_util.submodule(name, subname, pkg_dir)
            ham = self.init.import_module(fullname)
            reloaded = self.init.reload(ham)
            self.assertIs(reloaded, ham)

    def test_module_missing_spec(self):
        
        
        name = 'spam'
        with test_util.uncache(name):
            module = sys.modules[name] = types.ModuleType(name)
            
            module = self.init.import_module(name)
            self.assertIsNone(module.__spec__)
            with self.assertRaises(ModuleNotFoundError):
                self.init.reload(module)


(Frozen_ReloadTests,
 Source_ReloadTests
 ) = test_util.test_both(
     ReloadTests, init=init, util=util, machinery=machinery)


class InvalidateCacheTests:

    def test_method_called(self):
        
        class InvalidatingNullFinder:
            def __init__(self, *ignored):
                self.called = False
            def invalidate_caches(self):
                self.called = True

        key = os.path.abspath('gobledeegook')
        meta_ins = InvalidatingNullFinder()
        path_ins = InvalidatingNullFinder()
        sys.meta_path.insert(0, meta_ins)
        self.addCleanup(lambda: sys.path_importer_cache.__delitem__(key))
        sys.path_importer_cache[key] = path_ins
        self.addCleanup(lambda: sys.meta_path.remove(meta_ins))
        self.init.invalidate_caches()
        self.assertTrue(meta_ins.called)
        self.assertTrue(path_ins.called)

    def test_method_lacking(self):
        
        key = 'gobbledeegook'
        sys.path_importer_cache[key] = None
        self.addCleanup(lambda: sys.path_importer_cache.pop(key, None))
        self.init.invalidate_caches()  


(Frozen_InvalidateCacheTests,
 Source_InvalidateCacheTests
 ) = test_util.test_both(
     InvalidateCacheTests, init=init, util=util, machinery=machinery)


class FrozenImportlibTests(unittest.TestCase):

    def test_no_frozen_importlib(self):
        
        
        
        
        source_init = init['Source']
        self.assertNotEqual(source_init.__loader__.__class__.__name__,
                            'FrozenImporter')


class StartupTests:

    def test_everyone_has___loader__(self):
        
        for name, module in sys.modules.items():
            if isinstance(module, types.ModuleType):
                with self.subTest(name=name):
                    self.assertTrue(hasattr(module, '__loader__'),
                                    '{!r} lacks a __loader__ attribute'.format(name))
                    if self.machinery.BuiltinImporter.find_spec(name):
                        self.assertIsNot(module.__loader__, None)
                    elif self.machinery.FrozenImporter.find_spec(name):
                        self.assertIsNot(module.__loader__, None)

    def test_everyone_has___spec__(self):
        for name, module in sys.modules.items():
            if isinstance(module, types.ModuleType):
                with self.subTest(name=name):
                    self.assertTrue(hasattr(module, '__spec__'))
                    if self.machinery.BuiltinImporter.find_spec(name):
                        self.assertIsNot(module.__spec__, None)
                    elif self.machinery.FrozenImporter.find_spec(name):
                        self.assertIsNot(module.__spec__, None)


(Frozen_StartupTests,
 Source_StartupTests
 ) = test_util.test_both(StartupTests, machinery=machinery)


if __name__ == '__main__':
    unittest.main()