Commit e138a846 authored by da-woods's avatar da-woods Committed by GitHub

Get 0.29.x working on Python 3.11 (GH-4465)

* Initial support for Python 3.11 (GH-4414)

https://github.com/cython/cython/issues/4414

* Add a basic replacement for PyCode_New().

An optimized versions would be nice, but this is intended to work sufficiently to start testing. Also, CPython 3.11 might actually add a new C-API function to simplify setting the current code position. That might be used instead.

* Disable introspection of frame object with vectorcall

This feature looked to only be used for early Python versions that don't have the full vectorcall protocol (and the contents of the frame object are changed in Python 3.11).

* Use new C-API function to get the current frame on Python 3.11 alpha (GH-4427)

Use the accessor function instead of the direct struct member (which is now the wrong type).

https://github.com/cython/cython/issues/4427
Closes https://github.com/cython/cython/issues/4416

* Fix number of arguments

* Disable CYTHON_FAST_PYCALL for 3.11 in Cython 0.29.x due to non-trivial incompatibilities.

* Remove remanent of 3.8alpha/beta workaround for PyCode_New().
parent 41d65a72
...@@ -714,9 +714,15 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i ...@@ -714,9 +714,15 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
PyTracebackObject *tb = (PyTracebackObject *) exc_state->exc_traceback; PyTracebackObject *tb = (PyTracebackObject *) exc_state->exc_traceback;
PyFrameObject *f = tb->tb_frame; PyFrameObject *f = tb->tb_frame;
Py_XINCREF(tstate->frame);
assert(f->f_back == NULL); assert(f->f_back == NULL);
#if PY_VERSION_HEX >= 0x030B00A1
// PyThreadState_GetFrame returns NULL if there isn't a current frame
// which is a valid state so no need to check
f->f_back = PyThreadState_GetFrame(tstate);
#else
Py_XINCREF(tstate->frame);
f->f_back = tstate->frame; f->f_back = tstate->frame;
#endif
} }
#endif #endif
} }
......
...@@ -179,7 +179,9 @@ ...@@ -179,7 +179,9 @@
#define CYTHON_FAST_THREAD_STATE 1 #define CYTHON_FAST_THREAD_STATE 1
#endif #endif
#ifndef CYTHON_FAST_PYCALL #ifndef CYTHON_FAST_PYCALL
#define CYTHON_FAST_PYCALL 1 // Python 3.11 deleted localplus argument from frame object, which is used in our
// fast_pycall code
#define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030B00A1)
#endif #endif
#ifndef CYTHON_PEP489_MULTI_PHASE_INIT #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
#define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000)
...@@ -383,9 +385,77 @@ class __Pyx_FakeReference { ...@@ -383,9 +385,77 @@ class __Pyx_FakeReference {
#define __Pyx_DefaultClassType PyClass_Type #define __Pyx_DefaultClassType PyClass_Type
#else #else
#define __Pyx_BUILTIN_MODULE_NAME "builtins" #define __Pyx_BUILTIN_MODULE_NAME "builtins"
#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 #define __Pyx_DefaultClassType PyType_Type
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ #if PY_VERSION_HEX >= 0x030B00A1
PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f,
PyObject *code, PyObject *c, PyObject* n, PyObject *v,
PyObject *fv, PyObject *cell, PyObject* fn,
PyObject *name, int fline, PyObject *lnos) {
// TODO - currently written to be simple and work in limited API etc.
// A more optimized version would be good
PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL;
PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL;
const char *fn_cstr=NULL;
const char *name_cstr=NULL;
PyCodeObject* co=NULL;
PyObject *type, *value, *traceback;
// we must be able to call this while an exception is happening - thus clear then restore the state
PyErr_Fetch(&type, &value, &traceback);
if (!(kwds=PyDict_New())) goto end;
if (!(argcount=PyLong_FromLong(a))) goto end;
if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end;
if (!(posonlyargcount=PyLong_FromLong(0))) goto end;
if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end;
if (!(kwonlyargcount=PyLong_FromLong(k))) goto end;
if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end;
if (!(nlocals=PyLong_FromLong(l))) goto end;
if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end;
if (!(stacksize=PyLong_FromLong(s))) goto end;
if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end;
if (!(flags=PyLong_FromLong(f))) goto end;
if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end;
if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end;
if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end;
if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end;
if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end;
if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too;
if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here
if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too;
Py_XDECREF((PyObject*)co);
co = (PyCodeObject*)call_result;
call_result = NULL;
if (0) {
cleanup_code_too:
Py_XDECREF((PyObject*)co);
co = NULL;
}
end:
Py_XDECREF(kwds);
Py_XDECREF(argcount);
Py_XDECREF(posonlyargcount);
Py_XDECREF(kwonlyargcount);
Py_XDECREF(nlocals);
Py_XDECREF(stacksize);
Py_XDECREF(replace);
Py_XDECREF(call_result);
Py_XDECREF(empty);
if (type) {
PyErr_Restore(type, value, traceback);
}
return co;
}
#else #else
#define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
......
...@@ -1991,6 +1991,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, ...@@ -1991,6 +1991,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#endif #endif
#if CYTHON_FAST_PYCALL
// Initialised by module init code. // Initialised by module init code.
static size_t __pyx_pyframe_localsplus_offset = 0; static size_t __pyx_pyframe_localsplus_offset = 0;
...@@ -2005,6 +2006,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, ...@@ -2005,6 +2006,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
(void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus)))
#define __Pyx_PyFrame_GetLocalsplus(frame) \ #define __Pyx_PyFrame_GetLocalsplus(frame) \
(assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset))
#endif // CYTHON_FAST_PYCALL
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment