Skip to content

Commit 1881628

Browse files
committed
This adds support for Python 3.12
The code compiles, and runs all my (admittedly pretty primitive) web applications. There may still be hidden issues in more complicated scenarios (like threading support).
1 parent b3e09ce commit 1881628

File tree

3 files changed

+69
-23
lines changed

3 files changed

+69
-23
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-20.04
1313
strategy:
1414
matrix:
15-
python-version: ["2.7", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
15+
python-version: ["2.7", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
1616
test-suite: [unittest, python, deadlocks]
1717
steps:
1818
- name: Add deadnakes ppa
@@ -24,7 +24,7 @@ jobs:
2424
libpcre3-dev libjansson-dev libcap2-dev \
2525
curl check
2626
- name: Install distutils
27-
if: contains(fromJson('["3.6","3.7","3.8","3.9","3.10","3.11"]'), matrix.python-version)
27+
if: contains(fromJson('["3.6","3.7","3.8","3.9","3.10","3.11","3.12"]'), matrix.python-version)
2828
run: |
2929
sudo apt install --no-install-recommends -qqyf python${{ matrix.python-version }}-distutils \
3030
- uses: actions/checkout@v2

plugins/python/python_plugin.c

+54-20
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,21 @@ void uwsgi_python_pthread_child(void) {
233233
PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} };
234234
PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} };
235235

