Skip to content

Commit cd6d3ac

Browse files
committed
add tests for some of the new C API
1 parent 12680de commit cd6d3ac

File tree

9 files changed

+316
-29
lines changed

9 files changed

+316
-29
lines changed

graalpython/com.oracle.graal.python.cext/src/import.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ PyObject* PyImport_ImportModule(const char *name) {
4343
}
4444

4545
PyObject* PyImport_Import(PyObject *name) {
46-
return UPCALL_CEXT_O("PyImport_Import", native_to_java(name));
46+
return UPCALL_CEXT_O("PyImport_ImportModule", native_to_java(name));
4747
}
4848

4949
PyObject* PyImport_ImportModuleLevelObject(PyObject* name, PyObject* globals, PyObject* locals,

graalpython/com.oracle.graal.python.test/src/tests/cpyext/__init__.py

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,7 @@ def setUp(self):
7070
def ccompile(self, name):
7171
from distutils.core import setup, Extension
7272
source_file = '%s/%s.c' % (__dir__, name)
73-
74-
try:
75-
stat_result = os.stat(source_file)
76-
if stat_result[6] == 0:
77-
raise SystemError("empty source file %s" % (source_file,))
78-
except FileNotFoundError:
79-
raise SystemError("source file %s not available" % (source_file,))
80-
73+
file_not_empty(source_file)
8174
module = Extension(name, sources=[source_file])
8275
args = ['--quiet', 'build', 'install_lib', '-f', '--install-dir=%s' % __dir__]
8376
setup(
@@ -90,24 +83,19 @@ def ccompile(self, name):
9083
)
9184
# ensure file was really written
9285
binary_file_llvm = '%s/%s.bc' % (__dir__, name)
93-
binary_file_gcc = '%s/%s.so' % (__dir__, name)
94-
95-
tries = 0
96-
while tries < 3 and not file_not_empty(binary_file_llvm) and not file_not_empty(binary_file_gcc):
97-
tries += 1
98-
99-
if tries >= 3:
100-
raise SystemError("binary file %s/%s.(bc|so) not available" % (__dir__, name))
86+
if GRAALPYTHON:
87+
file_not_empty(binary_file_llvm)
10188

10289

10390
def file_not_empty(path):
104-
try:
105-
stat_result = os.stat(path)
106-
if stat_result[6] == 0:
107-
return False
108-
except FileNotFoundError:
109-
return False
110-
return True
91+
for i in range(3):
92+
try:
93+
stat_result = os.stat(path)
94+
if stat_result[6] != 0:
95+
return
96+
except FileNotFoundError:
97+
pass
98+
raise SystemError("file %s not available" % path)
11199

112100

113101
c_template = """
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates.
2+
#
3+
# The Universal Permissive License (UPL), Version 1.0
4+
#
5+
# Subject to the condition set forth below, permission is hereby granted to any
6+
# person obtaining a copy of this software, associated documentation and/or data
7+
# (collectively the "Software"), free of charge and under any and all copyright
8+
# rights in the Software, and any and all patent rights owned or freely
9+
# licensable by each licensor hereunder covering either (i) the unmodified
10+
# Software as contributed to or provided by such licensor, or (ii) the Larger
11+
# Works (as defined below), to deal in both
12+
#
13+
# (a) the Software, and
14+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
# one is included with the Software (each a "Larger Work" to which the
16+
# Software is contributed by such licensors),
17+
#
18+
# without restriction, including without limitation the rights to copy, create
19+
# derivative works of, display, perform, and distribute the Software and make,
20+
# use, sell, offer for sale, import, export, have made, and have sold the
21+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
# either these or other terms.
23+
#
24+
# This license is subject to the following condition:
25+
#
26+
# The above copyright notice and either this complete permission notice or at a
27+
# minimum a reference to the UPL must be included in all copies or substantial
28+
# portions of the Software.
29+
#
30+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
# SOFTWARE.
37+
38+
import sys
39+
from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON
40+
__dir__ = __file__.rpartition("/")[0]
41+
42+
43+
class DummyClass():
44+
def foo(self):
45+
return 0
46+
47+
48+
DummyInstance = DummyClass()
49+
50+
51+
class TestClassobject(CPyExtTestCase):
52+
def compile_module(self, name):
53+
type(self).mro()[1].__dict__["test_%s" % name].create_module(name)
54+
super().compile_module(name)
55+
56+
testmod = type(sys)("foo")
57+
58+
test_PyMethod_Function = CPyExtFunction(
59+
lambda args: args[0].__func__,
60+
lambda: (
61+
(
62+
DummyClass().foo,
63+
),
64+
),
65+
resultspec="O",
66+
argspec="O",
67+
arguments=["PyObject* func"],
68+
)
69+
70+
test_PyMethod_Self = CPyExtFunction(
71+
lambda args: args[0].__self__,
72+
lambda: (
73+
(
74+
DummyInstance.foo,
75+
),
76+
),
77+
resultspec="O",
78+
argspec="O",
79+
arguments=["PyObject* func"],
80+
)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates.
2+
#
3+
# The Universal Permissive License (UPL), Version 1.0
4+
#
5+
# Subject to the condition set forth below, permission is hereby granted to any
6+
# person obtaining a copy of this software, associated documentation and/or data
7+
# (collectively the "Software"), free of charge and under any and all copyright
8+
# rights in the Software, and any and all patent rights owned or freely
9+
# licensable by each licensor hereunder covering either (i) the unmodified
10+
# Software as contributed to or provided by such licensor, or (ii) the Larger
11+
# Works (as defined below), to deal in both
12+
#
13+
# (a) the Software, and
14+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
# one is included with the Software (each a "Larger Work" to which the
16+
# Software is contributed by such licensors),
17+
#
18+
# without restriction, including without limitation the rights to copy, create
19+
# derivative works of, display, perform, and distribute the Software and make,
20+
# use, sell, offer for sale, import, export, have made, and have sold the
21+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
# either these or other terms.
23+
#
24+
# This license is subject to the following condition:
25+
#
26+
# The above copyright notice and either this complete permission notice or at a
27+
# minimum a reference to the UPL must be included in all copies or substantial
28+
# portions of the Software.
29+
#
30+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
# SOFTWARE.
37+
38+
import sys
39+
import types
40+
from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON
41+
__dir__ = __file__.rpartition("/")[0]
42+
43+
44+
class DummyClass():
45+
def foo(self):
46+
return 0
47+
48+
49+
DummyInstance = DummyClass()
50+
DictInstance = {}
51+
52+
53+
class TestCodeobject(CPyExtTestCase):
54+
def compile_module(self, name):
55+
type(self).mro()[1].__dict__["test_%s" % name].create_module(name)
56+
super().compile_module(name)
57+
58+
testmod = type(sys)("foo")
59+
60+
test_PyCode_New = CPyExtFunction(
61+
lambda args: args,
62+
lambda: (
63+
(
64+
1,2,3,4,0,b"",tuple(),tuple(),tuple(),
65+
tuple(),tuple(),"filename","name",1,b"",
66+
),
67+
),
68+
resultspec="O",
69+
argspec="iiiiiOOOOOOOOiO",
70+
arguments=[
71+
"int argcount", "int kwonlyargcount", "int nlocals",
72+
"int stacksize", "int flags", "PyObject* code",
73+
"PyObject* consts", "PyObject* names", "PyObject* varnames",
74+
"PyObject* freevars", "PyObject* cellvars",
75+
"PyObject* filename", "PyObject* name", "int firstlineno",
76+
"PyObject* lnotab"
77+
],
78+
cmpfunc=lambda cr,pr: isinstance(cr, types.CodeType),
79+
)

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_dict.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ class SubDict(dict):
102102
pass
103103

104104

105+
ExampleDict = {}
106+
def fresh_dict():
107+
global ExampleDict
108+
ExampleDict = {}
109+
return ExampleDict
110+
111+
105112
class TestPyDict(CPyExtTestCase):
106113

107114
def compile_module(self, name):
@@ -289,3 +296,23 @@ def compile_module(self, name):
289296
argspec='O',
290297
arguments=["PyObject* o"],
291298
)
299+
300+
test_PyDict_Update = CPyExtFunction(
301+
lambda args: 1 if args[0].update(args[1]) else 0,
302+
lambda: (
303+
(fresh_dict(), {"a": 1}),
304+
),
305+
resultspec="O",
306+
argspec="OO",
307+
arguments=["PyObject* self", "PyObject* other"],
308+
code='''PyObject* wrap_PyDict_Update(PyObject* self, PyObject* other) {
309+
int result = PyDict_Update(self, other);
310+
if (result == -1) {
311+
return NULL;
312+
} else {
313+
return PyLong_FromLong(result);
314+
}
315+
}''',
316+
callfunction="wrap_PyDict_Update",
317+
cmpfunc=lambda cr,pr: (cr == pr or (isinstance(cr, BaseException) and type(cr) == type(pr))) and (ExampleDict.get("a") == 1 or len(ExampleDict) == 0)
318+
)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates.
2+
#
3+
# The Universal Permissive License (UPL), Version 1.0
4+
#
5+
# Subject to the condition set forth below, permission is hereby granted to any
6+
# person obtaining a copy of this software, associated documentation and/or data
7+
# (collectively the "Software"), free of charge and under any and all copyright
8+
# rights in the Software, and any and all patent rights owned or freely
9+
# licensable by each licensor hereunder covering either (i) the unmodified
10+
# Software as contributed to or provided by such licensor, or (ii) the Larger
11+
# Works (as defined below), to deal in both
12+
#
13+
# (a) the Software, and
14+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
15+
# one is included with the Software (each a "Larger Work" to which the
16+
# Software is contributed by such licensors),
17+
#
18+
# without restriction, including without limitation the rights to copy, create
19+
# derivative works of, display, perform, and distribute the Software and make,
20+
# use, sell, offer for sale, import, export, have made, and have sold the
21+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
22+
# either these or other terms.
23+
#
24+
# This license is subject to the following condition:
25+
#
26+
# The above copyright notice and either this complete permission notice or at a
27+
# minimum a reference to the UPL must be included in all copies or substantial
28+
# portions of the Software.
29+
#
30+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
# SOFTWARE.
37+
38+
import sys
39+
from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON
40+
__dir__ = __file__.rpartition("/")[0]
41+
42+
43+
try:
44+
raise TypeError
45+
except:
46+
TB = sys.exc_info()[2]
47+
48+
49+
class TestExceptionobject(CPyExtTestCase):
50+
def compile_module(self, name):
51+
type(self).mro()[1].__dict__["test_%s" % name].create_module(name)
52+
super().compile_module(name)
53+
54+
test_PyException_SetTraceback = CPyExtFunction(
55+
lambda args: 0,
56+
lambda: (
57+
(
58+
AssertionError(), TB
59+
),
60+
),
61+
resultspec="i",
62+
argspec="OO",
63+
arguments=["PyObject* exc", "PyObject* tb"],
64+
)

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_long.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,19 @@ def compile_module(self, name):
272272
arguments=["PyObject* o"],
273273
cmpfunc=unhandled_error_compare
274274
)
275+
276+
test_PyLong_FromString = CPyExtFunction(
277+
lambda args: int(args[0], args[1]),
278+
lambda: (
279+
(" 12 ", 10),
280+
("12", 0),
281+
),
282+
code='''PyObject* wrap_PyLong_FromString(const char* str, int base) {
283+
char* pend;
284+
return PyLong_FromString(str, &pend, base);
285+
}''',
286+
callfunction="wrap_PyLong_FromString",
287+
resultspec="O",
288+
argspec="si",
289+
arguments=["char* string", "int base"],
290+
)

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,41 @@ def compile_module(self, name):
110110
arguments=["PyObject* ignored"],
111111
callfunction="wrap_PyImport_GetModuleDict",
112112
)
113+
114+
test_PyImport_Import = CPyExtFunction(
115+
_reference_importmodule,
116+
lambda: (
117+
("os",),
118+
("os.path",),
119+
("distutils.core",),
120+
("nonexisting",),
121+
),
122+
resultspec="O",
123+
argspec="O",
124+
arguments=["PyObject* module_name"],
125+
cmpfunc=unhandled_error_compare
126+
)
127+
128+
test_PyImport_ImportModuleLevelObject = CPyExtFunction(
129+
lambda args: __import__(*args),
130+
lambda: (
131+
("os", None, None, ["*"], 0),
132+
("os", None, None, ["path"], 0),
133+
),
134+
resultspec="O",
135+
argspec="OOOOi",
136+
arguments=["PyObject* name", "PyObject* globals", "PyObject* locals", "PyObject* fromlist", "int level"],
137+
cmpfunc=unhandled_error_compare
138+
)
139+
140+
test_PyImport_ImportModuleLevel = CPyExtFunction(
141+
lambda args: __import__(*args),
142+
lambda: (
143+
("os", None, None, ["*"], 0),
144+
("os", None, None, ["path"], 0),
145+
),
146+
resultspec="O",
147+
argspec="sOOOi",
148+
arguments=["char* name", "PyObject* globals", "PyObject* locals", "PyObject* fromlist", "int level"],
149+
cmpfunc=unhandled_error_compare
150+
)

graalpython/lib-graalpython/python_cext.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,11 +1198,6 @@ def PyImport_ImportModule(name):
11981198
return __import__(name, fromlist=["*"])
11991199

12001200

1201-
@may_raise
1202-
def PyImport_Import(name):
1203-
return __import__(name)
1204-
1205-
12061201
@may_raise
12071202
def PyImport_GetModuleDict():
12081203
return sys.modules

0 commit comments

Comments
 (0)