Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-greenlet for openSUSE:Factory 
checked in at 2025-09-02 17:58:00
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-greenlet (Old)
 and      /work/SRC/openSUSE:Factory/.python-greenlet.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-greenlet"

Tue Sep  2 17:58:00 2025 rev:55 rq:1302236 version:3.2.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-greenlet/python-greenlet.changes  
2025-06-14 16:17:15.933119463 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-greenlet.new.1977/python-greenlet.changes    
    2025-09-02 17:58:07.169983962 +0200
@@ -1,0 +2,13 @@
+Mon Sep  1 12:37:08 UTC 2025 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- Update to 3.2.4
+  * Various small build/test changes for less common configurations (e.g.,
+    building CPython with assertions enabled but NOT debugging),
+    contributed by Michał Górny. Note that while greenlet will BUILD in
+    a free-threaded Python, it will cause the GIL to be allocated and
+    used, and memory may leak. Also note that these configurations
+    are not tested by this project's CI.
+  * Fix an assertion error on debug builds of Python 3.14 when using the
+    experimental JIT. See PR 460.
+
+-------------------------------------------------------------------

Old:
----
  greenlet-3.2.3.tar.gz

New:
----
  greenlet-3.2.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-greenlet.spec ++++++
--- /var/tmp/diff_new_pack.MBgYLb/_old  2025-09-02 17:58:07.830011737 +0200
+++ /var/tmp/diff_new_pack.MBgYLb/_new  2025-09-02 17:58:07.830011737 +0200
@@ -22,7 +22,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-greenlet
-Version:        3.2.3
+Version:        3.2.4
 Release:        0
 Summary:        Lightweight in-process concurrent programming
 License:        MIT

++++++ greenlet-3.2.3.tar.gz -> greenlet-3.2.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/.github/workflows/tests.yml 
new/greenlet-3.2.4/.github/workflows/tests.yml
--- old/greenlet-3.2.3/.github/workflows/tests.yml      2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/.github/workflows/tests.yml      2025-08-07 
15:13:36.000000000 +0200
@@ -22,7 +22,7 @@
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        python-version: [3.9, "3.10", "3.11", "3.12", "3.13", "3.14.0-beta.2"]
+        python-version: [3.9, "3.10", "3.11", "3.12", "3.13", "3.14.0-rc.1"]
         # Recall the macOS builds upload built wheels so all supported versions
         # need to run on mac.
         os: [ubuntu-latest, macos-latest]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/CHANGES.rst 
new/greenlet-3.2.4/CHANGES.rst
--- old/greenlet-3.2.3/CHANGES.rst      2025-06-05 18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/CHANGES.rst      2025-08-07 15:13:36.000000000 +0200
@@ -2,6 +2,24 @@
  Changes
 =========
 
+3.2.4 (2025-08-07)
+==================
+
+.. note::
+
+   The 3.2.x series will be the last to support Python 3.9.
+
+- Various small build/test changes for less common configurations (e.g.,
+  building CPython with assertions enabled but NOT debugging),
+  contributed by Michał Górny. Note that while greenlet will BUILD in
+  a free-threaded Python, it will cause the GIL to be allocated and
+  used, and memory may leak. Also note that these configurations
+  are not tested by this project's CI.
+- Fix an assertion error on debug builds of Python 3.14 when using the
+  experimental JIT. See :issue:`460
+  <https://github.com/python-greenlet/greenlet/issues/460>`_.
+
+
 3.2.3 (2025-06-05)
 ==================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/PKG-INFO new/greenlet-3.2.4/PKG-INFO
--- old/greenlet-3.2.3/PKG-INFO 2025-06-05 18:08:19.273496000 +0200
+++ new/greenlet-3.2.4/PKG-INFO 2025-08-07 15:13:39.288525800 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: greenlet
-Version: 3.2.3
+Version: 3.2.4
 Summary: Lightweight in-process concurrent programming
 Home-page: https://greenlet.readthedocs.io/
 Author: Alexey Borzenkov
@@ -38,6 +38,7 @@
 Provides-Extra: test
 Requires-Dist: objgraph; extra == "test"
 Requires-Dist: psutil; extra == "test"
