Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-gobject for openSUSE:Factory 
checked in at 2026-05-13 17:19:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-gobject (Old)
 and      /work/SRC/openSUSE:Factory/.python-gobject.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-gobject"

Wed May 13 17:19:32 2026 rev:111 rq:1352553 version:3.56.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-gobject/python-gobject.changes    
2026-03-28 20:14:30.280279566 +0100
+++ /work/SRC/openSUSE:Factory/.python-gobject.new.1966/python-gobject.changes  
2026-05-13 17:20:43.654755014 +0200
@@ -1,0 +2,9 @@
+Sat May  9 08:38:33 UTC 2026 - Bjørn Lie <[email protected]>
+
+- Update to version 3.56.3:
+  + Fix crash when user_data is defined before callback
+  + Add missing msg argument to asyncio cancel()
+  + Fix potential buffer overflow errors
+  + Fix memory leak when initializing GTK templates
+
+-------------------------------------------------------------------

Old:
----
  pygobject-3.56.2.tar.xz

New:
----
  pygobject-3.56.3.tar.xz

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

Other differences:
------------------
++++++ python-gobject.spec ++++++
--- /var/tmp/diff_new_pack.G1R32w/_old  2026-05-13 17:20:46.266862928 +0200
+++ /var/tmp/diff_new_pack.G1R32w/_new  2026-05-13 17:20:46.290863920 +0200
@@ -34,7 +34,7 @@
 %define libffi_version 3.0
 %{?sle15_python_module_pythons}
 Name:           python-gobject
-Version:        3.56.2
+Version:        3.56.3
 Release:        0
 Summary:        Python bindings for GObject
 License:        LGPL-2.1-or-later

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.G1R32w/_old  2026-05-13 17:20:46.674879785 +0200
+++ /var/tmp/diff_new_pack.G1R32w/_new  2026-05-13 17:20:46.714881437 +0200
@@ -1,6 +1,6 @@
-mtime: 1774467603
-commit: fb6a735bad0d053bb900ee900197b1eee68b6b29f630026f3197bbf2de263638
+mtime: 1778315976
+commit: b6c66d026495741570deda1c8e878c855b4e89e18a3ad020cfff07ae7e77be81
 url: https://src.opensuse.org/GNOME/python-gobject
-revision: fb6a735bad0d053bb900ee900197b1eee68b6b29f630026f3197bbf2de263638
+revision: b6c66d026495741570deda1c8e878c855b4e89e18a3ad020cfff07ae7e77be81
 projectscmsync: https://src.opensuse.org/GNOME/_ObsPrj
 

++++++ _service ++++++
--- /var/tmp/diff_new_pack.G1R32w/_old  2026-05-13 17:20:46.890888709 +0200
+++ /var/tmp/diff_new_pack.G1R32w/_new  2026-05-13 17:20:46.926890196 +0200
@@ -3,7 +3,7 @@
   <service name="obs_scm" mode="manual">
     <param name="scm">git</param>
     <param name="url">https://gitlab.gnome.org/GNOME/pygobject.git</param>
-    <param name="revision">3.56.2</param>
+    <param name="revision">3.56.3</param>
     <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param>
     <param name="versionrewrite-pattern">v?(.*)\+0</param>
     <param name="versionrewrite-replacement">\1</param>

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-05-09 10:39:36.000000000 +0200
@@ -0,0 +1,5 @@
+*.obscpio
+*.osc
+_build.*
+.pbuild
+osc-collab.*

++++++ pygobject-3.56.2.tar.xz -> pygobject-3.56.3.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/NEWS new/pygobject-3.56.3/NEWS
--- old/pygobject-3.56.2/NEWS   2026-03-25 16:01:00.000000000 +0100
+++ new/pygobject-3.56.3/NEWS   2026-05-08 22:10:32.000000000 +0200
@@ -1,3 +1,11 @@
+3.56.3 - 2026-05-08
+-------------------
+
+* Fix crash when user_data is defined before callback :mr:`554`
+* Add missing msg argument to asyncio cancel() :mr:`541`
+* Fix potential buffer overflow errors :mr:`540`
+* Fix memory leak when initializing GTK templates :mr:`526`
+
 3.56.2 - 2026-03-25
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/gi/pygi-async.c 
new/pygobject-3.56.3/gi/pygi-async.c
--- old/pygobject-3.56.2/gi/pygi-async.c        2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/gi/pygi-async.c        2026-05-08 22:10:32.000000000 
+0200
@@ -63,8 +63,14 @@
  * Cancel the asynchronous operation.
  */
 static PyObject *
