test_finder.py revision d71bed3d76cc90dac24f88197bd37fdc2063330d
1f87e04d3398091662c399ee5ba0a3e71dbae9a24Brett Cannonfrom importlib import _bootstrap
2f254a75176928e1d1228a5d20d49fbe2fe9f290aBrett Cannonfrom .. import abc
34ee2cdaf65971391b35ce7aaad5ce77ddcbb176eBrett Cannonfrom . import util as source_util
428a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsawfrom test.support import make_legacy_pyc
523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannonimport os
628a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsawimport errno
723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannonimport py_compile
823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannonimport unittest
923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannonimport warnings
1023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
1123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
12f254a75176928e1d1228a5d20d49fbe2fe9f290aBrett Cannonclass FinderTests(abc.FinderTests):
1323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
1423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    """For a top-level module, it should just be found directly in the
1523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    directory being searched. This is true for a directory with source
1623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    [top-level source], bytecode [top-level bc], or both [top-level both].
1723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    There is also the possibility that it is a package [top-level package], in
1823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    which case there will be a directory with the module name and an
1923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    __init__.py file. If there is a directory without an __init__.py an
2023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    ImportWarning is returned [empty dir].
2123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
2223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    For sub-modules and sub-packages, the same happens as above but only use
2323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    the tail end of the name [sub module] [sub package] [sub empty].
2423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
2523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    When there is a conflict between a package and module having the same name
2623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    in the same directory, the package wins out [package over module]. This is
2723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    so that imports of modules within the package can occur rather than trigger
2823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    an import error.
2923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
3023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    When there is a package and module with the same name, always pick the
3123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    package over the module [package over module]. This is so that imports from
3223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    the package have the possibility of succeeding.
3323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
3423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    """
3523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
3623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def import_(self, root, module):
3761b14251d3a653548f70350acb250cf23b696372Brett Cannon        finder = _bootstrap._FileFinder(root,
3861b14251d3a653548f70350acb250cf23b696372Brett Cannon                                        _bootstrap._SourceFinderDetails(),
3961b14251d3a653548f70350acb250cf23b696372Brett Cannon                                        _bootstrap._SourcelessFinderDetails())
4023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        return finder.find_module(module)
4123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
4223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def run_test(self, test, create=None, *, compile_=None, unlink=None):
4323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        """Test the finding of 'test' with the creation of modules listed in
4423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        'create'.
4523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
4623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        Any names listed in 'compile_' are byte-compiled. Modules
4723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        listed in 'unlink' have their source files deleted.
4823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
4923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        """
5023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        if create is None:
5123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            create = {test}
524ee2cdaf65971391b35ce7aaad5ce77ddcbb176eBrett Cannon        with source_util.create_modules(*create) as mapping:
5323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            if compile_:
5423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                for name in compile_:
5523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                    py_compile.compile(mapping[name])
5623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            if unlink:
5723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                for name in unlink:
5823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                    os.unlink(mapping[name])
5928a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                    try:
6028a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                        make_legacy_pyc(mapping[name])
6128a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                    except OSError as error:
6228a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                        # Some tests do not set compile_=True so the source
6328a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                        # module will not get compiled and there will be no
6428a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                        # PEP 3147 pyc file to rename.
6528a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                        if error.errno != errno.ENOENT:
6628a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                            raise
6723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            loader = self.import_(mapping['.root'], test)
68c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson            self.assertTrue(hasattr(loader, 'load_module'))
6923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            return loader
7023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
7123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_module(self):
7223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        # [top-level source]
7323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        self.run_test('top_level')
7423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        # [top-level bc]
7528a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw        self.run_test('top_level', compile_={'top_level'},
7628a691b7fdde1b8abafa4c4a5025e6bfa44f48b9Barry Warsaw                      unlink={'top_level'})
7723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        # [top-level both]
7823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        self.run_test('top_level', compile_={'top_level'})
7923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
8023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    # [top-level package]
8123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_package(self):
8223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        # Source.
8323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        self.run_test('pkg', {'pkg.__init__'})
8423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        # Bytecode.
8523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'},
8623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                unlink={'pkg.__init__'})
8723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        # Both.
8823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'})
8923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
9023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    # [sub module]
9123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_module_in_package(self):
924ee2cdaf65971391b35ce7aaad5ce77ddcbb176eBrett Cannon        with source_util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
9323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            pkg_dir = os.path.dirname(mapping['pkg.__init__'])
9423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            loader = self.import_(pkg_dir, 'pkg.sub')
95c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson            self.assertTrue(hasattr(loader, 'load_module'))
9623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
9723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    # [sub package]
9823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_package_in_package(self):
994ee2cdaf65971391b35ce7aaad5ce77ddcbb176eBrett Cannon        context = source_util.create_modules('pkg.__init__', 'pkg.sub.__init__')
10023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        with context as mapping:
10123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            pkg_dir = os.path.dirname(mapping['pkg.__init__'])
10223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            loader = self.import_(pkg_dir, 'pkg.sub')
103c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson            self.assertTrue(hasattr(loader, 'load_module'))
10423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
10523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    # [sub empty]
10623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_empty_sub_directory(self):
1074ee2cdaf65971391b35ce7aaad5ce77ddcbb176eBrett Cannon        context = source_util.create_modules('pkg.__init__', 'pkg.sub.__init__')
10823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        with warnings.catch_warnings():
10923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            warnings.simplefilter("error", ImportWarning)
11023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            with context as mapping:
11123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                os.unlink(mapping['pkg.sub.__init__'])
11223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon                pkg_dir = os.path.dirname(mapping['pkg.__init__'])
1132153dc001f5565592b44808d7f0f25815010eb9dBrett Cannon                with self.assertRaises(ImportWarning):
1142153dc001f5565592b44808d7f0f25815010eb9dBrett Cannon                    self.import_(pkg_dir, 'pkg.sub')
11523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
11623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    # [package over modules]
11723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_package_over_module(self):
11823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        name = '_temp'
11923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        loader = self.run_test(name, {'{0}.__init__'.format(name), name})
12061b14251d3a653548f70350acb250cf23b696372Brett Cannon        self.assertTrue('__init__' in loader.get_filename(name))
12123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
12223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
12323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_failure(self):
1244ee2cdaf65971391b35ce7aaad5ce77ddcbb176eBrett Cannon        with source_util.create_modules('blah') as mapping:
12523cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            nothing = self.import_(mapping['.root'], 'sdfsadsadf')
126c9c0f201fed21efcf669dbbf5f923eaf0eeb1db9Benjamin Peterson            self.assertTrue(nothing is None)
12723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
12823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    # [empty dir]
12923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    def test_empty_dir(self):
13023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon        with warnings.catch_warnings():
13123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon            warnings.simplefilter("error", ImportWarning)
1322153dc001f5565592b44808d7f0f25815010eb9dBrett Cannon            with self.assertRaises(ImportWarning):
1332153dc001f5565592b44808d7f0f25815010eb9dBrett Cannon                self.run_test('pkg', {'pkg.__init__'}, unlink={'pkg.__init__'})
13423cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
135d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon    def test_empty_string_for_dir(self):
136d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon        # The empty string from sys.path means to search in the cwd.
137d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon        finder = _bootstrap._FileFinder('', _bootstrap._SourceFinderDetails())
138d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon        with open('mod.py', 'w') as file:
139d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon            file.write("# test file for importlib")
140d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon        try:
141d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon            loader = finder.find_module('mod')
142d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon            self.assertTrue(hasattr(loader, 'load_module'))
143d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon        finally:
144d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon            os.unlink('mod.py')
145d71bed3d76cc90dac24f88197bd37fdc2063330dBrett Cannon
14623cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
14723cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannondef test_main():
14823cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    from test.support import run_unittest
14923cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    run_unittest(FinderTests)
15023cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
15123cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon
15223cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannonif __name__ == '__main__':
15323cbd8a6564df0ac3df339f91196c45f3e626d32Brett Cannon    test_main()
154