+Requires-Dist: setuptools; extra == "test"
 Dynamic: author
 Dynamic: author-email
 Dynamic: classifier
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/appveyor.yml 
new/greenlet-3.2.4/appveyor.yml
--- old/greenlet-3.2.3/appveyor.yml     2025-06-05 18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/appveyor.yml     2025-08-07 15:13:36.000000000 +0200
@@ -40,7 +40,7 @@
     # Fully supported 64-bit versions, with testing. This should be
     # all the current (non EOL) versions.
     - PYTHON: "C:\\Python314-x64"
-      PYTHON_VERSION: "3.14.0b2"
+      PYTHON_VERSION: "3.14.0rc1"
       PYTHON_ARCH: "64"
       PYTHON_EXE: python
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/docs/caveats.rst 
new/greenlet-3.2.4/docs/caveats.rst
--- old/greenlet-3.2.3/docs/caveats.rst 2025-06-05 18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/docs/caveats.rst 2025-08-07 15:13:36.000000000 +0200
@@ -32,3 +32,18 @@
 lead to a hang.
 
 See :issue:`143` for an example.
+
+Free-threading Is Not Supported
+===============================
+
+Beginning with 3.14 (and experimental in 3.13), CPython may be built
+in a free-threaded mode where the GIL is not used by default. greenlet
+does not support this mode (although it will build with it), and using
+greenlet in such an interpreter will cause the GIL to be enabled.
+
+In addition, there are known issues running greenlets in a
+free-threaded CPython. These include:
+
+- Garbage collection differences may cause ``GreenletExit`` to no
+  longer be raised in certain multi-threaded scenarios.
+- There may be other memory leaks.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/docs/index.rst 
new/greenlet-3.2.4/docs/index.rst
--- old/greenlet-3.2.3/docs/index.rst   2025-06-05 18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/docs/index.rst   2025-08-07 15:13:36.000000000 +0200
@@ -80,6 +80,10 @@
 when they execute, and since they are coroutines, many greenlets can
 exist in a single native thread.
 
+Note that greenlet will cause a free-threaded build of Python to
+allocate a GIL, so no actual free-threading will take place. For more
+on free-threading and greenlet, see :doc:`caveats`.
+
 .. rubric:: How are greenlets different from threads?
 
 Threads (in theory) are preemptive and parallel [#f1]_, meaning that multiple
@@ -102,6 +106,10 @@
 require fewer resources; it is often practical to have many more
 greenlets than it is threads.
 
+Note that greenlet will cause a free-threaded build of Python to
+allocate a GIL, so no actual free-threading will take place. For more
+on free-threading and greenlet, see :doc:`caveats`.
+
 .. _race conditions: https://en.wikipedia.org/wiki/Race_condition
 .. _deadlocks: 
https://docs.microsoft.com/en-us/troubleshoot/dotnet/visual-basic/race-conditions-deadlocks#when-deadlocks-occur
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/setup.py new/greenlet-3.2.4/setup.py
--- old/greenlet-3.2.3/setup.py 2025-06-05 18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/setup.py 2025-08-07 15:13:36.000000000 +0200
@@ -260,6 +260,7 @@
         'test': [
             'objgraph',
             'psutil',
+            'setuptools',
         ],
     },
     python_requires=">=3.9",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/PyGreenlet.cpp 
new/greenlet-3.2.4/src/greenlet/PyGreenlet.cpp
--- old/greenlet-3.2.3/src/greenlet/PyGreenlet.cpp      2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/PyGreenlet.cpp      2025-08-07 
15:13:36.000000000 +0200
@@ -56,8 +56,15 @@
     PyGreenlet* o =
         (PyGreenlet*)PyBaseObject_Type.tp_new(type, mod_globs->empty_tuple, 
mod_globs->empty_dict);
     if (o) {
-        new UserGreenlet(o, GET_THREAD_STATE().state().borrow_current());
+        // Recall: borrowing or getting the current greenlet
+        // causes the "deleteme list" to get cleared. So constructing a 
greenlet
+        // can do things like cause other greenlets to get finalized.
+        UserGreenlet* c = new UserGreenlet(o, 
GET_THREAD_STATE().state().borrow_current());
         assert(Py_REFCNT(o) == 1);
+        // Also: This looks like a memory leak, but isn't. Constructing the
+        // C++ object assigns it to the pimpl pointer of the Python object (o);
+        // we'll need that later.
+        assert(c == o->pimpl);
     }
     return o;
 }
@@ -236,20 +243,26 @@
          * and call ``PyObject_CallFinalizerFromDealloc``,
          * but that's only supported in Python 3.4+; see
          * Modules/_io/iobase.c for an example.
+         * TODO: We no longer run on anything that old, switch to finalizers.
          *
          * The following approach is copied from iobase.c in CPython 2.7.
          * (along with much of this function in general). Here's their
          * comment:
          *
          * When called from a heap type's dealloc, the type will be
-         * decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
+         * decref'ed on return (see e.g. subtype_dealloc in typeobject.c).
+         *
+         * On free-threaded builds of CPython, the type is meant to be immortal
+         * so we probably shouldn't mess with this? See
+         * test_issue_245_reference_counting_subclass_no_threads
+         */
         if (PyType_HasFeature(self.TYPE(), Py_TPFLAGS_HEAPTYPE)) {
             Py_INCREF(self.TYPE());
         }
 
         PyObject_GC_Track((PyObject*)self);
 
-        _Py_DEC_REFTOTAL;
+        GREENLET_Py_DEC_REFTOTAL;
 #ifdef COUNT_ALLOCS
         --Py_TYPE(self)->tp_frees;
         --Py_TYPE(self)->tp_allocs;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/TGreenlet.cpp 
new/greenlet-3.2.4/src/greenlet/TGreenlet.cpp
--- old/greenlet-3.2.3/src/greenlet/TGreenlet.cpp       2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/TGreenlet.cpp       2025-08-07 
15:13:36.000000000 +0200
@@ -562,6 +562,7 @@
     // be able to raise an exception.
     // That's mostly OK! Since we can't add it to a list, our refcount
     // won't increase, and we'll go ahead with the DECREFs later.
