1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
import os
import py_compile
import shutil
import sys
import tempfile
import unittest
import zipfile
from test import test_support
from java.lang import Thread
import pkgutil
class ClasspathImporterTestCase(unittest.TestCase):
def setUp(self):
self.orig_context = Thread.currentThread().contextClassLoader
def tearDown(self):
Thread.currentThread().contextClassLoader = self.orig_context
# I don't like the checked in jar file bug1239.jar. The *one* thing I
# liked about the tests in bugtests/ is that you could create a java file,
# compile it, jar it and destroy the jar when done. Maybe when we move to
# JDK 6 and can use JSR-199 to do runtime compiling, we can go back to
# that. Anyway, see http://bugs.jython.org/issue1239. In short, jars added
# with sys.path.append where not getting scanned if they start with a top
# level package we already have, like the "org" in org.python.*
def test_bug1239(self):
jar = test_support.findfile("bug1239.jar")
with test_support.DirsOnSysPath(jar):
import org.test403javapackage.test403
# different from test_bug1239 in that only a Java package is imported, not
# a Java class. I'd also like to get rid of this checked in test jar.
def test_bug1126(self):
jar = test_support.findfile("bug1126.jar", subdir="bug1126")
with test_support.DirsOnSysPath(jar):
import org.subpackage
class PyclasspathImporterTestCase(unittest.TestCase):
RESOURCE_DATA = "Always look\non the bright side\r\nof life."
def setUp(self):
self.orig_context = Thread.currentThread().contextClassLoader
self.temp_dir = tempfile.mkdtemp()
self.modules = sys.modules.keys()
def tearDown(self):
Thread.currentThread().contextClassLoader = self.orig_context
for module in sys.modules.keys():
if module not in self.modules:
del sys.modules[module]
try:
shutil.rmtree(self.temp_dir)
except OSError:
# On Windows at least we cannot delete the open JAR
pass
def prepareJar(self, orig_jar):
# Create a new copy of the checked-in test jar
orig_jar = test_support.findfile(orig_jar)
jar = os.path.join(self.temp_dir, os.path.basename(orig_jar))
shutil.copy(orig_jar, jar)
return jar
def compileToJar(self, jar, compile_path=''):
# Add a compiled version of prefer_compiled.py to the jar
source = 'prefer_compiled.py'
code = os.path.join(self.temp_dir, source)
with open(code, 'w') as fp:
fp.write('compiled = True')
# Compile that file
py_compile.compile(code)
# Now add the compiled file to the jar
compiled = source.replace('.py', '$py.class')
with zipfile.ZipFile(jar, 'a') as zip:
zip.write(os.path.join(self.temp_dir, compiled),
os.path.join(compile_path, 'jar_pkg', compiled))
return compiled
def addResourceToJar(self, jar, package='jar_pkg'):
name = 'testdata.dat'
with zipfile.ZipFile(jar, 'a') as zip:
zip.writestr(package + '/' + name, self.RESOURCE_DATA)
return name
def checkImports(self, prefix, compiled):
import flat_in_jar
self.assertEquals(flat_in_jar.value, 7)
import jar_pkg
self.assertEquals(prefix + '/jar_pkg/__init__.py', jar_pkg.__file__)
from jar_pkg import prefer_compiled
self.assertEquals(prefix + '/jar_pkg/' + compiled, prefer_compiled.__file__)
self.assert_(prefer_compiled.compiled)
self.assertRaises(NameError, __import__, 'flat_bad')
self.assertRaises(NameError, __import__, 'jar_pkg.bad')
def test_default_pyclasspath(self):
jar = self.prepareJar('classimport.jar')
compiled = self.compileToJar(jar)
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
self.checkImports('__pyclasspath__', compiled)
def test_path_in_pyclasspath(self):
jar = self.prepareJar('classimport_Lib.jar')
compiled = self.compileToJar(jar, 'Lib')
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
with test_support.DirsOnSysPath():
sys.path = ['__pyclasspath__/Lib']
self.checkImports('__pyclasspath__/Lib', compiled)
def test_loader_is_package(self):
jar = self.prepareJar('classimport.jar')
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
mod_name = 'flat_in_jar'
loader = pkgutil.get_loader(mod_name)
self.assertFalse(loader.is_package(mod_name))
self.assertTrue(loader.is_package('jar_pkg'))
self.assertFalse(loader.is_package('jar_pkg.prefer_compiled'))
@unittest.skipIf(test_support.is_jython_posix, "FIXME: failing on Linux issue #2422")
@unittest.skipIf(test_support.get_java_version() >= (9,),
"Fails on Java 9+. See b.j.o. issue #2362") # FIXME
# Probably related to Java modules: ensure also works outside java.base
def test_loader_get_code(self):
# Execute Python code out of the JAR
jar = self.prepareJar('classimport.jar')
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
loader = pkgutil.get_loader('jar_pkg')
space = { 'value':None, 'compiled':None}
# flat_in_jar contains the assignment value = 7
code = loader.get_code('flat_in_jar')
exec code in space
self.assertEquals(space['value'], 7)
# jar_pkg.prefer_compiled contains the assignment compiled = False
code = loader.get_code('jar_pkg.prefer_compiled')
exec code in space
self.assertEquals(space['compiled'], False)
# Compile a new one containing the assignment compiled = True
self.compileToJar(jar)
code = loader.get_code('jar_pkg.prefer_compiled')
exec code in space
self.assertEquals(space['compiled'], True)
def test_pkgutil_get_data(self):
# Test loader.get_data used via pkgutil
jar = self.prepareJar('classimport.jar')
name = self.addResourceToJar(jar)
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
data = pkgutil.get_data('jar_pkg', name)
self.assertIsInstance(data, bytes)
self.assertEqual(data, self.RESOURCE_DATA)
def test_loader_get_data(self):
# Test loader.get_data used via pkgutil.get_loader
jar = self.prepareJar('classimport.jar')
name = self.addResourceToJar(jar)
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
loader = pkgutil.get_loader('jar_pkg')
# path is a resource path (not file system path using os.path.sep)
path = 'jar_pkg/' + name
data = loader.get_data(path)
self.assertIsInstance(data, bytes)
self.assertEqual(data, self.RESOURCE_DATA)
def test_importer_get_data(self):
# Test loader.get_data used via pkgutil.get_importer
jar = self.prepareJar('classimport.jar')
name = self.addResourceToJar(jar)
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
importer = pkgutil.get_importer('__pyclasspath__/')
# path is a resource path (may be file system path using os.path.sep)
path = os.path.join('jar_pkg', name)
data = importer.get_data(path)
self.assertIsInstance(data, bytes)
self.assertEqual(data, self.RESOURCE_DATA)
# Check works a second time (stream use internal to implementation)
data = importer.get_data(path)
self.assertEqual(data, self.RESOURCE_DATA)
def test_importer_get_source(self):
# Test loader.get_source used via pkgutil.get_importer
jar = self.prepareJar('classimport.jar')
Thread.currentThread().contextClassLoader = test_support.make_jar_classloader(jar)
importer = pkgutil.get_importer('__pyclasspath__/')
# In package
mod = 'jar_pkg.prefer_compiled'
source = importer.get_source(mod)
self.assertIsInstance(source, bytes)
self.assertEqual(source, 'compiled = False\n')
def test_main():
test_support.run_unittest(
ClasspathImporterTestCase,
PyclasspathImporterTestCase
)
if __name__ == '__main__':
test_main()
|