Package: src:pygame
Version: 2.6.1-5 User: [email protected]
Usertags: python3.15
Tags: patch

Hi!

While rebuilding the python related packages against the Python 3.15rc1
version we found that pygame fails to build from source [1].
Sadly, the upstream repository seems to be abandoned. I found that the
Fedora team had already made a patch for fixing this issue [2] and
reported it upstream [3].
However, that patch was causing some tests to fail (and it seemed like a
legitimate failure, due to a bug in the patch), so I've adapted it to
make it work correctly.

While doing this, I also found the reason for one of the reference
counting errors that were being hard-fixed for 3.14+ inside of
py314-refcount-tests.patch, and added a patch that fixes the test to
make it behave correctly instead.

I applied these fixes in the sandbox [4] to be able to build the
packages that depend on pygame, please consider applying the patch to
support the upcoming 3.15 version.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4315864/
[2]: 
https://src.fedoraproject.org/rpms/pygame/c/bac081363eaae1bbec28c1af8003c37abd52c372?branch=rawhide
[3]: https://github.com/pygame/pygame/issues/4716
[4]: https://debusine.debian.net/debian/r-python-python3.15/

--
"Can you imagine what I would do if I could do all I can?" -- Sun Tzu
Saludos /\/\ /\ >< `/
diff -Nru pygame-2.6.1/debian/changelog pygame-2.6.1/debian/changelog
--- pygame-2.6.1/debian/changelog       2026-06-03 12:36:57.000000000 +0200
+++ pygame-2.6.1/debian/changelog       2026-08-23 16:28:50.000000000 +0200
@@ -1,3 +1,17 @@
+pygame (2.6.1-6) UNRELEASED; urgency=medium
+
+  * Team upload.
+  * Add updated fedora patch for python 3.15: 
pygame-2.6.1-python-3.15-fix.patch
+    - Fix unlocking when consumer is NULL
+  * Add py315-refcount-test-constant-folding.patch
+    - build the bytes object in rwobject_test.test_refcount() at run time,
+      python 3.14+ constant folds b"..."[1:].
+  * Update patch py314-refcount-tests.patch
+    - drop the rwobject_test.py part, superseded by the above
+    - add the "import sys" its freetype_test.py part needs.
+
+ -- Maximiliano Curia <[email protected]>  Sun, 23 Aug 2026 16:28:50 +0200
+
 pygame (2.6.1-5) unstable; urgency=medium
 
   * Team upload.
diff -Nru pygame-2.6.1/debian/patches/py314-refcount-tests.patch 
pygame-2.6.1/debian/patches/py314-refcount-tests.patch
--- pygame-2.6.1/debian/patches/py314-refcount-tests.patch      2026-06-03 
12:36:57.000000000 +0200
+++ pygame-2.6.1/debian/patches/py314-refcount-tests.patch      2026-08-23 
16:28:50.000000000 +0200
@@ -1,27 +1,24 @@
-From: =?utf-8?q?Ren=C3=A9_Dudfield?= <[email protected]>
-Date: Mon, 8 Dec 2025 19:34:06 +0000
-Subject: freetype_test: mask_test: rwobject_test: Change ref counts for py
- 3.14
-
-Are these correct? I don't know.
-
-But apparently the garbage collector changed and reference counts
-changed.
-
+Description: freetype_test: mask_test: rwobject_test: Change ref counts for py 
3.14
+ .
+ Are these correct? I don't know.
+ .
+ But apparently the garbage collector changed and reference counts changed.
+Author: =?utf-8?q?Ren=C3=A9_Dudfield?= <[email protected]>
 Origin: 
https://github.com/pygame/pygame/pull/4599/commits/ac69c0be7e165d967123ffaf2075f81357a5a25e
 Bug-Debian: https://bugs.debian.org/1121999
-Last-Update: 2025-12-08
----
- test/freetype_test.py | 17 +++++++++--
- test/mask_test.py     | 84 ++++++++++++++++++++++++++++++++++++++++++---------
- test/rwobject_test.py |  6 +++-
- 3 files changed, 89 insertions(+), 18 deletions(-)
-
-diff --git a/test/freetype_test.py b/test/freetype_test.py
-index 25551d8..d00db8a 100644
---- a/test/freetype_test.py
-+++ b/test/freetype_test.py
-@@ -1609,16 +1609,27 @@ class FreeTypeFontTest(unittest.TestCase):
+Forwarded: https://github.com/pygame/pygame/pull/4599
+Last-Update: 2026-08-23
+Index: pygame/test/freetype_test.py
+===================================================================
+--- pygame.orig/test/freetype_test.py
++++ pygame/test/freetype_test.py
+@@ -1,4 +1,5 @@
+ import os
++import sys
+ 
+ if os.environ.get("SDL_VIDEODRIVER") == "dummy":
+     __tags__ = ("ignore", "subprocess_ignore")
+@@ -1609,16 +1610,27 @@ class FreeTypeFontTest(unittest.TestCase
          else:
              array = arrinter.Array(rect.size, "u", 1)
              o = font.render_raw(text)
@@ -52,10 +49,10 @@
              for i in range(len(o)):
                  self.assertEqual(getrefcount(o[i]), 2, "refcount fail for 
item %d" % i)
  
-diff --git a/test/mask_test.py b/test/mask_test.py
-index bd7daf5..3bd7062 100644
---- a/test/mask_test.py
-+++ b/test/mask_test.py
+Index: pygame/test/mask_test.py
+===================================================================
+--- pygame.orig/test/mask_test.py
++++ pygame/test/mask_test.py
 @@ -2579,7 +2579,11 @@ class MaskTypeTest(unittest.TestCase):
      @unittest.skipIf(IS_PYPY, "Segfaults on pypy")
      def test_to_surface(self):
@@ -238,26 +235,3 @@
          expected_flag = SRCALPHA
          expected_depth = 32
          expected_color = pygame.Color("black")  # Default unsetcolor.
-diff --git a/test/rwobject_test.py b/test/rwobject_test.py
-index 31723ae..3441b04 100644
---- a/test/rwobject_test.py
-+++ b/test/rwobject_test.py
-@@ -1,5 +1,6 @@
- import pathlib
- import unittest
-+import sys
- 
- from pygame import encode_string, encode_file_path
- 
-@@ -83,7 +84,10 @@ class RWopsEncodeStringTest(unittest.TestCase):
-             bpath = encode_string(bpath)
-             self.assertEqual(getrefcount(bpath), before)
-             bpath = encode_string(upath)
--            self.assertEqual(getrefcount(bpath), before)
-+            if sys.version_info >= (3, 14):
-+                self.assertEqual(getrefcount(bpath), before - 1)
-+            else:
-+                self.assertEqual(getrefcount(bpath), before)
- 
-     def test_smp(self):
-         utf_8 = b"a\xF0\x93\x82\xA7b"
diff -Nru 
pygame-2.6.1/debian/patches/py315-refcount-test-constant-folding.patch 
pygame-2.6.1/debian/patches/py315-refcount-test-constant-folding.patch
--- pygame-2.6.1/debian/patches/py315-refcount-test-constant-folding.patch      
1970-01-01 01:00:00.000000000 +0100
+++ pygame-2.6.1/debian/patches/py315-refcount-test-constant-folding.patch      
2026-08-23 16:28:50.000000000 +0200
@@ -0,0 +1,18 @@
+Description: rwobject_test: build the test bytes object at run time
+ This way the object has two references no matter the python version.
+Author: Maximiliano Curia <[email protected]>
+Forwarded: no
+Last-Update: 2026-08-23
+Index: pygame/test/rwobject_test.py
+===================================================================
+--- pygame.orig/test/rwobject_test.py
++++ pygame/test/rwobject_test.py
+@@ -77,7 +77,7 @@ class RWopsEncodeStringTest(unittest.Tes
+     else:
+ 
+         def test_refcount(self):
+-            bpath = b" This is a string that is not cached."[1:]
++            bpath = bytes(bytearray(b"This is a string that is not cached."))
+             upath = bpath.decode("ascii")
+             before = getrefcount(bpath)
+             bpath = encode_string(bpath)
diff -Nru pygame-2.6.1/debian/patches/pygame-2.6.1-python-3.15-fix.patch 
pygame-2.6.1/debian/patches/pygame-2.6.1-python-3.15-fix.patch
--- pygame-2.6.1/debian/patches/pygame-2.6.1-python-3.15-fix.patch      
1970-01-01 01:00:00.000000000 +0100
+++ pygame-2.6.1/debian/patches/pygame-2.6.1-python-3.15-fix.patch      
2026-08-23 16:28:50.000000000 +0200
@@ -0,0 +1,89 @@
+Description: Replace PyWeakref_GetObject() with PyWeakref_GetRef()
+Author: Maximiliano Curia <[email protected]>
+Origin: other, 
https://src.fedoraproject.org/rpms/pygame/blob/rawhide/f/pygame-2.6.1-python-3.15-fix.patch
+Forwarded: no
+Last-Update: 2026-08-23
+Index: pygame/src_c/surface.c
+===================================================================
+--- pygame.orig/src_c/surface.c
++++ pygame/src_c/surface.c
+@@ -1024,8 +1024,10 @@ surf_get_locks(PyObject *self, PyObject
+         return NULL;
+ 
+     for (i = 0; i < len; i++) {
+-        tmp = PyWeakref_GetObject(PyList_GetItem(surf->locklist, i));
+-        Py_INCREF(tmp);
++        if (PyWeakref_GetRef(PyList_GetItem(surf->locklist, i), &tmp) <= 0) {
++            Py_INCREF(Py_None);
++            tmp = Py_None;
++        }
+         PyTuple_SetItem(tuple, i, tmp);
+     }
+     return tuple;
+@@ -3449,12 +3451,11 @@ _release_buffer(Py_buffer *view_p)
+     internal = (pg_bufferinternal *)view_p->internal;
+     consumer_ref = internal->consumer_ref;
+     assert(consumer_ref && PyWeakref_CheckRef(consumer_ref));
+-    consumer = PyWeakref_GetObject(consumer_ref);
+-    if (consumer) {
+-        if (!pgSurface_UnlockBy((pgSurfaceObject *)view_p->obj, consumer)) {
+-            PyErr_Clear();
+-        }
++    PyWeakref_GetRef(consumer_ref, &consumer);
++    if (!pgSurface_UnlockBy((pgSurfaceObject *)view_p->obj, consumer)) {
++        PyErr_Clear();
+     }
++    Py_XDECREF(consumer);
+     Py_DECREF(consumer_ref);
+     PyMem_Free(internal);
+     Py_DECREF(view_p->obj);
+Index: pygame/src_c/surflock.c
+===================================================================
+--- pygame.orig/src_c/surflock.c
++++ pygame/src_c/surflock.c
+@@ -120,27 +120,32 @@ pgSurface_UnlockBy(pgSurfaceObject *surf
+     int noerror = 1;
+ 
+     if (surf->locklist != NULL) {
++        int getref_stat;
+         PyObject *item, *ref;
+         Py_ssize_t len = PyList_Size(surf->locklist);
+         while (--len >= 0 && !found) {
+             item = PyList_GetItem(surf->locklist, len);
+-            ref = PyWeakref_GetObject(item);
++            getref_stat = PyWeakref_GetRef(item, &ref);
+             if (ref == lockobj) {
+                 if (PySequence_DelItem(surf->locklist, len) == -1) {
++                    Py_XDECREF(ref);
+                     return 0;
+                 }
+                 else {
+                     found = 1;
+                 }
+             }
++            if (getref_stat > 0) {
++                Py_DECREF(ref);
++            }
+         }
+ 
+         /* Clear dead references */
+         len = PyList_Size(surf->locklist);
+         while (--len >= 0) {
+             item = PyList_GetItem(surf->locklist, len);
+-            ref = PyWeakref_GetObject(item);
+-            if (ref == Py_None) {
++            getref_stat = PyWeakref_GetRef(item, &ref);
++            if (ref == NULL) {
+                 if (PySequence_DelItem(surf->locklist, len) == -1) {
+                     noerror = 0;
+                 }
+@@ -148,6 +153,9 @@ pgSurface_UnlockBy(pgSurfaceObject *surf
+                     found++;
+                 }
+             }
++            if (getref_stat > 0) {
++                Py_DECREF(ref);
++            }
+         }
+     }
+ 
diff -Nru pygame-2.6.1/debian/patches/series pygame-2.6.1/debian/patches/series
--- pygame-2.6.1/debian/patches/series  2026-06-03 12:36:57.000000000 +0200
+++ pygame-2.6.1/debian/patches/series  2026-08-23 16:28:50.000000000 +0200
@@ -7,3 +7,5 @@
 py314-refcount-tests.patch
 Use-SDL_HasSurfaceRLE-when-available.patch
 sdl2-compat-remove-rle-assertions.patch
+pygame-2.6.1-python-3.15-fix.patch
+py315-refcount-test-constant-folding.patch

Reply via email to