+
     ThreadState *const  thread_state = this->thread_state();
     if (thread_state) {
         thread_state->delete_when_thread_running(this->self());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/TGreenlet.hpp 
new/greenlet-3.2.4/src/greenlet/TGreenlet.hpp
--- old/greenlet-3.2.3/src/greenlet/TGreenlet.hpp       2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/TGreenlet.hpp       2025-08-07 
15:13:36.000000000 +0200
@@ -116,6 +116,12 @@
 #endif
 #if GREENLET_PY314
         int py_recursion_depth;
+        // I think this is only used by the JIT. At least,
+        // we only got errors not switching it when the JIT was enabled.
+        //    Python/generated_cases.c.h:12469: _PyEval_EvalFrameDefault:
+        //      Assertion `tstate->current_executor == NULL' failed.
+        // see https://github.com/python-greenlet/greenlet/issues/460
+        PyObject* current_executor;
 #elif GREENLET_PY312
         int py_recursion_depth;
         int c_recursion_depth;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/TPythonState.cpp 
new/greenlet-3.2.4/src/greenlet/TPythonState.cpp
--- old/greenlet-3.2.3/src/greenlet/TPythonState.cpp    2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/TPythonState.cpp    2025-08-07 
15:13:36.000000000 +0200
@@ -14,6 +14,7 @@
 #endif
 #if GREENLET_PY314
     ,py_recursion_depth(0)
+    ,current_executor(nullptr)
 #elif GREENLET_PY312
     ,py_recursion_depth(0)
     ,c_recursion_depth(0)
@@ -136,6 +137,7 @@
 #if GREENLET_PY311
   #if GREENLET_PY314
     this->py_recursion_depth = tstate->py_recursion_limit - 
tstate->py_recursion_remaining;
+    this->current_executor = tstate->current_executor;
   #elif GREENLET_PY312
     this->py_recursion_depth = tstate->py_recursion_limit - 
tstate->py_recursion_remaining;
     this->c_recursion_depth = Py_C_RECURSION_LIMIT - 
tstate->c_recursion_remaining;
@@ -213,6 +215,7 @@
 #if GREENLET_PY311
   #if GREENLET_PY314
     tstate->py_recursion_remaining = tstate->py_recursion_limit - 
this->py_recursion_depth;
+    tstate->current_executor = this->current_executor;
     this->unexpose_frames();
   #elif GREENLET_PY312
     tstate->py_recursion_remaining = tstate->py_recursion_limit - 
this->py_recursion_depth;
@@ -262,6 +265,7 @@
     this->_top_frame = nullptr;
 #if GREENLET_PY314
     this->py_recursion_depth = tstate->py_recursion_limit - 
tstate->py_recursion_remaining;
+    this->current_executor = tstate->current_executor;
 #elif GREENLET_PY312
     this->py_recursion_depth = tstate->py_recursion_limit - 
tstate->py_recursion_remaining;
     // XXX: TODO: Comment from a reviewer:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/__init__.py 
new/greenlet-3.2.4/src/greenlet/__init__.py
--- old/greenlet-3.2.3/src/greenlet/__init__.py 2025-06-05 18:08:17.000000000 
+0200
+++ new/greenlet-3.2.4/src/greenlet/__init__.py 2025-08-07 15:13:36.000000000 
+0200
@@ -25,7 +25,7 @@
 ###
 # Metadata
 ###
-__version__ = '3.2.3'
+__version__ = '3.2.4'
 from ._greenlet import _C_API # pylint:disable=no-name-in-module
 
 ###
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/greenlet_allocator.hpp 
new/greenlet-3.2.4/src/greenlet/greenlet_allocator.hpp
--- old/greenlet-3.2.3/src/greenlet/greenlet_allocator.hpp      2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/greenlet_allocator.hpp      2025-08-07 
15:13:36.000000000 +0200
@@ -5,10 +5,35 @@
 #include <Python.h>
 #include <memory>
 #include "greenlet_compiler_compat.hpp"
+#include "greenlet_cpython_compat.hpp"
 
 
 namespace greenlet
 {
+#if defined(Py_GIL_DISABLED)
+// Python on free threaded builds says this
+// 
(https://docs.python.org/3/howto/free-threading-extensions.html#memory-allocation-apis):
+//
+//  For thread-safety, the free-threaded build requires that only
+//  Python objects are allocated using the object domain, and that all
+//  Python object are allocated using that domain.
+//
+// This turns out to be important because the GC implementation on
+// free threaded Python uses internal mimalloc APIs to find allocated
+// objects. If we allocate non-PyObject objects using that API, then
+// Bad Things could happen, including crashes and improper results.
+// So in that case, we revert to standard C++ allocation.
+
+    template <class T>
+    struct PythonAllocator : public std::allocator<T> {
+        // This member is deprecated in C++17 and removed in C++20
+        template< class U >
+        struct rebind {
+            typedef PythonAllocator<U> other;
+        };
+    };
+
+#else
     // This allocator is stateless; all instances are identical.
     // It can *ONLY* be used when we're sure we're holding the GIL
     // (Python's allocators require the GIL).
@@ -58,6 +83,7 @@
         };
 
     };
+#endif // allocator type
 }
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/greenlet-3.2.3/src/greenlet/greenlet_cpython_compat.hpp 
new/greenlet-3.2.4/src/greenlet/greenlet_cpython_compat.hpp
--- old/greenlet-3.2.3/src/greenlet/greenlet_cpython_compat.hpp 2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/greenlet_cpython_compat.hpp 2025-08-07 
15:13:36.000000000 +0200
@@ -73,7 +73,9 @@
 #    define Py_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt)
 #endif
 
-#ifndef _Py_DEC_REFTOTAL
+#ifdef _Py_DEC_REFTOTAL
+#  define GREENLET_Py_DEC_REFTOTAL _Py_DEC_REFTOTAL
+#else
 /* _Py_DEC_REFTOTAL macro has been removed from Python 3.9 by:
   
https://github.com/python/cpython/commit/49932fec62c616ec88da52642339d83ae719e924
 
@@ -81,12 +83,12 @@
 */
 #    ifdef Py_REF_DEBUG
 #      if GREENLET_PY312
