File: test_classpathimporter.py

package info (click to toggle)
jython 2.7.2%2Brepack1-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 62,676 kB
  • sloc: python: 640,908; java: 306,458; xml: 1,984; sh: 522; ansic: 126; makefile: 76
file content (206 lines) | stat: -rw-r--r-- 8,583 bytes parent folder | download | duplicates (2)
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()