summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2021-10-24 23:13:50 +0100
committerGitHub <noreply@github.com>2021-10-25 00:13:50 +0200
commit9d1ffd5dcdcc0f2f719f86a9a30ce08a67641f10 (patch)
tree0c2bc714e338053616581218d360f4bdf43c4256
parent346c81fe9b0a13892a2dbd137d994f198940b435 (diff)
downloadcython-9d1ffd5dcdcc0f2f719f86a9a30ce08a67641f10.tar.gz
Initial support for Python 3.11 (GH-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).
-rw-r--r--.github/workflows/ci.yml8
-rw-r--r--Cython/Utility/Coroutine.c3
-rw-r--r--Cython/Utility/ModuleSetupCode.c77
-rw-r--r--Cython/Utility/ObjectHandling.c2
4 files changed, 80 insertions, 10 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9c8cc0aab..ca0f43a88 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -25,13 +25,13 @@ jobs:
# in all python versions and test failures (builtin_float) in 3.5<
os: [ubuntu-18.04]
backend: [c, cpp]
- python-version: ["2.7", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10"]
+ python-version: ["2.7", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11-dev"]
env: [{}]
include:
- # Temporary - Allow failure on all Python -dev jobs until they are considered stable
- #- python-version: 3.10-dev
- # allowed_failure: true
+ # Temporary - Allow failure on Python 3.11-dev jobs until they are considered stable
+ - python-version: 3.11-dev
+ allowed_failure: true
# Ubuntu sub-jobs:
# ================
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index e530a078d..fea7657bc 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -719,7 +719,8 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
exc_state = &self->gi_exc_state;
if (exc_state->exc_type) {
- #if CYTHON_COMPILING_IN_PYPY
+ #if CYTHON_COMPILING_IN_PYPY || PY_VERSION_HEX >= 0x030B00A1
+ // FIXME: https://bugs.python.org/issue44590 - Python 3.11 changed the type of frame
// FIXME: what to do in PyPy?
#else
// Generators always return to their most recent caller, not
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index 4bced6cac..758ce7f86 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -465,13 +465,80 @@ class __Pyx_FakeReference {
#else
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
#define __Pyx_DefaultClassType PyType_Type
-#if PY_VERSION_HEX >= 0x030800B2
+#if PY_VERSION_HEX >= 0x030B00A1
+ static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int p, 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(p))) 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;
+ }
+#elif PY_VERSION_HEX >= 0x030800B2
+
#define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
-#elif PY_VERSION_HEX >= 0x030800A4
- // TODO: remove this special case once Py3.8 is released.
- #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
- PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
#else
#define __Pyx_PyCode_New(a, p, 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)
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index 074bcd8e7..f495a5ddd 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -2442,6 +2442,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#endif
+#if !CYTHON_VECTORCALL
// Initialised by module init code.
static size_t __pyx_pyframe_localsplus_offset = 0;
@@ -2456,6 +2457,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)))
#define __Pyx_PyFrame_GetLocalsplus(frame) \
(assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset))
+#endif // !CYTHON_VECTORCALL
#endif