-#         define _Py_DEC_REFTOTAL
+#         define GREENLET_Py_DEC_REFTOTAL
 #      else
-#        define _Py_DEC_REFTOTAL _Py_RefTotal--
+#        define GREENLET_Py_DEC_REFTOTAL _Py_RefTotal--
 #      endif
 #    else
-#        define _Py_DEC_REFTOTAL
+#        define GREENLET_Py_DEC_REFTOTAL
 #    endif
 #endif
 // Define these flags like Cython does if we're on an old version.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/tests/__init__.py 
new/greenlet-3.2.4/src/greenlet/tests/__init__.py
--- old/greenlet-3.2.3/src/greenlet/tests/__init__.py   2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/tests/__init__.py   2025-08-07 
15:13:36.000000000 +0200
@@ -5,6 +5,7 @@
 """
 import os
 import sys
+import sysconfig
 import unittest
 
 from gc import collect
@@ -36,6 +37,13 @@
 RUNNING_ON_CI = RUNNING_ON_TRAVIS or RUNNING_ON_APPVEYOR
 RUNNING_ON_MANYLINUX = os.environ.get('GREENLET_MANYLINUX')
 
+# Is the current interpreter free-threaded?) Note that this
+# isn't the same as whether the GIL is enabled, this is the build-time
+# value. Certain CPython details, like the garbage collector,
+# work very differently on potentially-free-threaded builds than
+# standard builds.
+RUNNING_ON_FREETHREAD_BUILD = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
+
 class TestCaseMetaClass(type):
     # wrap each test method with
     # a) leak checks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/tests/leakcheck.py 
new/greenlet-3.2.4/src/greenlet/tests/leakcheck.py
--- old/greenlet-3.2.3/src/greenlet/tests/leakcheck.py  2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/tests/leakcheck.py  2025-08-07 
15:13:36.000000000 +0200
@@ -136,6 +136,18 @@
     # presumably.
     IGNORED_TYPES = () #(tuple, dict, types.FrameType, types.TracebackType)
 
+    # Names of types that should be ignored. Use this when we cannot
+    # or don't want to import the class directly.
+    IGNORED_TYPE_NAMES = (
+        # This appears in Python3.14 with the JIT enabled. It
+        # doesn't seem to be directly exposed to Python; the only way to get
+        # one is to cause code to get jitted and then look for all objects
+        # and find one with this name. But they multiply as code
+        # executes and gets jitted, in ways we don't want to rely on.
+        # So just ignore it.
+        'uop_executor',
+    )
+
     def __init__(self, testcase, function):
         self.testcase = testcase
         self.function = function
@@ -179,9 +191,14 @@
                 return False
 
 
-        if kind in self.ignored_types or kind in self.IGNORED_TYPES:
+        if (
+            kind in self.ignored_types
+            or kind in self.IGNORED_TYPES
+            or kind.__name__ in self.IGNORED_TYPE_NAMES
+        ):
             return False
 
+
         return True
 
     def _growth(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/tests/test_greenlet.py 
new/greenlet-3.2.4/src/greenlet/tests/test_greenlet.py
--- old/greenlet-3.2.3/src/greenlet/tests/test_greenlet.py      2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/tests/test_greenlet.py      2025-08-07 
15:13:36.000000000 +0200
@@ -13,6 +13,7 @@
 from . import RUNNING_ON_MANYLINUX
 from . import PY313
 from . import PY314
+from . import RUNNING_ON_FREETHREAD_BUILD
 from .leakcheck import fails_leakcheck
 
 
@@ -245,7 +246,6 @@
             someref.append(g1)
             del g1
             gc.collect()
-
             bg_glet_created_running_and_no_longer_ref_in_bg.set()
             fg_ref_released.wait(3)
 
@@ -261,8 +261,20 @@
         self.assertEqual(seen, [])
         self.assertEqual(len(someref), 1)
         del someref[:]
-        gc.collect()
-        # g1 is not released immediately because it's from another thread
+        if not RUNNING_ON_FREETHREAD_BUILD:
+            # The free-threaded GC is very different. In 3.14rc1,
+            # the free-threaded GC traverses ``g1``, realizes it is
+            # not referenced from anywhere else IT cares about,
+            # calls ``tp_clear`` and then ``green_dealloc``. This causes
+            # the greenlet to lose its reference to the main greenlet and 
thread
+            # in which it was running, which means we can no longer throw an
+            # exception into it, preventing the rest of this test from working.
+            # Standard 3.14 traverses the object but doesn't ``tp_clear`` or
+            # ``green_dealloc`` it.
+            gc.collect()
+        # g1 is not released immediately because it's from another thread;
+        # switching back to that thread will allocate a greenlet and thus
+        # trigger deletion actions.
         self.assertEqual(seen, [])
         fg_ref_released.set()
         bg_should_be_clear.wait(3)
@@ -720,7 +732,18 @@
             Greenlet(greenlet_main).switch()
 
         del self.glets
-        self.assertEqual(sys.getrefcount(Greenlet), initial_refs)
+        if RUNNING_ON_FREETHREAD_BUILD:
+            # Free-threaded builds make types immortal, which gives us
+            # weird numbers here, and we actually do APPEAR to end
+            # up with one more reference than we started with, at least on 
3.14.
+            # If we change the code in green_dealloc to avoid increffing the 
type
+            # (which fixed this initial bug), then our leakchecks find other 
objects
+            # that have leaked, including a tuple, a dict, and a type. So 
that's not the
+            # right solution. Instead we change the test:
+            # XXX: FIXME: Is there a better way?
+            self.assertGreaterEqual(sys.getrefcount(Greenlet), initial_refs)
+        else:
+            self.assertEqual(sys.getrefcount(Greenlet), initial_refs)
 
     @unittest.skipIf(
         PY313 and RUNNING_ON_MANYLINUX,
@@ -775,9 +798,12 @@
         # non-deterministic. Presumably the memory layouts are different
         initial_refs = sys.getrefcount(MyGreenlet)
         thread_ready_events = []
-        for _ in range(
-                initial_refs + 45
-        ):
+        thread_count = initial_refs + 45
+        if RUNNING_ON_FREETHREAD_BUILD:
+            # types are immortal, so this is a HUGE number most likely,
+            # and we can't create that many threads.
+            thread_count = 50
+        for _ in range(thread_count):
             event = Event()
             thread = Thread(target=thread_main, args=(event,))
             thread_ready_events.append(event)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/tests/test_leaks.py 
new/greenlet-3.2.4/src/greenlet/tests/test_leaks.py
--- old/greenlet-3.2.3/src/greenlet/tests/test_leaks.py 2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/tests/test_leaks.py 2025-08-07 
15:13:36.000000000 +0200
@@ -15,10 +15,12 @@
 import greenlet
 from . import TestCase
 from . import PY314
+from . import RUNNING_ON_FREETHREAD_BUILD
 from .leakcheck import fails_leakcheck
 from .leakcheck import ignores_leakcheck
 from .leakcheck import RUNNING_ON_MANYLINUX
 
+
 # pylint:disable=protected-access
 
 assert greenlet.GREENLET_USE_GC # Option to disable this was removed in 1.0
@@ -39,6 +41,14 @@
         cls.EXTANT_INSTANCES.clear()
 
 
+def fails_leakcheck_except_on_free_thraded(func):
+    if RUNNING_ON_FREETHREAD_BUILD:
+        # These all seem to pass on free threading because
+        # of the changes to the garbage collector
+        return func
+    return fails_leakcheck(func)
+
+
 class TestLeaks(TestCase):
 
     def test_arg_refs(self):
@@ -265,7 +275,7 @@
         finally:
             greenlet._greenlet.enable_optional_cleanup(True)
 
-    @fails_leakcheck
+    @fails_leakcheck_except_on_free_thraded
     def test_issue251_issue252_need_to_collect_in_background(self):
         # Between greenlet 1.1.2 and the next version, this was still
         # failing because the leak of the list still exists when we
@@ -286,7 +296,7 @@
         # for some reason, but I've never seen it pass on macOS.
         self._check_issue251(manually_collect_background=False)
 
-    @fails_leakcheck
+    @fails_leakcheck_except_on_free_thraded
     def 
test_issue251_issue252_need_to_collect_in_background_cleanup_disabled(self):
         self.expect_greenlet_leak = True
         greenlet._greenlet.enable_optional_cleanup(False)
@@ -295,7 +305,7 @@
         finally:
             greenlet._greenlet.enable_optional_cleanup(True)
 
-    @fails_leakcheck
+    @fails_leakcheck_except_on_free_thraded
     def test_issue251_issue252_explicit_reference_not_collectable(self):
         self._check_issue251(
             manually_collect_background=False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet/tests/test_tracing.py 
new/greenlet-3.2.4/src/greenlet/tests/test_tracing.py
--- old/greenlet-3.2.3/src/greenlet/tests/test_tracing.py       2025-06-05 
18:08:17.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet/tests/test_tracing.py       2025-08-07 
15:13:36.000000000 +0200
@@ -1,5 +1,6 @@
 from __future__ import print_function
 import sys
+import sysconfig
 import greenlet
 import unittest
 
@@ -7,9 +8,16 @@
 from . import PY312
 
 # 
https://discuss.python.org/t/cpython-3-12-greenlet-and-tracing-profiling-how-to-not-crash-and-get-correct-results/33144/2
-DEBUG_BUILD_PY312 = (
-    PY312 and hasattr(sys, 'gettotalrefcount'),
-    "Broken on debug builds of Python 3.12"
+# When build variables are available, OPT is the best way of detecting
+# the build with assertions enabled. Otherwise, fallback to detecting PyDEBUG
+# build.
+ASSERTION_BUILD_PY312 = (
+    PY312 and (
+        "-DNDEBUG" not in sysconfig.get_config_var("OPT").split()
+        if sysconfig.get_config_var("OPT") is not None
+        else hasattr(sys, 'gettotalrefcount')
+    ),
+    "Broken on assertion-enabled builds of Python 3.12"
 )
 
 class SomeError(Exception):
@@ -198,7 +206,7 @@
 
         self._check_trace_events_from_greenlet_sets_profiler(X(), tracer)
 
-    @unittest.skipIf(*DEBUG_BUILD_PY312)
+    @unittest.skipIf(*ASSERTION_BUILD_PY312)
     def test_trace_events_multiple_greenlets_switching(self):
         tracer = PythonTracer()
 
@@ -236,7 +244,7 @@
             ('c_call', '__exit__'),
         ])
 
-    @unittest.skipIf(*DEBUG_BUILD_PY312)
+    @unittest.skipIf(*ASSERTION_BUILD_PY312)
     def test_trace_events_multiple_greenlets_switching_siblings(self):
         # Like the first version, but get both greenlets running first
         # as "siblings" and then establish the tracing.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet.egg-info/PKG-INFO 
new/greenlet-3.2.4/src/greenlet.egg-info/PKG-INFO
--- old/greenlet-3.2.3/src/greenlet.egg-info/PKG-INFO   2025-06-05 
18:08:19.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet.egg-info/PKG-INFO   2025-08-07 
15:13:39.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: greenlet
-Version: 3.2.3
+Version: 3.2.4
 Summary: Lightweight in-process concurrent programming
 Home-page: https://greenlet.readthedocs.io/
 Author: Alexey Borzenkov
@@ -38,6 +38,7 @@
 Provides-Extra: test
 Requires-Dist: objgraph; extra == "test"
 Requires-Dist: psutil; extra == "test"
+Requires-Dist: setuptools; extra == "test"
 Dynamic: author
 Dynamic: author-email
 Dynamic: classifier
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/greenlet-3.2.3/src/greenlet.egg-info/requires.txt 
new/greenlet-3.2.4/src/greenlet.egg-info/requires.txt
--- old/greenlet-3.2.3/src/greenlet.egg-info/requires.txt       2025-06-05 
18:08:19.000000000 +0200
+++ new/greenlet-3.2.4/src/greenlet.egg-info/requires.txt       2025-08-07 
15:13:39.000000000 +0200
@@ -6,3 +6,4 @@
 [test]
 objgraph
 psutil
+setuptools

Reply via email to