236+
PyDoc_STRVAR(uwsgi_py_doc, "uWSGI api module.");
237+
238+
#ifdef PYTHREE
239+
static PyModuleDef uwsgi_module3 = {
240+
PyModuleDef_HEAD_INIT,
241+
"uwsgi",
242+
uwsgi_py_doc,
243+
-1,
244+
NULL,
245+
};
246+
PyObject *init_uwsgi3(void) {
247+
return PyModule_Create(&uwsgi_module3);
248+
}
249+
#endif
250+
236251
int uwsgi_python_init() {
237252

238253
char *pyversion = strchr(Py_GetVersion(), '\n');
@@ -298,6 +313,9 @@ int uwsgi_python_init() {
298313
wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(program_name)+1));
299314
mbstowcs(pname, program_name, strlen(program_name)+1);
300315
Py_SetProgramName(pname);
316+
#ifdef UWSGI_PY312
317+
PyImport_AppendInittab("uwsgi", init_uwsgi3);
318+
#endif
301319
#else
302320
Py_SetProgramName(program_name);
303321
#endif
@@ -660,21 +678,6 @@ void init_uwsgi_vars() {
660678

661679

662680

663-
PyDoc_STRVAR(uwsgi_py_doc, "uWSGI api module.");
664-
665-
#ifdef PYTHREE
666-
static PyModuleDef uwsgi_module3 = {
667-
PyModuleDef_HEAD_INIT,
668-
"uwsgi",
669-
uwsgi_py_doc,
670-
-1,
671-
NULL,
672-
};
673-
PyObject *init_uwsgi3(void) {
674-
return PyModule_Create(&uwsgi_module3);
675-
}
676-
#endif
677-
678681
void init_uwsgi_embedded_module() {
679682
PyObject *new_uwsgi_module, *zero;
680683
int i;
@@ -695,7 +698,9 @@ void init_uwsgi_embedded_module() {
695698

696699

697700
#ifdef PYTHREE
701+
#ifndef UWSGI_PY312
698702
PyImport_AppendInittab("uwsgi", init_uwsgi3);
703+
#endif
699704
new_uwsgi_module = PyImport_AddModule("uwsgi");
700705
#else
701706
new_uwsgi_module = Py_InitModule3("uwsgi", NULL, uwsgi_py_doc);
@@ -1208,7 +1213,10 @@ void uwsgi_python_init_apps() {
12081213

12091214
// prepare for stack suspend/resume
12101215
if (uwsgi.async > 0) {
1211-
#ifdef UWSGI_PY311
1216+
#ifdef UWSGI_PY312
1217+
up.current_c_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async);
1218+
up.current_py_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async);
1219+
#elif defined UWSGI_PY311
12121220
up.current_recursion_remaining = uwsgi_malloc(sizeof(int)*uwsgi.async);
12131221
#else
12141222
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
@@ -1360,7 +1368,12 @@ void uwsgi_python_pre_uwsgi_fork() {
13601368
// Acquire the gil and import lock before forking in order to avoid
13611369
// deadlocks in workers
13621370
UWSGI_GET_GIL
1371+
#if defined UWSGI_PY312
1372+
PyInterpreterState *interp = PyInterpreterState_Get();
1373+
_PyImport_AcquireLock(interp);
1374+
#else
13631375
_PyImport_AcquireLock();
1376+
#endif
13641377
}
13651378
}
13661379

@@ -1372,7 +1385,12 @@ void uwsgi_python_post_uwsgi_fork(int step) {
13721385
if (uwsgi.has_threads) {
13731386
if (step == 0) {
13741387
// Release locks within master process
1388+
#if defined UWSGI_PY312
1389+
PyInterpreterState *interp = PyInterpreterState_Get();
1390+
_PyImport_ReleaseLock(interp);
1391+
#else
13751392
_PyImport_ReleaseLock();
1393+
#endif
13761394
UWSGI_RELEASE_GIL
13771395
}
13781396
else {
@@ -1643,7 +1661,11 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
16431661
PyGILState_Release(pgst);
16441662

16451663
if (wsgi_req) {
1646-
#ifdef UWSGI_PY311
1664+
#ifdef UWSGI_PY312
1665+
up.current_c_recursion_remaining[wsgi_req->async_id] = tstate->c_recursion_remaining;
1666+
up.current_py_recursion_remaining[wsgi_req->async_id] = tstate->py_recursion_remaining;
1667+
up.current_frame[wsgi_req->async_id] = tstate->cframe;
1668+
#elif defined UWSGI_PY311
16471669
up.current_recursion_remaining[wsgi_req->async_id] = tstate->recursion_remaining;
16481670
up.current_frame[wsgi_req->async_id] = tstate->cframe;
16491671
#else
@@ -1652,7 +1674,11 @@ void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
16521674
#endif
16531675
}
16541676
else {
1655-
#ifdef UWSGI_PY311
1677+
#ifdef UWSGI_PY312
1678+
up.current_main_c_recursion_remaining = tstate->c_recursion_remaining;
1679+
up.current_main_py_recursion_remaining = tstate->py_recursion_remaining;
1680+
up.current_main_frame = tstate->cframe;
1681+
#elif defined UWSGI_PY311
16561682
up.current_main_recursion_remaining = tstate->recursion_remaining;
16571683
up.current_main_frame = tstate->cframe;
16581684
#else
@@ -1886,7 +1912,11 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
18861912
PyGILState_Release(pgst);
18871913

18881914
if (wsgi_req) {
1889-
#ifdef UWSGI_PY311
1915+
#ifdef UWSGI_PY312
1916+
tstate->c_recursion_remaining = up.current_c_recursion_remaining[wsgi_req->async_id];
1917+
tstate->py_recursion_remaining = up.current_py_recursion_remaining[wsgi_req->async_id];
1918+
tstate->cframe = up.current_frame[wsgi_req->async_id];
1919+
#elif defined UWSGI_PY311
18901920
tstate->recursion_remaining = up.current_recursion_remaining[wsgi_req->async_id];
18911921
tstate->cframe = up.current_frame[wsgi_req->async_id];
18921922
#else
@@ -1895,7 +1925,11 @@ void uwsgi_python_resume(struct wsgi_request *wsgi_req) {
18951925
#endif
18961926
}
18971927
else {
1898-
#ifdef UWSGI_PY311
1928+
#ifdef UWSGI_PY312
1929+
tstate->c_recursion_remaining = up.current_main_c_recursion_remaining;
1930+
tstate->py_recursion_remaining = up.current_main_py_recursion_remaining;
1931+
tstate->cframe = up.current_main_frame;
1932+
#elif defined UWSGI_PY311
18991933
tstate->recursion_remaining = up.current_main_recursion_remaining;
19001934
tstate->cframe = up.current_main_frame;
19011935
#else

plugins/python/uwsgi_python.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
# define UWSGI_PY311
2222
#endif
2323

24+
#if (PY_VERSION_HEX >= 0x030c0000)
25+
# define UWSGI_PY312
26+
#endif
27+
2428
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 7
2529
#define HAS_NOT_PyMemoryView_FromBuffer
2630
#endif
@@ -182,7 +186,15 @@ struct uwsgi_python {
182186

183187
char *callable;
184188

185-
#ifdef UWSGI_PY311
189+
#ifdef UWSGI_PY312
190+
int *current_c_recursion_remaining;
191+
int *current_py_recursion_remaining;
192+
_PyCFrame **current_frame;
193+
194+
int current_main_c_recursion_remaining;
195+
int current_main_py_recursion_remaining;
196+
_PyCFrame *current_main_frame;
197+
#elif defined UWSGI_PY311
186198
int *current_recursion_remaining;
187199
_PyCFrame **current_frame;
188200

0 commit comments

Comments
 (0)