Skip to content

Commit e84b253

Browse files
committed
[GR-29396] [GR-21017] Properly support building HPy universal extensions.
PullRequest: graalpython/1618
2 parents 9a8db4c + a3eceac commit e84b253

File tree

12 files changed

+315
-59
lines changed

12 files changed

+315
-59
lines changed

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "overlay": "906bd55aa7bab20dde6fec805cd289559fb64d40" }
1+
{ "overlay": "d8d57ccfe5a0a2b1ef094be4772d4f01c2dfb2cb" }

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

Lines changed: 95 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -48,86 +48,142 @@ PyTypeObject _PyExc_BaseException = PY_TRUFFLE_TYPE("BaseException", &PyType_Typ
4848

4949
PyObject * PyExc_BaseException = NULL;
5050
PyObject * PyExc_Exception = NULL;
51+
PyObject * PyExc_StopAsyncIteration = NULL;
52+
PyObject * PyExc_StopIteration = NULL;
53+
PyObject * PyExc_GeneratorExit = NULL;
54+
PyObject * PyExc_ArithmeticError = NULL;
55+
PyObject * PyExc_LookupError = NULL;
56+
PyObject * PyExc_AssertionError = NULL;
5157
PyObject * PyExc_AttributeError = NULL;
58+
PyObject * PyExc_BufferError = NULL;
59+
PyObject * PyExc_EOFError = NULL;
5260
PyObject * PyExc_FloatingPointError = NULL;
5361
PyObject * PyExc_OSError = NULL;
5462
PyObject * PyExc_ImportError = NULL;
63+
PyObject * PyExc_ModuleNotFoundError = NULL;
5564
PyObject * PyExc_IndexError = NULL;
5665
PyObject * PyExc_KeyError = NULL;
66+
PyObject * PyExc_KeyboardInterrupt = NULL;
5767
PyObject * PyExc_MemoryError = NULL;
5868
PyObject * PyExc_NameError = NULL;
5969
PyObject * PyExc_OverflowError = NULL;
6070
PyObject * PyExc_RuntimeError = NULL;
71+
PyObject * PyExc_RecursionError = NULL;
72+
PyObject * PyExc_NotImplementedError = NULL;
73+
PyObject * PyExc_SyntaxError = NULL;
74+
PyObject * PyExc_IndentationError = NULL;
75+
PyObject * PyExc_TabError = NULL;
76+
PyObject * PyExc_ReferenceError = NULL;
6177
PyObject * PyExc_SystemError = NULL;
78+
PyObject * PyExc_SystemExit = NULL;
6279
PyObject * PyExc_TypeError = NULL;
80+
PyObject * PyExc_UnboundLocalError = NULL;
81+
PyObject * PyExc_UnicodeError = NULL;
82+
PyObject * PyExc_UnicodeEncodeError = NULL;
83+
PyObject * PyExc_UnicodeDecodeError = NULL;
84+
PyObject * PyExc_UnicodeTranslateError = NULL;
6385
PyObject * PyExc_ValueError = NULL;
86+
PyObject * PyExc_ZeroDivisionError = NULL;
87+
PyObject * PyExc_BlockingIOError = NULL;
88+
PyObject * PyExc_BrokenPipeError = NULL;
89+
PyObject * PyExc_ChildProcessError = NULL;
90+
PyObject * PyExc_ConnectionError = NULL;
91+
PyObject * PyExc_ConnectionAbortedError = NULL;
92+
PyObject * PyExc_ConnectionRefusedError = NULL;
93+
PyObject * PyExc_ConnectionResetError = NULL;
94+
PyObject * PyExc_FileExistsError = NULL;
95+
PyObject * PyExc_FileNotFoundError = NULL;
96+
PyObject * PyExc_InterruptedError = NULL;
97+
PyObject * PyExc_IsADirectoryError = NULL;
98+
PyObject * PyExc_NotADirectoryError = NULL;
99+
PyObject * PyExc_PermissionError = NULL;
100+
PyObject * PyExc_ProcessLookupError = NULL;
101+
PyObject * PyExc_TimeoutError = NULL;
102+
103+
PyObject * PyExc_EnvironmentError = NULL;
64104
PyObject * PyExc_IOError = NULL;
105+
65106
PyObject * PyExc_Warning = NULL;
66107
PyObject * PyExc_UserWarning = NULL;
67108
PyObject * PyExc_DeprecationWarning = NULL;
68-
PyObject * PyExc_RuntimeWarning = NULL;
69-
PyObject * PyExc_FutureWarning = NULL;
70109
PyObject * PyExc_PendingDeprecationWarning = NULL;
71110
PyObject * PyExc_SyntaxWarning = NULL;
72-
PyObject * PyExc_SyntaxError = NULL;
111+
PyObject * PyExc_RuntimeWarning = NULL;
112+
PyObject * PyExc_FutureWarning = NULL;
73113
PyObject * PyExc_ImportWarning = NULL;
74114
PyObject * PyExc_UnicodeWarning = NULL;
75115
PyObject * PyExc_BytesWarning = NULL;
76116
PyObject * PyExc_ResourceWarning = NULL;
77-
PyObject * PyExc_ZeroDivisionError = NULL;
78-
PyObject * PyExc_ArithmeticError = NULL;
79-
PyObject * PyExc_StopIteration = NULL;
80-
PyObject * PyExc_BufferError = NULL;
81-
PyObject * PyExc_AssertionError = NULL;
82-
PyObject * PyExc_UnboundLocalError = NULL;
83-
PyObject * PyExc_NotImplementedError = NULL;
84-
PyObject * PyExc_RecursionError = NULL;
85-
PyObject * PyExc_UnicodeEncodeError = NULL;
86-
PyObject * PyExc_GeneratorExit = NULL;
87-
PyObject * PyExc_EOFError = NULL;
88-
PyObject * PyExc_FileNotFoundError = NULL;
89117

90118
void initialize_exceptions() {
91-
PyExc_AttributeError = PY_EXCEPTION("AttributeError");
92-
PyExc_AssertionError = PY_EXCEPTION("AssertionError");
93119
PyExc_BaseException = PY_EXCEPTION("BaseException");
94-
PyExc_BytesWarning = PY_EXCEPTION("BytesWarning");
95-
PyExc_DeprecationWarning = PY_EXCEPTION("DeprecationWarning");
96120
PyExc_Exception = PY_EXCEPTION("Exception");
121+
PyExc_StopAsyncIteration = PY_EXCEPTION("StopAsyncIteration");
122+
PyExc_StopIteration = PY_EXCEPTION("StopIteration");
123+
PyExc_GeneratorExit = PY_EXCEPTION("GeneratorExit");
124+
PyExc_ArithmeticError = PY_EXCEPTION("ArithmeticError");
125+
PyExc_LookupError = PY_EXCEPTION("LookupError");
126+
PyExc_AssertionError = PY_EXCEPTION("AssertionError");
127+
PyExc_AttributeError = PY_EXCEPTION("AttributeError");
128+
PyExc_BufferError = PY_EXCEPTION("BufferError");
129+
PyExc_EOFError = PY_EXCEPTION("EOFError");
97130
PyExc_FloatingPointError = PY_EXCEPTION("FloatingPointError");
98-
PyExc_IOError = PY_EXCEPTION("IOError");
131+
PyExc_OSError = PY_EXCEPTION("OSError");
99132
PyExc_ImportError = PY_EXCEPTION("ImportError");
100-
PyExc_ImportWarning = PY_EXCEPTION("ImportWarning");
133+
PyExc_ModuleNotFoundError = PY_EXCEPTION("ModuleNotFoundError");
101134
PyExc_IndexError = PY_EXCEPTION("IndexError");
102135
PyExc_KeyError = PY_EXCEPTION("KeyError");
136+
PyExc_KeyboardInterrupt = PY_EXCEPTION("KeyboardInterrupt");
103137
PyExc_MemoryError = PY_EXCEPTION("MemoryError");
104138
PyExc_NameError = PY_EXCEPTION("NameError");
105-
PyExc_OSError = PY_EXCEPTION("OSError");
106139
PyExc_OverflowError = PY_EXCEPTION("OverflowError");
107-
PyExc_PendingDeprecationWarning = PY_EXCEPTION("PendingDeprecationWarning");
108-
PyExc_ResourceWarning = PY_EXCEPTION("ResourceWarning");
109140
PyExc_RuntimeError = PY_EXCEPTION("RuntimeError");
110-
PyExc_RuntimeWarning = PY_EXCEPTION("RuntimeWarning");
111-
PyExc_SyntaxWarning = PY_EXCEPTION("SyntaxWarning");
141+
PyExc_RecursionError = PY_EXCEPTION("RecursionError");
142+
PyExc_NotImplementedError = PY_EXCEPTION("NotImplementedError");
112143
PyExc_SyntaxError = PY_EXCEPTION("SyntaxError");
144+
PyExc_IndentationError = PY_EXCEPTION("IndentationError");
145+
PyExc_TabError = PY_EXCEPTION("TabError");
146+
PyExc_ReferenceError = PY_EXCEPTION("ReferenceError");
113147
PyExc_SystemError = PY_EXCEPTION("SystemError");
148+
PyExc_SystemExit = PY_EXCEPTION("SystemExit");
114149
PyExc_TypeError = PY_EXCEPTION("TypeError");
115-
PyExc_UnicodeWarning = PY_EXCEPTION("UnicodeWarning");
116-
PyExc_UserWarning = PY_EXCEPTION("UserWarning");
117-
PyExc_ValueError = PY_EXCEPTION("ValueError");
118-
PyExc_Warning = PY_EXCEPTION("Warning");
119-
PyExc_ZeroDivisionError = PY_EXCEPTION("ZeroDivisionError");
120-
PyExc_ArithmeticError = PY_EXCEPTION("ArithmeticError");
121-
PyExc_StopIteration = PY_EXCEPTION("StopIteration");
122-
PyExc_BufferError = PY_EXCEPTION("BufferError");
123150
PyExc_UnboundLocalError = PY_EXCEPTION("UnboundLocalError");
124-
PyExc_NotImplementedError = PY_EXCEPTION("NotImplementedError");
125-
PyExc_RecursionError = PY_EXCEPTION("RecursionError");
126-
PyExc_NotImplementedError = PY_EXCEPTION("NotImplementedError");
151+
PyExc_UnicodeError = PY_EXCEPTION("UnicodeError");
127152
PyExc_UnicodeEncodeError = PY_EXCEPTION("UnicodeEncodeError");
128-
PyExc_GeneratorExit = PY_EXCEPTION("GeneratorExit");
129-
PyExc_EOFError = PY_EXCEPTION("EOFError");
153+
PyExc_UnicodeDecodeError = PY_EXCEPTION("UnicodeDecodeError");
154+
PyExc_UnicodeTranslateError = PY_EXCEPTION("UnicodeTranslateError");
155+
PyExc_ValueError = PY_EXCEPTION("ValueError");
156+
PyExc_ZeroDivisionError = PY_EXCEPTION("ZeroDivisionError");
157+
PyExc_BlockingIOError = PY_EXCEPTION("BlockingIOError");
158+
PyExc_BrokenPipeError = PY_EXCEPTION("BrokenPipeError");
159+
PyExc_ChildProcessError = PY_EXCEPTION("ChildProcessError");
160+
PyExc_ConnectionError = PY_EXCEPTION("ConnectionError");
161+
PyExc_ConnectionAbortedError = PY_EXCEPTION("ConnectionAbortedError");
162+
PyExc_ConnectionRefusedError = PY_EXCEPTION("ConnectionRefusedError");
163+
PyExc_ConnectionResetError = PY_EXCEPTION("ConnectionResetError");
164+
PyExc_FileExistsError = PY_EXCEPTION("FileExistsError");
130165
PyExc_FileNotFoundError = PY_EXCEPTION("FileNotFoundError");
166+
PyExc_InterruptedError = PY_EXCEPTION("InterruptedError");
167+
PyExc_IsADirectoryError = PY_EXCEPTION("IsADirectoryError");
168+
PyExc_NotADirectoryError = PY_EXCEPTION("NotADirectoryError");
169+
PyExc_PermissionError = PY_EXCEPTION("PermissionError");
170+
PyExc_ProcessLookupError = PY_EXCEPTION("ProcessLookupError");
171+
PyExc_TimeoutError = PY_EXCEPTION("TimeoutError");
172+
173+
PyExc_EnvironmentError = PY_EXCEPTION("EnvironmentError");
174+
PyExc_IOError = PY_EXCEPTION("IOError");
175+
176+
PyExc_Warning = PY_EXCEPTION("Warning");
177+
PyExc_UserWarning = PY_EXCEPTION("UserWarning");
178+
PyExc_DeprecationWarning = PY_EXCEPTION("DeprecationWarning");
179+
PyExc_PendingDeprecationWarning = PY_EXCEPTION("PendingDeprecationWarning");
180+
PyExc_SyntaxWarning = PY_EXCEPTION("SyntaxWarning");
181+
PyExc_RuntimeWarning = PY_EXCEPTION("RuntimeWarning");
182+
PyExc_FutureWarning = PY_EXCEPTION("FutureWarning");
183+
PyExc_ImportWarning = PY_EXCEPTION("ImportWarning");
184+
PyExc_UnicodeWarning = PY_EXCEPTION("UnicodeWarning");
185+
PyExc_BytesWarning = PY_EXCEPTION("BytesWarning");
186+
PyExc_ResourceWarning = PY_EXCEPTION("ResourceWarning");
131187
}
132188

133189

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ void* PyMem_Malloc(size_t size) {
109109
return ptr;
110110
}
111111

112+
void* PyMem_Calloc(size_t nelem, size_t elsize) {
113+
if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize) {
114+
return NULL;
115+
}
116+
return PyMem_RawCalloc(nelem, elsize);
117+
}
118+
112119
void* PyMem_RawMalloc(size_t size) {
113120
mem_head_t* ptr_with_head = malloc((size == 0 ? 1 : size) + sizeof(mem_head_t));
114121
void* ptr = FROM_MEM_HEAD(ptr_with_head);

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare, GRAALPYTHON
4242
__dir__ = __file__.rpartition("/")[0]
4343

44+
ModuleType = type(sys)
45+
46+
47+
class SubModuleType(ModuleType):
48+
pass
49+
4450

4551
def _reference_format_specifier_w_star(args):
4652
bytes_like = args[0]
@@ -403,7 +409,7 @@ def compile_module(self, name):
403409
va_end(va);
404410
return result;
405411
}
406-
412+
407413
static PyObject* wrap_PyArg_VaParseTupleAndKeywords_SizeT(PyObject* argTuple) {
408414
PyObject* out0 = NULL;
409415
int out1 = 0;
@@ -439,3 +445,21 @@ def compile_module(self, name):
439445
cmpfunc=unhandled_error_compare
440446
)
441447

