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