From 0418516101d92159f74e69fdd1c29010db71c5cc Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 4 Nov 2022 11:11:58 -0400 Subject: [PATCH 01/12] Fix #323: Support Python 3.12 --- src/greenlet/greenlet_cpython_compat.hpp | 6 ++++++ src/greenlet/greenlet_greenlet.hpp | 12 +++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/greenlet/greenlet_cpython_compat.hpp b/src/greenlet/greenlet_cpython_compat.hpp index 3fd13ac..6210586 100644 --- a/src/greenlet/greenlet_cpython_compat.hpp +++ b/src/greenlet/greenlet_cpython_compat.hpp @@ -48,6 +48,12 @@ We have to save and restore this as well. # define GREENLET_USE_CFRAME 0 #endif +#if PY_VERSION_HEX >= 0x30C0000 +# define GREENLET_PY312 1 +#else +# define GREENLET_PY312 0 +#endif + #if PY_VERSION_HEX >= 0x30B00A4 /* Greenlet won't compile on anything older than Python 3.11 alpha 4 (see diff --git a/src/greenlet/greenlet_greenlet.hpp b/src/greenlet/greenlet_greenlet.hpp index cc02c5c..472902e 100644 --- a/src/greenlet/greenlet_greenlet.hpp +++ b/src/greenlet/greenlet_greenlet.hpp @@ -831,7 +831,11 @@ void PythonState::operator<<(const PyThreadState *const tstate) G_NOEXCEPT this->use_tracing = tstate->cframe->use_tracing; #endif #if GREENLET_PY311 + #if GREENLET_PY312 + this->recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; + #else this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; + #endif this->current_frame = tstate->cframe->current_frame; this->datastack_chunk = tstate->datastack_chunk; this->datastack_top = tstate->datastack_top; @@ -867,7 +871,11 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT tstate->cframe->use_tracing = this->use_tracing; #endif #if GREENLET_PY311 + #if GREENLET_PY312 + tstate->py_recursion_remaining = tstate->py_recursion_limit - this->recursion_depth; + #else tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth; + #endif tstate->cframe->current_frame = this->current_frame; tstate->datastack_chunk = this->datastack_chunk; tstate->datastack_top = this->datastack_top; @@ -895,7 +903,9 @@ void PythonState::will_switch_from(PyThreadState *const origin_tstate) G_NOEXCEP void PythonState::set_initial_state(const PyThreadState* const tstate) G_NOEXCEPT { this->_top_frame = nullptr; -#if GREENLET_PY311 +#if GREENLET_PY312 + this->recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; +#elif GREENLET_PY311 this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; #else this->recursion_depth = tstate->recursion_depth; From 5c76aeda3709cafc8afe656ed7fa284369059d98 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 4 Nov 2022 12:53:37 -0400 Subject: [PATCH 02/12] Fix 3.12 testing --- .github/workflows/tests.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 27c91e0..237a85b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,15 +25,23 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11"] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12.0~a1"] # Jan 2023: We have pinned back from ubuntu-latest (which is # now ubuntu 22.04) because older Python versions like # 3.5, 3.6 and presumably 2.7 are not available in it. - os: [ubuntu-20.04, macos-latest] + os: [ubuntu-latest, macos-latest] + exclude: + - os: macos-latest + python-version: 3.12.0~a1 steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 + if: "!contains(matrix.python-version, '~')" + with: + python-version: ${{ matrix.python-version }} + - uses: deadsnakes/action@v2.1.1 + if: "contains(matrix.python-version, '~')" with: python-version: ${{ matrix.python-version }} cache: 'pip' From dbe67e389158a5120bcaee857ce9df8d8e20240f Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 4 Nov 2022 12:56:25 -0400 Subject: [PATCH 03/12] Try a different way to specify version --- .github/workflows/tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 237a85b..7d3c3d4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,23 +25,23 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12.0~a1"] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12"] # Jan 2023: We have pinned back from ubuntu-latest (which is # now ubuntu 22.04) because older Python versions like # 3.5, 3.6 and presumably 2.7 are not available in it. os: [ubuntu-latest, macos-latest] exclude: - os: macos-latest - python-version: 3.12.0~a1 + python-version: 3.12 steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 - if: "!contains(matrix.python-version, '~')" + if: "!equals(matrix.python-version, '3.12')" with: python-version: ${{ matrix.python-version }} - uses: deadsnakes/action@v2.1.1 - if: "contains(matrix.python-version, '~')" + if: "equals(matrix.python-version, '3.12')" with: python-version: ${{ matrix.python-version }} cache: 'pip' From 8d0cb88cfba16226e5a5936b3f48d838a15fbe28 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Fri, 4 Nov 2022 14:20:47 -0400 Subject: [PATCH 04/12] Fix syntax --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7d3c3d4..90897af 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,11 +37,11 @@ jobs: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 - if: "!equals(matrix.python-version, '3.12')" + if: "matrix.python-version != '3.12'" with: python-version: ${{ matrix.python-version }} - uses: deadsnakes/action@v2.1.1 - if: "equals(matrix.python-version, '3.12')" + if: "matrix.python-version == '3.12'" with: python-version: ${{ matrix.python-version }} cache: 'pip' From 51a334e65dafb171742f5a715ad89c3116900c04 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Nov 2022 09:14:29 -0500 Subject: [PATCH 05/12] Use 3.12-dev instead of deadsnakes Co-authored-by: Andreas Motl --- .github/workflows/tests.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 90897af..060cc7f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,23 +25,18 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12"] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9, "3.10", "3.11", "3.12-dev"] # Jan 2023: We have pinned back from ubuntu-latest (which is # now ubuntu 22.04) because older Python versions like # 3.5, 3.6 and presumably 2.7 are not available in it. os: [ubuntu-latest, macos-latest] exclude: - os: macos-latest - python-version: 3.12 + python-version: 3.12-dev steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 - if: "matrix.python-version != '3.12'" - with: - python-version: ${{ matrix.python-version }} - - uses: deadsnakes/action@v2.1.1 - if: "matrix.python-version == '3.12'" with: python-version: ${{ matrix.python-version }} cache: 'pip' From 387dee06179373e53b2d42447ea88f2acdcd2d1f Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 27 Apr 2023 09:52:14 -0400 Subject: [PATCH 06/12] Updates for PEP669 --- src/greenlet/greenlet.cpp | 4 ++++ src/greenlet/greenlet_greenlet.hpp | 15 +++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/greenlet/greenlet.cpp b/src/greenlet/greenlet.cpp index 1d6ddaa..b382c5a 100644 --- a/src/greenlet/greenlet.cpp +++ b/src/greenlet/greenlet.cpp @@ -3092,7 +3092,11 @@ static PyObject* mod_get_tstate_trash_delete_nesting(PyObject* UNUSED(module)) { PyThreadState* tstate = PyThreadState_GET(); +#if GREENLET_PY312 + return PyLong_FromLong(tstate->trash.delete_nesting); +#else return PyLong_FromLong(tstate->trash_delete_nesting); +#endif } static PyMethodDef GreenMethods[] = { diff --git a/src/greenlet/greenlet_greenlet.hpp b/src/greenlet/greenlet_greenlet.hpp index 472902e..7146214 100644 --- a/src/greenlet/greenlet_greenlet.hpp +++ b/src/greenlet/greenlet_greenlet.hpp @@ -828,7 +828,9 @@ void PythonState::operator<<(const PyThreadState *const tstate) G_NOEXCEPT the switch, use `will_switch_from`. */ this->cframe = tstate->cframe; + #if !GREENLET_PY312 this->use_tracing = tstate->cframe->use_tracing; + #endif #endif #if GREENLET_PY311 #if GREENLET_PY312 @@ -843,13 +845,12 @@ void PythonState::operator<<(const PyThreadState *const tstate) G_NOEXCEPT PyFrameObject *frame = PyThreadState_GetFrame((PyThreadState *)tstate); Py_XDECREF(frame); // PyThreadState_GetFrame gives us a new reference. this->_top_frame.steal(frame); + this->trash_delete_nesting = tstate->trash.delete_nesting; #else this->recursion_depth = tstate->recursion_depth; this->_top_frame.steal(tstate->frame); -#endif - - // All versions of Python. this->trash_delete_nesting = tstate->trash_delete_nesting; +#endif } void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT @@ -868,7 +869,9 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT root_cframe here. See note above about why we can't just copy this from ``origin->cframe->use_tracing``. */ + #if !GREENLET_PY312 tstate->cframe->use_tracing = this->use_tracing; + #endif #endif #if GREENLET_PY311 #if GREENLET_PY312 @@ -881,17 +884,17 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT tstate->datastack_top = this->datastack_top; tstate->datastack_limit = this->datastack_limit; this->_top_frame.relinquish_ownership(); + tstate->trash.delete_nesting = this->trash_delete_nesting; #else tstate->frame = this->_top_frame.relinquish_ownership(); tstate->recursion_depth = this->recursion_depth; + tstate->trash.delete_nesting = this->trash_delete_nesting; #endif - // All versions of Python. - tstate->trash_delete_nesting = this->trash_delete_nesting; } void PythonState::will_switch_from(PyThreadState *const origin_tstate) G_NOEXCEPT { -#if GREENLET_USE_CFRAME +#if GREENLET_USE_CFRAME && !GREENLET_PY312 // The weird thing is, we don't actually save this for an // effect on the current greenlet, it's saved for an // effect on the target greenlet. That is, we want From db74f88454dd36c3c6769bec680a16a1ac284b96 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 27 Apr 2023 09:54:50 -0400 Subject: [PATCH 07/12] Fix Python 3.11 --- src/greenlet/greenlet_greenlet.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/greenlet/greenlet_greenlet.hpp b/src/greenlet/greenlet_greenlet.hpp index 7146214..41fda8e 100644 --- a/src/greenlet/greenlet_greenlet.hpp +++ b/src/greenlet/greenlet_greenlet.hpp @@ -845,7 +845,11 @@ void PythonState::operator<<(const PyThreadState *const tstate) G_NOEXCEPT PyFrameObject *frame = PyThreadState_GetFrame((PyThreadState *)tstate); Py_XDECREF(frame); // PyThreadState_GetFrame gives us a new reference. this->_top_frame.steal(frame); + #if GREENLET_PY312 this->trash_delete_nesting = tstate->trash.delete_nesting; + #else + this->trash_delete_nesting = tstate->trash_delete_nesting; + #endif #else this->recursion_depth = tstate->recursion_depth; this->_top_frame.steal(tstate->frame); @@ -884,7 +888,11 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT tstate->datastack_top = this->datastack_top; tstate->datastack_limit = this->datastack_limit; this->_top_frame.relinquish_ownership(); + #if GREENLET_PY312 tstate->trash.delete_nesting = this->trash_delete_nesting; + #else + tstate->trash_delete_nesting = this->trash_delete_nesting; + #endif #else tstate->frame = this->_top_frame.relinquish_ownership(); tstate->recursion_depth = this->recursion_depth; From 132c4616f38e3c05899da1be22086d96e4981057 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 27 Apr 2023 09:56:56 -0400 Subject: [PATCH 08/12] Revert ubuntu-latest change --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 060cc7f..fa48066 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: # Jan 2023: We have pinned back from ubuntu-latest (which is # now ubuntu 22.04) because older Python versions like # 3.5, 3.6 and presumably 2.7 are not available in it. - os: [ubuntu-latest, macos-latest] + os: [ubuntu-20.04, macos-latest] exclude: - os: macos-latest python-version: 3.12-dev From d26952ec3fb74c1f1d68104a4ac80018deb0618c Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 27 Apr 2023 09:58:22 -0400 Subject: [PATCH 09/12] Fix legacy versions --- src/greenlet/greenlet_greenlet.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/greenlet/greenlet_greenlet.hpp b/src/greenlet/greenlet_greenlet.hpp index 41fda8e..ffb23a7 100644 --- a/src/greenlet/greenlet_greenlet.hpp +++ b/src/greenlet/greenlet_greenlet.hpp @@ -896,7 +896,7 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT #else tstate->frame = this->_top_frame.relinquish_ownership(); tstate->recursion_depth = this->recursion_depth; - tstate->trash.delete_nesting = this->trash_delete_nesting; + tstate->trash_delete_nesting = this->trash_delete_nesting; #endif } From 82f9a8869d88616decb777bc6afae3a751a4a9c0 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Thu, 27 Apr 2023 17:29:10 -0400 Subject: [PATCH 10/12] Print precise Python version --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fa48066..aa14318 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -80,6 +80,7 @@ jobs: path: dist/*whl - name: Test run: | + python -VV python -c 'import greenlet._greenlet as G; assert G.GREENLET_USE_STANDARD_THREADING' python -m unittest discover -v greenlet.tests - name: Doctest From 3629e46c49533a994aa8f12ed3b41ae6725ab2ce Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 2 May 2023 10:48:37 -0400 Subject: [PATCH 11/12] Fix recursion depth updating --- src/greenlet/greenlet_greenlet.hpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/greenlet/greenlet_greenlet.hpp b/src/greenlet/greenlet_greenlet.hpp index ffb23a7..10244e0 100644 --- a/src/greenlet/greenlet_greenlet.hpp +++ b/src/greenlet/greenlet_greenlet.hpp @@ -143,7 +143,12 @@ namespace greenlet _PyCFrame* cframe; int use_tracing; #endif +#if GREENLET_PY312 + int py_recursion_depth; + int c_recursion_depth; +#else int recursion_depth; +#endif int trash_delete_nesting; #if GREENLET_PY311 _PyInterpreterFrame* current_frame; @@ -748,7 +753,12 @@ PythonState::PythonState() ,cframe(nullptr) ,use_tracing(0) #endif +#if GREENLET_PY312 + ,py_recursion_depth(0) + ,c_recursion_depth(0) +#else ,recursion_depth(0) +#endif ,trash_delete_nesting(0) #if GREENLET_PY311 ,current_frame(nullptr) @@ -834,7 +844,8 @@ void PythonState::operator<<(const PyThreadState *const tstate) G_NOEXCEPT #endif #if GREENLET_PY311 #if GREENLET_PY312 - this->recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; + this->py_recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; + this->c_recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining; #else this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; #endif @@ -879,7 +890,8 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT #endif #if GREENLET_PY311 #if GREENLET_PY312 - tstate->py_recursion_remaining = tstate->py_recursion_limit - this->recursion_depth; + tstate->py_recursion_remaining = tstate->py_recursion_limit - this->py_recursion_depth; + tstate->c_recursion_remaining = C_RECURSION_LIMIT - this->c_recursion_depth; #else tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth; #endif @@ -915,7 +927,8 @@ void PythonState::set_initial_state(const PyThreadState* const tstate) G_NOEXCEP { this->_top_frame = nullptr; #if GREENLET_PY312 - this->recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; + this->py_recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; + this->c_recursion_depth = tstate->py_recursion_limit - tstate->py_recursion_remaining; #elif GREENLET_PY311 this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; #else From 6bba85fdfd0acd1484780fae7a537e3dac99c067 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 30 May 2023 12:14:22 -0400 Subject: [PATCH 12/12] Insert blank line --- src/greenlet/greenlet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/greenlet/greenlet.cpp b/src/greenlet/greenlet.cpp index b382c5a..677fce8 100644 --- a/src/greenlet/greenlet.cpp +++ b/src/greenlet/greenlet.cpp @@ -3092,6 +3092,7 @@ static PyObject* mod_get_tstate_trash_delete_nesting(PyObject* UNUSED(module)) { PyThreadState* tstate = PyThreadState_GET(); + #if GREENLET_PY312 return PyLong_FromLong(tstate->trash.delete_nesting); #else