448+
# For some reason, some 'PyModule_*' functions are in 'modsupport.h'
449+
test_PyModule_SetDocString = CPyExtFunction(
450+
lambda args: args[1],
451+
lambda: (
452+
(ModuleType("hello"), "hello doc"),
453+
(SubModuleType("subhello"), "subhello doc"),
454+
),
455+
code='''
456+
static PyObject* wrap_PyModule_SetDocString(PyObject* object, char* doc) {
457+
PyModule_SetDocString(object, (const char *)doc);
458+
return PyObject_GetAttrString(object, "__doc__");
459+
}
460+
''',
461+
resultspec="O",
462+
argspec='Os',
463+
callfunction="wrap_PyModule_SetDocString",
464+
arguments=["PyObject* object", "char* doc"],
465+
)
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
import sys
41+
from . import CPyExtTestCase, CPyExtFunction, unhandled_error_compare
42+
__dir__ = __file__.rpartition("/")[0]
43+
44+
ModuleType = type(sys)
45+
46+
47+
class SubModuleType(ModuleType):
48+
pass
49+
50+
51+
class TestPyModule(CPyExtTestCase):
52+
53+
def compile_module(self, name):
54+
type(self).mro()[1].__dict__["test_%s" % name].create_module(name)
55+
super(TestPyModule, self).compile_module(name)
56+
57+
test_PyModule_Check = CPyExtFunction(
58+
lambda args: isinstance(args[0], ModuleType),
59+
lambda: (
60+
(sys,),
61+
(ModuleType("hello"),),
62+
(SubModuleType("subhello"),),
63+
("not a module",),
64+
(3,),
65+
),
66+
resultspec="i",
67+
argspec='O',
68+
arguments=["PyObject* o"],
69+
)
70+
71+
test_PyModule_CheckExact = CPyExtFunction(
72+
lambda args: type(args[0]) is ModuleType,
73+
lambda: (
74+
(sys,),
75+
(ModuleType("hello"),),
76+
(SubModuleType("subhello"),),
77+
("not a module",),
78+
(3,),
79+
),
80+
resultspec="i",
81+
argspec='O',
82+
arguments=["PyObject* o"],
83+
)
84+
85+
test_PyModule_GetState = CPyExtFunction(
86+
lambda args: "Hello, world!",
87+
lambda: (
88+
("Hello, world!", ),
89+
),
90+
code='''
91+
typedef struct {
92+
PyObject *content;
93+
} test_module_state_t;
94+
95+
static PyModuleDef test_module_def = {
96+
PyModuleDef_HEAD_INIT,
97+
"DummyModule",
98+
"This is a dummy module.",
99+
sizeof(test_module_state_t),
100+
NULL, NULL, NULL, NULL, NULL
101+
};
102+
103+
static PyObject* wrap_PyModule_GetState(PyObject* arg) {
104+
PyObject* module = PyModule_Create(&test_module_def);
105+
test_module_state_t* module_state = (test_module_state_t*) PyModule_GetState(module);
106+
Py_INCREF(arg);
107+
module_state->content = arg;
108+
return ((test_module_state_t*) PyModule_GetState(module))->content;
109+
}
110+
''',
111+
resultspec="O",
112+
argspec="O",
113+
arguments=["PyObject* arg"],
114+
callfunction="wrap_PyModule_GetState",
115+
cmpfunc=unhandled_error_compare
116+
)
117+
118+
test_PyModule_GetName = CPyExtFunction(
119+
lambda args: args[0].__name__,
120+
lambda: (
121+
(sys,),
122+
(ModuleType("hello"),),
123+
(SubModuleType("subhello"),),
124+
),
125+
resultspec="s",
126+
argspec='O',
127+
arguments=["PyObject* object"],
128+
)
129+
130+
test_PyModule_GetNameObject = CPyExtFunction(
131+
lambda args: args[0].__name__,
132+
lambda: (
133+
(sys,),
134+
(ModuleType("hello"),),
135+
(SubModuleType("subhello"),),
136+
),
137+
resultspec="O",
138+
argspec='O',
139+
arguments=["PyObject* object"],
140+
)

0 commit comments

Comments
 (0)