summaryrefslogtreecommitdiff
path: root/dev-python/greenlet/files/greenlet-1.1.2-fix-py3.11.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dev-python/greenlet/files/greenlet-1.1.2-fix-py3.11.patch')
-rw-r--r--dev-python/greenlet/files/greenlet-1.1.2-fix-py3.11.patch223
1 files changed, 223 insertions, 0 deletions
diff --git a/dev-python/greenlet/files/greenlet-1.1.2-fix-py3.11.patch b/dev-python/greenlet/files/greenlet-1.1.2-fix-py3.11.patch
new file mode 100644
index 000000000000..475fcd82fb34
--- /dev/null
+++ b/dev-python/greenlet/files/greenlet-1.1.2-fix-py3.11.patch
@@ -0,0 +1,223 @@
+From: Victor Stinner <vstinner@python.org>
+Subject: [PATCH] Closes #305: Add Python 3.11 support
+
+* Add GREENLET_PY311 macro
+* PyGreenlet structure:
+
+ * Add 3 members for the "data stack": 'datastack_chunk',
+ 'datastack_top' and 'datastack_limit'.
+ * Add 'current_frame' member.
+
+* Rename CFrame to _PyCFrame
+* tox.ini: Add py311 environment.
+
+Changes partially backport from the master branch:
+commit 63e1099acc3677e614532bea0fa2e1967b69125f.
+
+Co-Authored-By: Miro HronĨok <miro@hroncok.cz>
+
+https://github.com/python-greenlet/greenlet/pull/306
+--- a/src/greenlet/greenlet.c
++++ b/src/greenlet/greenlet.c
+@@ -170,9 +170,11 @@ green_clear_exc(PyGreenlet* g)
+ {
+ #if GREENLET_PY37
+ g->exc_info = NULL;
+- g->exc_state.exc_type = NULL;
+ g->exc_state.exc_value = NULL;
++#if !GREENLET_PY311
++ g->exc_state.exc_type = NULL;
+ g->exc_state.exc_traceback = NULL;
++#endif
+ g->exc_state.previous_item = NULL;
+ #else
+ g->exc_type = NULL;
+@@ -525,8 +527,13 @@ g_switchstack(void)
+ { /* save state */
+ PyGreenlet* current = ts_current;
+ PyThreadState* tstate = PyThreadState_GET();
++#if GREENLET_PY311
++ current->recursion_depth = (tstate->recursion_limit
++ - tstate->recursion_remaining);
++#else
+ current->recursion_depth = tstate->recursion_depth;
+ current->top_frame = tstate->frame;
++#endif
+ #if GREENLET_PY37
+ current->context = tstate->context;
+ #endif
+@@ -551,6 +558,15 @@ g_switchstack(void)
+ */
+ current->cframe = tstate->cframe;
+ ts__g_switchstack_use_tracing = tstate->cframe->use_tracing;
++#if GREENLET_PY311
++ current->current_frame = tstate->cframe->current_frame;
++ current->datastack_chunk = tstate->datastack_chunk;
++ current->datastack_top = tstate->datastack_top;
++ current->datastack_limit = tstate->datastack_limit;
++ PyFrameObject *frame = PyThreadState_GetFrame(tstate);
++ Py_XDECREF(frame); /* PyThreadState_GetFrame gives us a new reference. */
++ current->top_frame = frame;
++#endif
+ #endif
+ }
+
+@@ -574,9 +590,6 @@ g_switchstack(void)
+ PyGreenlet* target = ts_target;
+ PyGreenlet* origin = ts_current;
+ PyThreadState* tstate = PyThreadState_GET();
+- tstate->recursion_depth = target->recursion_depth;
+- tstate->frame = target->top_frame;
+- target->top_frame = NULL;
+
+ #if GREENLET_PY37
+ tstate->context = target->context;
+@@ -607,7 +620,18 @@ g_switchstack(void)
+ */
+ tstate->cframe->use_tracing = ts__g_switchstack_use_tracing;
+ #endif
+-
++#if GREENLET_PY311
++ tstate->recursion_remaining = (tstate->recursion_limit
++ - target->recursion_depth);
++ tstate->cframe->current_frame = target->current_frame;
++ tstate->datastack_chunk = target->datastack_chunk;
++ tstate->datastack_top = target->datastack_top;
++ tstate->datastack_limit = target->datastack_limit;
++#else
++ tstate->recursion_depth = target->recursion_depth;
++ tstate->frame = target->top_frame;
++#endif
++ target->top_frame = NULL;
+ assert(ts_origin == NULL);
+ Py_INCREF(target);
+ ts_current = target;
+@@ -810,7 +834,7 @@ static int GREENLET_NOINLINE(g_initialstub)(void* mark)
+ We want to defer copying the state info until we're sure
+ we need it and are in a stable place to do so.
+ */
+- CFrame trace_info;
++ _PyCFrame trace_info;
+ #endif
+ /* save exception in case getattr clears it */
+ PyErr_Fetch(&exc, &val, &tb);
+@@ -875,7 +899,12 @@ static int GREENLET_NOINLINE(g_initialstub)(void* mark)
+ }
+ self->top_frame = NULL;
+ green_clear_exc(self);
++#if GREENLET_PY311
++ self->recursion_depth = (PyThreadState_GET()->recursion_limit
++ - PyThreadState_GET()->recursion_remaining);
++#else
+ self->recursion_depth = PyThreadState_GET()->recursion_depth;
++#endif
+
+ /* restore arguments in case they are clobbered */
+ ts_target = self;
+@@ -1006,13 +1035,13 @@ green_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+ it uses the ``root_cframe`` just to have something to put there.
+ However, once the greenlet is actually switched to for the first
+ time, ``g_initialstub`` (which doesn't actually "return" while the
+- greenlet is running) stores a new CFrame on its local stack, and
++ greenlet is running) stores a new _PyCFrame on its local stack, and
+ copies the appropriate values from the currently running CFrame;
+- this is then made the CFrame for the newly-minted greenlet.
++ this is then made the _PyCFrame for the newly-minted greenlet.
+ ``g_initialstub`` then proceeds to call ``glet.run()``, which
+- results in ``PyEval_...`` adding the CFrame to the list. Switches
++ results in ``PyEval_...`` adding the _PyCFrame to the list. Switches
+ continue as normal. Finally, when the greenlet finishes, the call to
+- ``glet.run()`` returns and the CFrame is taken out of the linked
++ ``glet.run()`` returns and the _PyCFrame is taken out of the linked
+ list and the stack value is now unused and free to expire.
+ */
+ ((PyGreenlet*)o)->cframe = &PyThreadState_GET()->root_cframe;
+@@ -1121,9 +1150,11 @@ green_traverse(PyGreenlet* self, visitproc visit, void* arg)
+ Py_VISIT(self->context);
+ #endif
+ #if GREENLET_PY37
+- Py_VISIT(self->exc_state.exc_type);
+ Py_VISIT(self->exc_state.exc_value);
++#if !GREENLET_PY311
++ Py_VISIT(self->exc_state.exc_type);
+ Py_VISIT(self->exc_state.exc_traceback);
++#endif
+ #else
+ Py_VISIT(self->exc_type);
+ Py_VISIT(self->exc_value);
+@@ -1159,9 +1190,11 @@ green_clear(PyGreenlet* self)
+ Py_CLEAR(self->context);
+ #endif
+ #if GREENLET_PY37
+- Py_CLEAR(self->exc_state.exc_type);
+ Py_CLEAR(self->exc_state.exc_value);
++#if !GREENLET_PY311
++ Py_CLEAR(self->exc_state.exc_type);
+ Py_CLEAR(self->exc_state.exc_traceback);
++#endif
+ #else
+ Py_CLEAR(self->exc_type);
+ Py_CLEAR(self->exc_value);
+@@ -1253,9 +1286,11 @@ green_dealloc(PyGreenlet* self)
+ Py_CLEAR(self->context);
+ #endif
+ #if GREENLET_PY37
+- Py_CLEAR(self->exc_state.exc_type);
+ Py_CLEAR(self->exc_state.exc_value);
++#if !GREENLET_PY311
++ Py_CLEAR(self->exc_state.exc_type);
+ Py_CLEAR(self->exc_state.exc_traceback);
++#endif
+ #else
+ Py_CLEAR(self->exc_type);
+ Py_CLEAR(self->exc_value);
+--- a/src/greenlet/greenlet.h
++++ b/src/greenlet/greenlet.h
+@@ -14,6 +14,15 @@ extern "C" {
+ /* This is deprecated and undocumented. It does not change. */
+ #define GREENLET_VERSION "1.0.0"
+
++#if PY_VERSION_HEX >= 0x30B00A6
++# define GREENLET_PY311 1
++ /* _PyInterpreterFrame moved to the internal C API in Python 3.11 */
++# include <internal/pycore_frame.h>
++#else
++# define GREENLET_PY311 0
++# define _PyCFrame CFrame
++#endif
++
+ typedef struct _greenlet {
+ PyObject_HEAD
+ char* stack_start;
+@@ -25,6 +34,12 @@ typedef struct _greenlet {
+ PyObject* run_info;
+ struct _frame* top_frame;
+ int recursion_depth;
++#if GREENLET_PY311
++ _PyInterpreterFrame *current_frame;
++ _PyStackChunk *datastack_chunk;
++ PyObject **datastack_top;
++ PyObject **datastack_limit;
++#endif
+ PyObject* weakreflist;
+ #if PY_VERSION_HEX >= 0x030700A3
+ _PyErr_StackItem* exc_info;
+@@ -39,7 +54,7 @@ typedef struct _greenlet {
+ PyObject* context;
+ #endif
+ #if PY_VERSION_HEX >= 0x30A00B1
+- CFrame* cframe;
++ _PyCFrame* cframe;
+ #endif
+ } PyGreenlet;
+
+--- a/tox.ini
++++ b/tox.ini
+@@ -1,6 +1,6 @@
+ [tox]
+ envlist =
+- py27,py35,py36,py37,py38,py39,py310,docs
++ py27,py35,py36,py37,py38,py39,py310,py311,docs
+
+ [testenv]
+ commands =