-async_cancel (PyGIAsync *self)
+async_cancel (PyGIAsync *self, PyObject *args, PyObject *kwargs)
 {
+    static char *kwlist[] = { "msg", NULL };
+    const char *msg = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|z", kwlist, &msg))
+        return NULL;
+
     return PyObject_CallMethod (self->cancellable, "cancel", NULL);
 }
 
@@ -295,7 +301,7 @@
 }
 
 static PyMethodDef async_methods[] = {
-    { "cancel", (PyCFunction)async_cancel, METH_NOARGS },
+    { "cancel", (PyCFunction)async_cancel, METH_VARARGS | METH_KEYWORDS },
     { "done", (PyCFunction)async_done, METH_NOARGS },
     { "result", (PyCFunction)async_result, METH_NOARGS },
     { "exception", (PyCFunction)async_exception, METH_NOARGS },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/gi/pygi-cache-array.c 
new/pygobject-3.56.3/gi/pygi-cache-array.c
--- old/pygobject-3.56.2/gi/pygi-cache-array.c  2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/gi/pygi-cache-array.c  2026-05-08 22:10:32.000000000 
+0200
@@ -551,6 +551,7 @@
             PyGIMarshalToPyFunc item_to_py_marshaller;
             PyGIArgCache *item_arg_cache;
             GPtrArray *item_cleanups;
+            gboolean item_size_warning = FALSE;
 
             py_obj = PyList_New (array_->len);
             if (py_obj == NULL) goto err;
@@ -564,7 +565,7 @@
             item_size = g_array_get_element_size (array_);
 
             for (i = 0; i < array_->len; i++) {
-                GIArgument item_arg;
+                GIArgument item_arg = PYGI_ARG_INIT;
                 PyObject *py_item;
                 gpointer item_cleanup_data = NULL;
 
@@ -577,8 +578,25 @@
                         g_ptr_array_index ((GPtrArray *)array_, i);
 
                 } else if (item_arg_cache->is_pointer) {
-                    item_arg.v_pointer = g_array_index (array_, gpointer, i);
-
+                    if (item_size == sizeof (gpointer)) {
+                        item_arg.v_pointer =
+                            g_array_index (array_, gpointer, i);
+                    } else {
+                        // TODO: this warning needs to be actionable
+                        //  I do not have enough context to show which 
field/argument is in error, maybe
+                        //  allow to raise errors for those cases (e.g. an 
option that can be set in unit tests)
+                        if (!item_size_warning) {
+                            g_warning (
+                                "Array type is assumed to be a pointer, but "
+                                "item size is %" G_GSIZE_FORMAT " bytes",
+                                item_size);
+                            item_size_warning = TRUE;
+                        }
+
+                        // For now, copy the right number of bytes
+                        memcpy (&item_arg, array_->data + i * item_size,
+                                item_size);
+                    }
                 } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
                     PyGIInterfaceCache *iface_cache =
                         (PyGIInterfaceCache *)item_arg_cache;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/gi/pygi-cache-closure.c 
new/pygobject-3.56.3/gi/pygi-cache-closure.c
--- old/pygobject-3.56.2/gi/pygi-cache-closure.c        2026-03-25 
16:01:00.000000000 +0100
+++ new/pygobject-3.56.3/gi/pygi-cache-closure.c        2026-05-08 
22:10:32.000000000 +0200
@@ -270,6 +270,26 @@
         PyGIArgCache *user_data_arg_cache = pygi_arg_cache_alloc ();
         user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
         user_data_arg_cache->direction = direction;
