diff --git a/.python-greenlet.metadata b/.python-greenlet.metadata index 20a20c2..993d308 100644 --- a/.python-greenlet.metadata +++ b/.python-greenlet.metadata @@ -1 +1 @@ -105fcc7bae9e388e4b9a05b7c431ad2a637a0f75 SOURCES/greenlet-0.4.13.tar.gz +1c1e3dc2f4cb4522ad8195113b908b537be51c70 SOURCES/greenlet-3.0.1.tar.gz diff --git a/SOURCES/.gitignore b/SOURCES/.gitignore new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/SOURCES/.gitignore diff --git a/SOURCES/327.patch b/SOURCES/327.patch new file mode 100644 index 0000000..31a0bec --- /dev/null +++ b/SOURCES/327.patch @@ -0,0 +1,503 @@ +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 diff --git a/SOURCES/skip-leak-checks.patch b/SOURCES/skip-leak-checks.patch new file mode 100644 index 0000000..83228d5 --- /dev/null +++ b/SOURCES/skip-leak-checks.patch @@ -0,0 +1,291 @@ +diff -rU3 greenlet-2.0.2-orig/src/greenlet/tests/leakcheck.py greenlet-2.0.2/src/greenlet/tests/leakcheck.py +--- greenlet-2.0.2-orig/src/greenlet/tests/leakcheck.py 2023-01-28 15:19:12.000000000 +0100 ++++ greenlet-2.0.2/src/greenlet/tests/leakcheck.py 2023-06-14 17:49:32.395412453 +0200 +@@ -30,39 +30,7 @@ + from functools import wraps + import unittest + +- +-import objgraph +- +-# graphviz 0.18 (Nov 7 2021), available only on Python 3.6 and newer, +-# has added type hints (sigh). It wants to use ``typing.Literal`` for +-# some stuff, but that's only available on Python 3.9+. If that's not +-# found, it creates a ``unittest.mock.MagicMock`` object and annotates +-# with that. These are GC'able objects, and doing almost *anything* +-# with them results in an explosion of objects. For example, trying to +-# compare them for equality creates new objects. This causes our +-# leakchecks to fail, with reports like: +-# +-# greenlet.tests.leakcheck.LeakCheckError: refcount increased by [337, 1333, 343, 430, 530, 643, 769] +-# _Call 1820 +546 +-# dict 4094 +76 +-# MagicProxy 585 +73 +-# tuple 2693 +66 +-# _CallList 24 +3 +-# weakref 1441 +1 +-# function 5996 +1 +-# type 736 +1 +-# cell 592 +1 +-# MagicMock 8 +1 +-# +-# To avoid this, we *could* filter this type of object out early. In +-# principle it could leak, but we don't use mocks in greenlet, so it +-# doesn't leak from us. However, a further issue is that ``MagicMock`` +-# objects have subobjects that are also GC'able, like ``_Call``, and +-# those create new mocks of their own too. So we'd have to filter them +-# as well, and they're not public. That's OK, we can workaround the +-# problem by being very careful to never compare by equality or other +-# user-defined operators, only using object identity or other builtin +-# functions. ++# Edited for Fedora to avoid missing dependency + + RUNNING_ON_GITHUB_ACTIONS = os.environ.get('GITHUB_ACTIONS') + RUNNING_ON_TRAVIS = os.environ.get('TRAVIS') or RUNNING_ON_GITHUB_ACTIONS +@@ -74,53 +42,15 @@ + ONLY_FAILING_LEAKCHECKS = os.environ.get('GREENLET_ONLY_FAILING_LEAKCHECKS') + + def ignores_leakcheck(func): +- """ +- Ignore the given object during leakchecks. +- +- Can be applied to a method, in which case the method will run, but +- will not be subject to leak checks. +- +- If applied to a class, the entire class will be skipped during leakchecks. This +- is intended to be used for classes that are very slow and cause problems such as +- test timeouts; typically it will be used for classes that are subclasses of a base +- class and specify variants of behaviour (such as pool sizes). +- """ +- func.ignore_leakcheck = True + return func + + def fails_leakcheck(func): +- """ +- Mark that the function is known to leak. +- """ +- func.fails_leakcheck = True +- if SKIP_FAILING_LEAKCHECKS: +- func = unittest.skip("Skipping known failures")(func) + return func + + class LeakCheckError(AssertionError): + pass + +-if hasattr(sys, 'getobjects'): +- # In a Python build with ``--with-trace-refs``, make objgraph +- # trace *all* the objects, not just those that are tracked by the +- # GC +- class _MockGC(object): +- def get_objects(self): +- return sys.getobjects(0) # pylint:disable=no-member +- def __getattr__(self, name): +- return getattr(gc, name) +- objgraph.gc = _MockGC() +- fails_strict_leakcheck = fails_leakcheck +-else: +- def fails_strict_leakcheck(func): +- """ +- Decorator for a function that is known to fail when running +- strict (``sys.getobjects()``) leakchecks. +- +- This type of leakcheck finds all objects, even those, such as +- strings, which are not tracked by the garbage collector. +- """ +- return func ++fails_strict_leakcheck = fails_leakcheck + + class ignores_types_in_strict_leakcheck(object): + def __init__(self, types): +@@ -129,190 +59,5 @@ + func.leakcheck_ignore_types = self.types + return func + +-class _RefCountChecker(object): +- +- # Some builtin things that we ignore +- # XXX: Those things were ignored by gevent, but they're important here, +- # presumably. +- IGNORED_TYPES = () #(tuple, dict, types.FrameType, types.TracebackType) +- +- def __init__(self, testcase, function): +- self.testcase = testcase +- self.function = function +- self.deltas = [] +- self.peak_stats = {} +- self.ignored_types = () +- +- # The very first time we are called, we have already been +- # self.setUp() by the test runner, so we don't need to do it again. +- self.needs_setUp = False +- +- def _include_object_p(self, obj): +- # pylint:disable=too-many-return-statements +- # +- # See the comment block at the top. We must be careful to +- # avoid invoking user-defined operations. +- if obj is self: +- return False +- kind = type(obj) +- # ``self._include_object_p == obj`` returns NotImplemented +- # for non-function objects, which causes the interpreter +- # to try to reverse the order of arguments...which leads +- # to the explosion of mock objects. We don't want that, so we implement +- # the check manually. +- if kind == type(self._include_object_p): +- try: +- # pylint:disable=not-callable +- exact_method_equals = self._include_object_p.__eq__(obj) +- except AttributeError: +- # Python 2.7 methods may only have __cmp__, and that raises a +- # TypeError for non-method arguments +- # pylint:disable=no-member +- exact_method_equals = self._include_object_p.__cmp__(obj) == 0 +- +- if exact_method_equals is not NotImplemented and exact_method_equals: +- return False +- +- # Similarly, we need to check identity in our __dict__ to avoid mock explosions. +- for x in self.__dict__.values(): +- if obj is x: +- return False +- +- +- if kind in self.ignored_types or kind in self.IGNORED_TYPES: +- return False +- +- return True +- +- def _growth(self): +- return objgraph.growth(limit=None, peak_stats=self.peak_stats, +- filter=self._include_object_p) +- +- def _report_diff(self, growth): +- if not growth: +- return "" +- +- lines = [] +- width = max(len(name) for name, _, _ in growth) +- for name, count, delta in growth: +- lines.append('%-*s%9d %+9d' % (width, name, count, delta)) +- +- diff = '\n'.join(lines) +- return diff +- +- +- def _run_test(self, args, kwargs): +- gc_enabled = gc.isenabled() +- gc.disable() +- +- if self.needs_setUp: +- self.testcase.setUp() +- self.testcase.skipTearDown = False +- try: +- self.function(self.testcase, *args, **kwargs) +- finally: +- self.testcase.tearDown() +- self.testcase.doCleanups() +- self.testcase.skipTearDown = True +- self.needs_setUp = True +- if gc_enabled: +- gc.enable() +- +- def _growth_after(self): +- # Grab post snapshot +- if 'urlparse' in sys.modules: +- sys.modules['urlparse'].clear_cache() +- if 'urllib.parse' in sys.modules: +- sys.modules['urllib.parse'].clear_cache() +- +- return self._growth() +- +- def _check_deltas(self, growth): +- # Return false when we have decided there is no leak, +- # true if we should keep looping, raises an assertion +- # if we have decided there is a leak. +- +- deltas = self.deltas +- if not deltas: +- # We haven't run yet, no data, keep looping +- return True +- +- if gc.garbage: +- raise LeakCheckError("Generated uncollectable garbage %r" % (gc.garbage,)) +- +- +- # the following configurations are classified as "no leak" +- # [0, 0] +- # [x, 0, 0] +- # [... a, b, c, d] where a+b+c+d = 0 +- # +- # the following configurations are classified as "leak" +- # [... z, z, z] where z > 0 +- +- if deltas[-2:] == [0, 0] and len(deltas) in (2, 3): +- return False +- +- if deltas[-3:] == [0, 0, 0]: +- return False +- +- if len(deltas) >= 4 and sum(deltas[-4:]) == 0: +- return False +- +- if len(deltas) >= 3 and deltas[-1] > 0 and deltas[-1] == deltas[-2] and deltas[-2] == deltas[-3]: +- diff = self._report_diff(growth) +- raise LeakCheckError('refcount increased by %r\n%s' % (deltas, diff)) +- +- # OK, we don't know for sure yet. Let's search for more +- if sum(deltas[-3:]) <= 0 or sum(deltas[-4:]) <= 0 or deltas[-4:].count(0) >= 2: +- # this is suspicious, so give a few more runs +- limit = 11 +- else: +- limit = 7 +- if len(deltas) >= limit: +- raise LeakCheckError('refcount increased by %r\n%s' +- % (deltas, +- self._report_diff(growth))) +- +- # We couldn't decide yet, keep going +- return True +- +- def __call__(self, args, kwargs): +- for _ in range(3): +- gc.collect() +- +- expect_failure = getattr(self.function, 'fails_leakcheck', False) +- if expect_failure: +- self.testcase.expect_greenlet_leak = True +- self.ignored_types = getattr(self.function, "leakcheck_ignore_types", ()) +- +- # Capture state before; the incremental will be +- # updated by each call to _growth_after +- growth = self._growth() +- +- try: +- while self._check_deltas(growth): +- self._run_test(args, kwargs) +- +- growth = self._growth_after() +- +- self.deltas.append(sum((stat[2] for stat in growth))) +- except LeakCheckError: +- if not expect_failure: +- raise +- else: +- if expect_failure: +- raise LeakCheckError("Expected %s to leak but it did not." % (self.function,)) +- + def wrap_refcount(method): +- if getattr(method, 'ignore_leakcheck', False) or SKIP_LEAKCHECKS: +- return method +- +- @wraps(method) +- def wrapper(self, *args, **kwargs): # pylint:disable=too-many-branches +- if getattr(self, 'ignore_leakcheck', False): +- raise unittest.SkipTest("This class ignored during leakchecks") +- if ONLY_FAILING_LEAKCHECKS and not getattr(method, 'fails_leakcheck', False): +- raise unittest.SkipTest("Only running tests that fail leakchecks.") +- return _RefCountChecker(self, method)(args, kwargs) +- +- return wrapper ++ return method diff --git a/SPECS/python-greenlet.spec b/SPECS/python-greenlet.spec index 07905ea..26ecd3c 100644 --- a/SPECS/python-greenlet.spec +++ b/SPECS/python-greenlet.spec @@ -1,21 +1,17 @@ -%if 0%{?rhel} > 7 -# Disable python2 build by default -%bcond_with python2 -%else -%bcond_without python2 -%endif - %global modname greenlet Name: python-%{modname} -Version: 0.4.13 -Release: 4%{?dist} +Version: 3.0.1 +Release: 1%{?dist} Summary: Lightweight in-process concurrent programming -License: MIT +License: MIT AND PSF-2.0 URL: https://github.com/python-greenlet/greenlet Source0: %{url}/archive/%{version}/%{modname}-%{version}.tar.gz -# https://github.com/python-greenlet/greenlet/pull/120 -Patch0001: 0001-Don-t-clobber-r2-register-on-ppc64el.patch + +# Skip leak checking to avoid a missing dependency, `objgraph` +Patch: skip-leak-checks.patch + +BuildRequires: gcc-c++ %global _description \ The greenlet package is a spin-off of Stackless, a version of CPython\ @@ -25,43 +21,19 @@ and are synchronized with data exchanges on "channels". %description %{_description} -%if %{with python2} -%package -n python2-%{modname} -Summary: %{summary} -%{?python_provide:%python_provide python2-%{modname}} -BuildRequires: python2-devel -BuildRequires: python2-setuptools - -%description -n python2-%{modname} %{_description} - -Python 2 version. -%endif # with python2 - %package -n python3-%{modname} Summary: %{summary} -%{?python_provide:%python_provide python3-%{modname}} BuildRequires: python3-devel -BuildRequires: python3-setuptools +BuildRequires: pyproject-rpm-macros +# For tests +BuildRequires: python3-psutil %description -n python3-%{modname} %{_description} Python 3 version. -%if %{with python2} -%package -n python2-%{modname}-devel -Summary: C development headers for python2-%{modname} -%{?python_provide:%python_provide python2-%{modname}-devel} -Requires: python2-%{modname}%{?_isa} = %{?epoch:%{epoch}:}%{version}-%{release} - -%description -n python2-%{modname}-devel -%{summary}. - -Python 2 version. -%endif # with python2 - %package -n python3-%{modname}-devel Summary: C development headers for python3-%{modname} -%{?python_provide:%python_provide python3-%{modname}-devel} Requires: python3-%{modname}%{?_isa} = %{?epoch:%{epoch}:}%{version}-%{release} %description -n python3-%{modname}-devel @@ -72,51 +44,138 @@ Python 3 version. %prep %autosetup -n %{modname}-%{version} -p1 +%generate_buildrequires +%pyproject_buildrequires + %build -%if %{with python2} -%py2_build -%endif # with python2 -%py3_build +%pyproject_wheel %install -%if %{with python2} -%py2_install -%endif # with python2 -%py3_install - +%pyproject_install +%pyproject_save_files %{modname} + %check -%if %{with python2} -%{__python2} setup.py test -%endif # with python2 -%{__python3} setup.py test - -%if %{with python2} -%files -n python2-%{modname} -%license LICENSE LICENSE.PSF -%doc AUTHORS NEWS README.rst -%{python2_sitearch}/%{modname}-*.egg-info -%{python2_sitearch}/%{modname}.so - -%files -n python2-%{modname}-devel -%{_includedir}/python%{python2_version}*/%{modname}/ -%endif # with python2 - -%files -n python3-%{modname} -%license LICENSE LICENSE.PSF -%doc AUTHORS NEWS README.rst -%{python3_sitearch}/%{modname}-*.egg-info -%{python3_sitearch}/%{modname}*.so +cd / +PYTHONPATH="%{buildroot}%{python3_sitearch}" \ + %{python3} -m unittest discover -v \ + -s "%{buildroot}%{python3_sitearch}/greenlet/tests" \ + -t "%{buildroot}%{python3_sitearch}" + +%files -n python3-%{modname} -f %{pyproject_files} +%doc AUTHORS README.rst %files -n python3-greenlet-devel %{_includedir}/python%{python3_version}*/%{modname}/ %changelog -* Thu Nov 07 2019 Brian C. Lane - 0.4.13-4 -- Add gating tests - Resolves: rhbz#1682344 +* Sat Nov 25 2023 Terje Rosten - 3.0.1-1 +- 3.0.1 + +* Sat Oct 14 2023 Terje Rosten - 3.0.0-1 +- 3.0.0 + +* Wed Sep 06 2023 Carl George - 3.0.0~rc1-1 +- Update to version 3.0.0rc1 +- Convert to pyproject macros + +* Sun Aug 13 2023 Orion Poplawski - 3.0.0~a1-1 +- Update to 3.0.0a1 + +* Sat Aug 05 2023 Ondřej Budai - 2.0.2-3 +- SPDX migration + +* Fri Jul 21 2023 Fedora Release Engineering - 2.0.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Wed Jun 14 2023 Petr Viktorin - 2.0.2-1 +- Update to upstream version 2.0.2 +- Update patch for Python 3.12 compatibility +- Skip leak checks for now + +* Tue Jun 13 2023 Python Maint - 1.1.3-3 +- Rebuilt for Python 3.12 + +* Fri Jan 20 2023 Fedora Release Engineering - 1.1.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Fri Oct 14 2022 Lumír Balhar - 1.1.3-1 +- Update to 1.1.3 + +* Fri Jul 22 2022 Fedora Release Engineering - 1.1.2-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Mon Jun 13 2022 Python Maint - 1.1.2-4 +- Rebuilt for Python 3.11 + +* Wed Jun 01 2022 Miro Hrončok - 1.1.2-3 +- Python 3.11 support +- Fixes: rhbz#2040186 + +* Fri Jan 21 2022 Fedora Release Engineering - 1.1.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Thu Sep 30 2021 Kevin Fenzi - 1.1.2-1 +- Update to 1.1.2. Fixes rhbz#2008848 + +* Sat Aug 07 2021 Kevin Fenzi - 1.1.1-1 +- Update to 1.1.1. +- Fixes rhbz#1990901 + +* Fri Jul 23 2021 Fedora Release Engineering - 1.1.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Thu Jun 03 2021 Python Maint - 1.1.0-2 +- Rebuilt for Python 3.10 + +* Mon May 10 2021 Nils Philippsen - 1.1.0-1 +- Update to 1.1.0 + +* Wed Jan 27 2021 Fedora Release Engineering - 0.4.17-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Sat Oct 31 2020 Kevin Fenzi - 0.4.17-1 +- Update to 0.4.17. Fixes bug #1881455 + +* Wed Jul 29 2020 Fedora Release Engineering - 0.4.16-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Sat Jun 06 2020 Orion Poplawski - 0.4.16-1 +- Update to 0.4.16 + +* Sat May 23 2020 Miro Hrončok - 0.4.14-8 +- Rebuilt for Python 3.9 + +* Thu May 21 2020 Miro Hrončok - 0.4.14-7 +- Fix Python 3.9 build + +* Thu Jan 30 2020 Fedora Release Engineering - 0.4.14-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Sep 26 2019 Miro Hrončok - 0.4.14-5 +- Subpackages python2-greenlet, python2-greenlet-devel have been removed + See https://fedoraproject.org/wiki/Changes/Mass_Python_2_Package_Removal + +* Fri Aug 16 2019 Miro Hrončok - 0.4.14-4 +- Rebuilt for Python 3.8 + +* Fri Jul 26 2019 Fedora Release Engineering - 0.4.14-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sat Feb 02 2019 Fedora Release Engineering - 0.4.14-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jul 18 2018 Kevin Fenzi - 0.4.14-1 +- Update to 0.4.14. +- Drop upstreamed/no longer needed patches. + +* Sat Jul 14 2018 Fedora Release Engineering - 0.4.13-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jul 03 2018 Miro Hrončok - 0.4.13-4 +- Add fix for Python 3.7 -* Wed Jul 18 2018 Charalampos Stratakis - 0.4.13-3 -- Conditionalize the python2 subpackage +* Sat Jun 16 2018 Miro Hrončok - 0.4.13-3 +- Rebuilt for Python 3.7 * Fri Feb 09 2018 Fedora Release Engineering - 0.4.13-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild