2009-01-29 20:22:35 -04:00
|
|
|
from .. import abc
|
2009-01-31 23:08:31 -04:00
|
|
|
from . import util as source_util
|
2012-04-14 15:10:13 -03:00
|
|
|
|
2012-05-11 13:58:42 -03:00
|
|
|
from importlib import machinery
|
2010-04-16 21:19:56 -03:00
|
|
|
import errno
|
2012-04-22 20:58:33 -03:00
|
|
|
import imp
|
2012-04-14 15:10:13 -03:00
|
|
|
import os
|
2009-01-17 20:24:28 -04:00
|
|
|
import py_compile
|
2012-04-14 15:10:13 -03:00
|
|
|
from test.support import make_legacy_pyc
|
2009-01-17 20:24:28 -04:00
|
|
|
import unittest
|
|
|
|
import warnings
|
|
|
|
|
|
|
|
|
2009-01-29 20:22:35 -04:00
|
|
|
class FinderTests(abc.FinderTests):
|
2009-01-17 20:24:28 -04:00
|
|
|
|
|
|
|
"""For a top-level module, it should just be found directly in the
|
|
|
|
directory being searched. This is true for a directory with source
|
|
|
|
[top-level source], bytecode [top-level bc], or both [top-level both].
|
|
|
|
There is also the possibility that it is a package [top-level package], in
|
|
|
|
which case there will be a directory with the module name and an
|
|
|
|
__init__.py file. If there is a directory without an __init__.py an
|
|
|
|
ImportWarning is returned [empty dir].
|
|
|
|
|
|
|
|
For sub-modules and sub-packages, the same happens as above but only use
|
|
|
|
the tail end of the name [sub module] [sub package] [sub empty].
|
|
|
|
|
|
|
|
When there is a conflict between a package and module having the same name
|
|
|
|
in the same directory, the package wins out [package over module]. This is
|
|
|
|
so that imports of modules within the package can occur rather than trigger
|
|
|
|
an import error.
|
|
|
|
|
|
|
|
When there is a package and module with the same name, always pick the
|
|
|
|
package over the module [package over module]. This is so that imports from
|
|
|
|
the package have the possibility of succeeding.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
2012-08-20 00:18:15 -03:00
|
|
|
def get_finder(self, root):
|
2012-05-11 13:58:42 -03:00
|
|
|
loader_details = [(machinery.SourceFileLoader,
|
2012-08-10 14:47:54 -03:00
|
|
|
machinery.SOURCE_SUFFIXES),
|
2012-05-11 13:58:42 -03:00
|
|
|
(machinery.SourcelessFileLoader,
|
2012-08-10 14:47:54 -03:00
|
|
|
machinery.BYTECODE_SUFFIXES)]
|
2012-08-20 00:18:15 -03:00
|
|
|
return machinery.FileFinder(root, *loader_details)
|
|
|
|
|
|
|
|
def import_(self, root, module):
|
|
|
|
return self.get_finder(root).find_module(module)
|
2009-01-17 20:24:28 -04:00
|
|
|
|
|
|
|
def run_test(self, test, create=None, *, compile_=None, unlink=None):
|
|
|
|
"""Test the finding of 'test' with the creation of modules listed in
|
|
|
|
'create'.
|
|
|
|
|
|
|
|
Any names listed in 'compile_' are byte-compiled. Modules
|
|
|
|
listed in 'unlink' have their source files deleted.
|
|
|
|
|
|
|
|
"""
|
|
|
|
if create is None:
|
|
|
|
create = {test}
|
2009-01-31 23:08:31 -04:00
|
|
|
with source_util.create_modules(*create) as mapping:
|
2009-01-17 20:24:28 -04:00
|
|
|
if compile_:
|
|
|
|
for name in compile_:
|
|
|
|
py_compile.compile(mapping[name])
|
|
|
|
if unlink:
|
|
|
|
for name in unlink:
|
|
|
|
os.unlink(mapping[name])
|
2010-04-16 21:19:56 -03:00
|
|
|
try:
|
|
|
|
make_legacy_pyc(mapping[name])
|
|
|
|
except OSError as error:
|
|
|
|
# Some tests do not set compile_=True so the source
|
|
|
|
# module will not get compiled and there will be no
|
|
|
|
# PEP 3147 pyc file to rename.
|
|
|
|
if error.errno != errno.ENOENT:
|
|
|
|
raise
|
2009-01-17 20:24:28 -04:00
|
|
|
loader = self.import_(mapping['.root'], test)
|
2009-06-30 20:06:06 -03:00
|
|
|
self.assertTrue(hasattr(loader, 'load_module'))
|
2009-01-17 20:24:28 -04:00
|
|
|
return loader
|
|
|
|
|
|
|
|
def test_module(self):
|
|
|
|
# [top-level source]
|
|
|
|
self.run_test('top_level')
|
|
|
|
# [top-level bc]
|
2010-04-16 21:19:56 -03:00
|
|
|
self.run_test('top_level', compile_={'top_level'},
|
|
|
|
unlink={'top_level'})
|
2009-01-17 20:24:28 -04:00
|
|
|
# [top-level both]
|
|
|
|
self.run_test('top_level', compile_={'top_level'})
|
|
|
|
|
|
|
|
# [top-level package]
|
|
|
|
def test_package(self):
|
|
|
|
# Source.
|
|
|
|
self.run_test('pkg', {'pkg.__init__'})
|
|
|
|
# Bytecode.
|
|
|
|
self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'},
|
|
|
|
unlink={'pkg.__init__'})
|
|
|
|
# Both.
|
|
|
|
self.run_test('pkg', {'pkg.__init__'}, compile_={'pkg.__init__'})
|
|
|
|
|
|
|
|
# [sub module]
|
|
|
|
def test_module_in_package(self):
|
2009-01-31 23:08:31 -04:00
|
|
|
with source_util.create_modules('pkg.__init__', 'pkg.sub') as mapping:
|
2009-01-17 20:24:28 -04:00
|
|
|
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
|
|
|
|
loader = self.import_(pkg_dir, 'pkg.sub')
|
2009-06-30 20:06:06 -03:00
|
|
|
self.assertTrue(hasattr(loader, 'load_module'))
|
2009-01-17 20:24:28 -04:00
|
|
|
|
|
|
|
# [sub package]
|
|
|
|
def test_package_in_package(self):
|
2009-01-31 23:08:31 -04:00
|
|
|
context = source_util.create_modules('pkg.__init__', 'pkg.sub.__init__')
|
2009-01-17 20:24:28 -04:00
|
|
|
with context as mapping:
|
|
|
|
pkg_dir = os.path.dirname(mapping['pkg.__init__'])
|
|
|
|
loader = self.import_(pkg_dir, 'pkg.sub')
|
2009-06-30 20:06:06 -03:00
|
|
|
self.assertTrue(hasattr(loader, 'load_module'))
|
2009-01-17 20:24:28 -04:00
|
|
|
|
|
|
|
# [package over modules]
|
|
|
|
def test_package_over_module(self):
|
|
|
|
name = '_temp'
|
|
|
|
loader = self.run_test(name, {'{0}.__init__'.format(name), name})
|
2012-06-24 20:13:55 -03:00
|
|
|
self.assertIn('__init__', loader.get_filename(name))
|
2009-01-17 20:24:28 -04:00
|
|
|
|
|
|
|
def test_failure(self):
|
2009-01-31 23:08:31 -04:00
|
|
|
with source_util.create_modules('blah') as mapping:
|
2009-01-17 20:24:28 -04:00
|
|
|
nothing = self.import_(mapping['.root'], 'sdfsadsadf')
|
2012-06-28 07:15:01 -03:00
|
|
|
self.assertIsNone(nothing)
|
2009-01-17 20:24:28 -04:00
|
|
|
|
2010-07-03 19:18:47 -03:00
|
|
|
def test_empty_string_for_dir(self):
|
|
|
|
# The empty string from sys.path means to search in the cwd.
|
2012-05-11 13:58:42 -03:00
|
|
|
finder = machinery.FileFinder('', (machinery.SourceFileLoader,
|
2012-08-10 14:47:54 -03:00
|
|
|
machinery.SOURCE_SUFFIXES))
|
2010-07-03 19:18:47 -03:00
|
|
|
with open('mod.py', 'w') as file:
|
|
|
|
file.write("# test file for importlib")
|
|
|
|
try:
|
|
|
|
loader = finder.find_module('mod')
|
|
|
|
self.assertTrue(hasattr(loader, 'load_module'))
|
|
|
|
finally:
|
|
|
|
os.unlink('mod.py')
|
|
|
|
|
2012-02-27 19:15:42 -04:00
|
|
|
def test_invalidate_caches(self):
|
|
|
|
# invalidate_caches() should reset the mtime.
|
2012-05-11 13:58:42 -03:00
|
|
|
finder = machinery.FileFinder('', (machinery.SourceFileLoader,
|
2012-08-10 14:47:54 -03:00
|
|
|
machinery.SOURCE_SUFFIXES))
|
2012-02-27 19:15:42 -04:00
|
|
|
finder._path_mtime = 42
|
|
|
|
finder.invalidate_caches()
|
|
|
|
self.assertEqual(finder._path_mtime, -1)
|
|
|
|
|
2012-08-20 00:18:15 -03:00
|
|
|
# Regression test for http://bugs.python.org/issue14846
|
|
|
|
def test_dir_removal_handling(self):
|
|
|
|
mod = 'mod'
|
|
|
|
with source_util.create_modules(mod) as mapping:
|
|
|
|
finder = self.get_finder(mapping['.root'])
|
|
|
|
self.assertIsNotNone(finder.find_module(mod))
|
|
|
|
self.assertIsNone(finder.find_module(mod))
|
2009-01-17 20:24:28 -04:00
|
|
|
|
|
|
|
def test_main():
|
|
|
|
from test.support import run_unittest
|
|
|
|
run_unittest(FinderTests)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
test_main()
|