+
+        PyGIArgCache *existing = _pygi_callable_cache_get_arg (
+            callable_cache, callback_cache->user_data_index);
+        if (existing != NULL) {
+            /* user_data preceded the callback in the arg list and was already
+             * built as a PARENT by the main loop. Reuse its py_arg_index so
+             * we don't leave a hole in the [0..n_py_args) numbering.
+             */
+
+            /* user_data should never be (out); if it ever is, we'd also need 
to
+             * remove `existing` from `callable_cache->to_py_args` and 
decrememnt
+             * `n_to_py_args` before freeing it. */
+            g_assert (!(existing->direction & PYGI_DIRECTION_TO_PYTHON));
+
+            user_data_arg_cache->py_arg_index = existing->py_arg_index;
+            user_data_arg_cache->c_arg_index = existing->c_arg_index;
+            user_data_arg_cache->type_tag = existing->type_tag;
+            pygi_arg_cache_free (existing);
+        }
+
         _pygi_callable_cache_set_arg (callable_cache,
                                       callback_cache->user_data_index,
                                       user_data_arg_cache);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/gi/pygi-cache.h 
new/pygobject-3.56.3/gi/pygi-cache.h
--- old/pygobject-3.56.2/gi/pygi-cache.h        2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/gi/pygi-cache.h        2026-05-08 22:10:32.000000000 
+0200
@@ -287,6 +287,7 @@
 _pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index,
                               PyGIArgCache *arg_cache)
 {
+    g_assert (index < cache->args_cache->len);
     cache->args_cache->pdata[index] = arg_cache;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/gi/pygobject-class.c 
new/pygobject-3.56.3/gi/pygobject-class.c
--- old/pygobject-3.56.2/gi/pygobject-class.c   2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/gi/pygobject-class.c   2026-05-08 22:10:32.000000000 
+0200
@@ -768,12 +768,20 @@
     if (is_final_subclass
         && PyObject_HasAttrString ((PyObject *)Py_TYPE (wrapper),
                                    "__dontuse_ginstance_init__")) {
+        gboolean was_floating = g_object_is_floating (object);
+        g_object_ref_sink (object);
+
         result =
             PyObject_CallMethod (wrapper, "__dontuse_ginstance_init__", NULL);
         if (result == NULL)
             PyErr_Print ();
         else
             Py_DECREF (result);
+
+        if (was_floating)
+            g_object_force_floating (object);
+        else
+            g_object_unref (object);
     }
 
     if (needs_init) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/meson.build 
new/pygobject-3.56.3/meson.build
--- old/pygobject-3.56.2/meson.build    2026-03-25 16:01:00.000000000 +0100
+++ new/pygobject-3.56.3/meson.build    2026-05-08 22:10:32.000000000 +0200
@@ -1,7 +1,7 @@
 project(
   'pygobject',
   'c',
-  version : '3.56.2',
+  version : '3.56.3',
   meson_version : '>= 0.64.0',
   default_options : [
     'warning_level=1',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pygobject-3.56.2/subprojects/gobject-introspection-tests.wrap 
new/pygobject-3.56.3/subprojects/gobject-introspection-tests.wrap
--- old/pygobject-3.56.2/subprojects/gobject-introspection-tests.wrap   
2026-03-25 16:01:00.000000000 +0100
+++ new/pygobject-3.56.3/subprojects/gobject-introspection-tests.wrap   
2026-05-08 22:10:32.000000000 +0200
@@ -2,5 +2,5 @@
 directory=gobject-introspection-tests
 url=https://gitlab.gnome.org/GNOME/gobject-introspection-tests.git
 [email protected]:GNOME/gobject-introspection-tests.git
-revision=5e961ff83039340d104f57dbb1f9c3a9f55f5029
+revision=53e6bc978d5011f22d0a27cca49a94b19816ca7d
 depth=1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/tests/conftest.py 
new/pygobject-3.56.3/tests/conftest.py
--- old/pygobject-3.56.2/tests/conftest.py      2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/tests/conftest.py      2026-05-08 22:10:32.000000000 
+0200
@@ -88,12 +88,8 @@
 
     # force untranslated messages, as we check for them in some tests
     os.environ["LC_MESSAGES"] = "C"
-    os.environ["G_DEBUG"] = "fatal-warnings fatal-criticals"
-    if sys.platform == "darwin" or os.name == "nt":
-        # gtk 3.22 has warnings and ciriticals on OS X, ignore for now.
-        # On Windows glib will create an error dialog which will block tests
-        # so it's never a good idea there to make things fatal.
-        os.environ["G_DEBUG"] = ""
+    if os.name != "nt":
+        os.environ["G_DEBUG"] = "fatal-warnings fatal-criticals"
 
     # First add test directory, since we have a gi package there
     tests_srcdir = os.path.abspath(os.path.dirname(__file__))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/tests/test_async.py 
new/pygobject-3.56.3/tests/test_async.py
--- old/pygobject-3.56.2/tests/test_async.py    2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/tests/test_async.py    2026-05-08 22:10:32.000000000 
+0200
@@ -1,3 +1,4 @@
+import sys
 import pytest
 import platform
 import unittest
@@ -76,6 +77,86 @@
 
         self.loop.run_until_complete(run())
 
+    def test_cancel_async_task(self):
+        # Regression test for 
https://gitlab.gnome.org/GNOME/pygobject/-/issues/755
+        async def _long_task(proc):
+            await proc.wait_async()
+
+        async def run():
+            nonlocal self
+
+            # Create a process which waits for input on stdin, without ever
+            # actually providing any such input.  This process won't exit 
unless
+            # we explicitly kill it.
+            flags = (
+                Gio.SubprocessFlags.STDOUT_SILENCE
+                | Gio.SubprocessFlags.STDERR_SILENCE
+                | Gio.SubprocessFlags.STDIN_PIPE
+            )
+            proc = Gio.Subprocess.new([sys.executable], flags)
+
+            try:
+                # Create a task which waits for said process to exit; but since
+                # the process won't actually do so we've created a task which
+                # indefinitely awaits on a Gio cancellable.
+                res = asyncio.create_task(_long_task(proc))
+                # Briefly yield control to make sure the task we just created
+                # starts running on the loop and polls on a Gio task.
+                await asyncio.sleep(0.1)
+                # Now cancel the task while it's awaiting on a Gio task; this
+                # will now hit the async_cancel implementation on the C side.
+                #
+                # Also, explicitly assert that the task was really cancelled
+                # (.cancel() returns True), and hasn't already finished by this
+                # time (.cancel() returns False).  This makes sure that we're
+                # really testing the cancellation here.
+                assert res.cancel(), "Test invalid, task already finished"
+            finally:
+                proc.force_exit()
+
+        self.loop.run_until_complete(run())
+
+    def test_async_task_cancellation(self):
+        """Cancellation works on wrapping task."""
+        f = Gio.file_new_for_path("./")
+
+        async def run():
+            nonlocal self, task
+
+            # Queue cancellation of ourselves with default idle priority
+            GLib.idle_add(lambda: task.cancel("custom cancellation message") 
and False)
+
+            cancel = Gio.Cancellable()
+
+            try:
+                # Start low priority task which will be cancelled (lower than 
default idle)
+                async_call = f.enumerate_children_async(
+                    "standard::*", 0, GLib.PRIORITY_LOW, cancel
+                )
+                await async_call
+
+                self.fail("await did not raise!")
+            except asyncio.CancelledError:
+                self.assertTrue(cancel.is_cancelled())
+
+                gio_exception = async_call.exception()
+                self.assertIsInstance(gio_exception, GLib.GError)
+                self.assertTrue(
+                    gio_exception.matches(
+                        Gio.io_error_quark(), Gio.IOErrorEnum.CANCELLED
+                    )
+                )
+
+                # re-raise cancellation
+                raise
+
+        task = self.loop.create_task(run())
+        with self.assertRaisesRegex(
+            asyncio.CancelledError,
+            "" if sys.version_info < (3, 11) else "custom cancellation 
message",
+        ):
+            self.loop.run_until_complete(task)
+
     def test_not_completed(self):
         """Querying an uncompleted task raises exceptions."""
         f = Gio.file_new_for_path("./")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/tests/test_gi.py 
new/pygobject-3.56.3/tests/test_gi.py
--- old/pygobject-3.56.2/tests/test_gi.py       2026-03-25 16:01:00.000000000 
+0100
+++ new/pygobject-3.56.3/tests/test_gi.py       2026-05-08 22:10:32.000000000 
+0200
@@ -20,7 +20,7 @@
 from gi.repository import GIMarshallingTests
 import pytest
 
-from .helper import capture_exceptions, capture_output
+from .helper import capture_exceptions, capture_glib_warnings, capture_output
 import contextlib
 
 
@@ -2574,6 +2574,12 @@
         del in_struct
         del out_struct
 
+    def test_pointer_array_struct_with_guint8(self):
+        out_struct = GIMarshallingTests.PointerArrayStruct.with_uint8_array()
+
+        with capture_glib_warnings(allow_warnings=True):
+            assert out_struct.array == list(map(ord, "0123456789"))
+
     def test_struct_field_assignment(self):
         struct = GIMarshallingTests.BoxedStruct()
 
@@ -3107,6 +3113,42 @@
         GIMarshallingTests.callback_owned_boxed(nop_callback, None)
         self.assertEqual(self.box.long_, 1)
 
+    def test_callback_user_data_after_callback(self):
+        def callback(*args):
+            self.callback_args = args
+
+        GIMarshallingTests.callback_user_data_after_callback(1, 2, callback)
+        self.assertEqual(self.callback_args, (1, 2))
+
+        GIMarshallingTests.callback_user_data_after_callback(3, 4, callback, 
"testdata")
+        self.assertEqual(self.callback_args, (3, 4, "testdata"))
+
+        GIMarshallingTests.callback_user_data_after_callback(
+            5, 6, callback, "more testdata", "even more testdata"
+        )
+        self.assertEqual(
+            self.callback_args, (5, 6, "more testdata", "even more testdata")
+        )
+
+    def test_callback_user_data_before_callback(self):
+        def callback(*args):
+            self.callback_args = args
+
+        GIMarshallingTests.callback_user_data_before_callback(1, 2, None, 
callback)
+        self.assertEqual(self.callback_args, (1, 2, None))
+
+        GIMarshallingTests.callback_user_data_before_callback(
+            3, 4, "testdata", callback
+        )
+        self.assertEqual(self.callback_args, (3, 4, "testdata"))
+
+        GIMarshallingTests.callback_user_data_before_callback(
+            5, 6, ("more testdata", "even more testdata"), callback
+        )
+        self.assertEqual(
+            self.callback_args, (5, 6, ("more testdata", "even more testdata"))
+        )
+
 
 class TestMultiOutputArgs(unittest.TestCase):
     def test_int_out_out(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pygobject-3.56.2/tests/test_gtk_template.py 
new/pygobject-3.56.3/tests/test_gtk_template.py
--- old/pygobject-3.56.2/tests/test_gtk_template.py     2026-03-25 
16:01:00.000000000 +0100
+++ new/pygobject-3.56.3/tests/test_gtk_template.py     2026-05-08 
22:10:32.000000000 +0200
@@ -1,5 +1,6 @@
-import tempfile
+import gc
 import os
+import tempfile
 import weakref
 
 import pytest
@@ -782,3 +783,31 @@
     assert "CustomBox -> GObject finalized" in finalized
     assert "CustomLabel -> PyObject finalized" in finalized
     assert "CustomLabel -> GObject finalized" in finalized
+
+
+def test_signal_handler_with_object_does_not_leak_memory():
+    """Regression test for a memory leak when using signal handlers in GTK 
templates.
+    Note that this example is intentionally minimal, i.e. the handler doesn't 
even
+    need to exist on the class. The only requirement is that the `object` is 
specified.
+    """
+    type_name = new_gtype_name()
+    xml = f"""\
+    <?xml version="1.0" encoding="UTF-8"?>
+    <interface>
+    <requires lib="gtk" version="4.0" />
+    <template class="{type_name}" parent="GtkWidget">
+        <signal name="show" handler="on_show" object="{type_name}" 
swapped="no" />
+    </template>
+    </interface>
+    """
+
+    @Gtk.Template(string=xml)
+    class MyWidget(Gtk.Widget):
+        __gtype_name__ = type_name
+
+    weak = MyWidget().weak_ref()
+
+    gc.collect()
+    gc.collect()  # One more for PyPy
+
+    assert weak() is None

++++++ pygobject.obsinfo ++++++
--- /var/tmp/diff_new_pack.G1R32w/_old  2026-05-13 17:20:49.783008190 +0200
+++ /var/tmp/diff_new_pack.G1R32w/_new  2026-05-13 17:20:49.831010174 +0200
@@ -1,5 +1,5 @@
 name: pygobject
-version: 3.56.2
-mtime: 1774450860
-commit: 3e62df853e7bd3e65abfc887b09616d9803ef048
+version: 3.56.3
+mtime: 1778271032
+commit: 57b42b3423227010946db6fd84aad72c734ddf63
 

Reply via email to