160 lines
6.1 KiB
Python
160 lines
6.1 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
test_polyloader
|
|
----------------------------------
|
|
|
|
Tests for `polyloader` module.
|
|
"""
|
|
|
|
import polyloader
|
|
import copy
|
|
import sys
|
|
import pytest
|
|
|
|
# Note that these compilers don't actually load much out of the
|
|
# source files. That's not the point. The point is to show that the
|
|
# correct compiler has been found for a given extension.
|
|
|
|
|
|
class ImportEnvironment(object):
|
|
def __init__(self):
|
|
pass
|
|
|
|
def __enter__(self):
|
|
polyloader.reset()
|
|
self.path = copy.copy(sys.path)
|
|
self.path_hooks = copy.copy(sys.path_hooks)
|
|
self.meta_path = copy.copy(sys.meta_path)
|
|
self.modules = copy.copy(sys.modules)
|
|
self.path_importer_cache = copy.copy(sys.path_importer_cache)
|
|
self.dont_write_bytecode = sys.dont_write_bytecode
|
|
sys.dont_write_bytecode = True
|
|
return sys
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
sys.path = self.path
|
|
sys.path_hooks = self.path_hooks
|
|
sys.meta_path = self.meta_path
|
|
sys.modules = self.modules
|
|
sys.path_importer_cache = self.path_importer_cache
|
|
sys.dont_write_bytecode = self.dont_write_bytecode
|
|
|
|
|
|
class Compiler:
|
|
def __init__(self, pt):
|
|
self.pt = pt
|
|
|
|
def __call__(self, source_text, filename, *extra):
|
|
return compile("result='Success for %s: %s'" %
|
|
(self.pt, source_text.decode('utf-8').rstrip()), filename, "exec")
|
|
|
|
def __repr__(self):
|
|
return "Compiler %s" % (self.pt)
|
|
|
|
def compiler(pt):
|
|
return Compiler(pt)
|
|
|
|
# Functionally, the "From" test and the "Direct" test should be
|
|
# indistinguishable. What's interesting about them, though, is that
|
|
# in the context of the caller, the "Direct" test now has test and
|
|
# test.polytestmix as objects in the calling context. They're fairly
|
|
# lightweight, but they do exist, and they do honor the __all__ and
|
|
# __path__ cases.
|
|
#
|
|
# Also:
|
|
# See http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html
|
|
# for some 'gotchas' to look forward to. Whee.
|
|
|
|
class Test_Polymorph_From(object):
|
|
def test_import1(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("2"), ['2'])
|
|
polyloader.install(compiler("3"), ['3'])
|
|
from .polytestmix import test2
|
|
from .polytestmix import test3
|
|
from .polytestmix import test1
|
|
assert(test1.result == "Success for 1: Test One")
|
|
assert(test2.result == "Success for 2: Test Two")
|
|
assert(test3.result == "Success for 3: Test Three")
|
|
|
|
class Test_Polymorph_Direct(object):
|
|
def test_import2(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("2"), ['2'])
|
|
polyloader.install(compiler("3"), ['3'])
|
|
import tests_py3.polytestmix.test2
|
|
import tests_py3.polytestmix.test3
|
|
import tests_py3.polytestmix.test1
|
|
assert(tests_py3.polytestmix.test1.result == "Success for 1: Test One")
|
|
assert(tests_py3.polytestmix.test2.result == "Success for 2: Test Two")
|
|
assert(tests_py3.polytestmix.test3.result == "Success for 3: Test Three")
|
|
|
|
class Test_Polymorph_Module(object):
|
|
def test_import3(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("3"), ['3'])
|
|
polyloader.install(compiler("2"), ['2'])
|
|
from tests_py3.polytestmix.test3 import result as result3
|
|
from tests_py3.polytestmix.test2 import result as result2
|
|
from tests_py3.polytestmix.test1 import result as result1
|
|
assert(result1 == "Success for 1: Test One")
|
|
assert(result2 == "Success for 2: Test Two")
|
|
assert(result3 == "Success for 3: Test Three")
|
|
|
|
class Test_Polymorph_Reset(object):
|
|
def test_reset_after_import(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("2"), ['2'])
|
|
polyloader.install(compiler("3"), ['3'])
|
|
from tests_py2.polytestmix.test3 import result as result3
|
|
polyloader.reset()
|
|
with pytest.raises(ImportError):
|
|
from tests_py2.polytestmix.test2 import result as result2
|
|
def test_reset_before_import(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("3"), ['3'])
|
|
polyloader.reset()
|
|
with pytest.raises(ImportError):
|
|
from tests_py2.polytestmix.test3 import result as result3
|
|
|
|
class Test_Polymorph_Uninstall(object):
|
|
def test_uninstall_after_import(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("3"), ['3'])
|
|
polyloader.install(compiler("2"), ['2'])
|
|
import tests_py2.polytestmix.test3
|
|
polyloader.uninstall('2')
|
|
with pytest.raises(ImportError):
|
|
import tests_py2.polytestmix.test2
|
|
import tests_py2.polytestmix.test1
|
|
def test_uninstall_before_import(self):
|
|
with ImportEnvironment() as sys:
|
|
polyloader.install(compiler("3"), ['3'])
|
|
polyloader.install(compiler("2"), ['2'])
|
|
polyloader.uninstall('3')
|
|
polyloader.uninstall('2')
|
|
with pytest.raises(ImportError):
|
|
import tests_py2.polytestmix.test3
|
|
with pytest.raises(ImportError):
|
|
import tests_py2.polytestmix.test2
|
|
import tests_py2.polytestmix.test1
|
|
|
|
class Test_Polymorph_Iterator(object):
|
|
''' The Django Compatibility test: Can we load arbitrary modules from a package? '''
|
|
def test_iterator(self):
|
|
with ImportEnvironment() as sys:
|
|
import os
|
|
import inspect
|
|
polyloader.install(compiler("2"), ['2'])
|
|
polyloader.install(compiler("3"), ['3'])
|
|
import pkgutil
|
|
target_dir = os.path.join(
|
|
os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))),
|
|
'polytestmix')
|
|
modules = set([name for (_, name, is_pkg) in pkgutil.iter_modules([target_dir])
|
|
if not is_pkg and not name.startswith('_')])
|
|
assert(modules == set(['test1', 'test2', 'test3']))
|
|
|