dbus-python: Unimportable module when building in Python 3.15
Maximiliano Curia <[email protected]>
| Newsgroups | gmane.linux.debian.devel.python |
|---|---|
| Message-ID | <[email protected]> |
Package: src:dbus-python Version: 1.4.0-1 User: [email protected] Usertags: python3.15 Hi! While rebuilding packages against Python 3.15 we found that dbus-python failed to build from source due to failing tests. All the tests were saying something like: test: dbus-python:standalone start time: 10:20:31 duration: 0.05s result: exit status 1 command: DBUS_TEST_TMPDIR=/build/reproducible-path/dbus-python-1.4.0/build-3.15/test DBUS_TOP_SRCDIR=/build/reproducible-path/dbus-python-1.4.0 DBUS_PYTHON_VERSION=1.4.0 MALLOC_PERTURB_=171 UBSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 PYTHONPATH=/build/reproducible-path/dbus-python-1.4.0:/build/reproducible-path/dbus-python-1.4.0/test:/build/reproducible-path/dbus-python-1.4.0/build-3.15:/build/reproducible-path/dbus-python-1.4.0/build-3.15/test MSAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1 ASAN_OPTIONS=halt_on_error=1:abort_on_error=1:print_summary=1 DBUS_TEST_UNINSTALLED=1 DBUS_FATAL_WARNINGS=1 MESON_TEST_ITERATION=1 DBUS_TOP_BUILDDIR=/build/reproducible-path/dbus-python-1.4.0/build-3.15 /usr/bin/dbus-run-session --config-file /build/reproducible-path/dbus-python-1.4.0/build-3.15/test/tmp-session-bus.conf -- /usr/bin/python3.15 /build/reproducible-path/dbus-python-1.4.0/build-3.15/../test/test-standalone.py ----------------------------------- stderr ----------------------------------- Traceback (most recent call last): File "/build/reproducible-path/dbus-python-1.4.0/build-3.15/../test/test-standalone.py", line 39, in <module> import _dbus_bindings SystemError: type _dbus_bindings.Connection has the Py_TPFLAGS_MANAGED_WEAKREF flag but not Py_TPFLAGS_HAVE_GC flag The problem seems to be caused by the fact that the Connection is a GenericAlloc that's missing the PyGC_Head header header, this is now detected in Python 3.15 (see: https://github.com/python/cpython/issues/134786). The weakref was introduced by ebecd174 but the previous mechanism still works, so I'm reverting ebecd174 and adding a regression test that should fail in python 3.12 to 3.14. Happy hacking, -- "Backtracking algorithms are nondeterministic, not in the sense of being random, but in the sense of having free will." -- Robert W. Floyd Saludos /\/\ /\ >< `/
no-managed-weakref-without-gc.patch
(text/x-diff, 5.3 KB)
From: Maximiliano Curia <[email protected]> Date: Sat, 16 Aug 2026 12:00:00 +0200 Subject: Don't use Py_TPFLAGS_MANAGED_WEAKREF on types without Py_TPFLAGS_HAVE_GC Revert ebecd174 plus regression test. Forwarded: no Last-Update: 2026-08-16 --- Index: dbus-python/dbus_bindings/conn-internal.h =================================================================== --- dbus-python.orig/dbus_bindings/conn-internal.h +++ dbus-python/dbus_bindings/conn-internal.h @@ -42,10 +42,8 @@ typedef struct { */ PyObject *object_paths; -#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) /* Weak-references list to make Connections weakly referenceable */ PyObject *weaklist; -#endif dbus_bool_t has_mainloop; } Connection; Index: dbus-python/dbus_bindings/conn.c =================================================================== --- dbus-python.orig/dbus_bindings/conn.c +++ dbus-python/dbus_bindings/conn.c @@ -238,9 +238,7 @@ DBusPyConnection_NewConsumingDBusConnect self->has_mainloop = (mainloop != Py_None); self->conn = NULL; self->filters = PyList_New(0); -#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) self->weaklist = NULL; -#endif if (!self->filters) goto err; self->object_paths = PyDict_New(); if (!self->object_paths) goto err; @@ -394,10 +392,7 @@ static void Connection_tp_dealloc(Connec /* avoid clobbering any pending exception */ PyErr_Fetch(&et, &ev, &etb); -#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) - if (self->weaklist) -#endif - { + if (self->weaklist) { PyObject_ClearWeakRefs((PyObject *)self); } @@ -460,19 +455,12 @@ PyTypeObject DBusPyConnection_Type = { 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ -#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) - Py_TPFLAGS_MANAGED_WEAKREF | -#endif Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, Connection_tp_doc, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ -#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) - 0, /*tp_weaklistoffset*/ -#else offsetof(Connection, weaklist), /*tp_weaklistoffset*/ -#endif 0, /*tp_iter*/ 0, /*tp_iternext*/ DBusPyConnection_tp_methods, /*tp_methods*/ Index: dbus-python/dbus_bindings/server.c =================================================================== --- dbus-python.orig/dbus_bindings/server.c +++ dbus-python/dbus_bindings/server.c @@ -38,10 +38,8 @@ typedef struct { /* The Connection subtype for which this Server is a factory */ PyObject *conn_class; -#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) /* Weak-references list to make server weakly referenceable */ PyObject *weaklist; -#endif PyObject *mainloop; } Server; @@ -425,9 +423,7 @@ Server_tp_new(PyTypeObject *cls, PyObjec return NULL; } -#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) ((Server *)self)->weaklist = NULL; -#endif TRACE(self); return self; @@ -442,10 +438,7 @@ static void Server_tp_dealloc(Server *se /* avoid clobbering any pending exception */ PyErr_Fetch(&et, &ev, &etb); -#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) - if (self->weaklist) -#endif - { + if (self->weaklist) { PyObject_ClearWeakRefs((PyObject *)self); } @@ -577,19 +570,12 @@ PyTypeObject DBusPyServer_Type = { 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ -#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) - Py_TPFLAGS_MANAGED_WEAKREF | -#endif Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, Server_tp_doc, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ -#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0) - 0, /*tp_weaklistoffset*/ -#else offsetof(Server, weaklist), /*tp_weaklistoffset*/ -#endif 0, /*tp_iter*/ 0, /*tp_iternext*/ DBusPyServer_tp_methods,/*tp_methods*/ Index: dbus-python/test/test-client.py =================================================================== --- dbus-python.orig/test/test-client.py +++ dbus-python/test/test-client.py @@ -110,6 +110,22 @@ class TestDBusBindings(unittest.TestCase del bus self.assertTrue(ref() is None) + def testWeakRefsToBaseConnection(self): + # dbus.SessionBus() is a Python subclass, which always has + # Py_TPFLAGS_HAVE_GC; the C types do not, so they need their own + # coverage. Marking a non-GC type Py_TPFLAGS_MANAGED_WEAKREF makes + # CPython look for the weakref slot in the PyGC_Head that was never + # allocated, which reads and writes off the front of the object. + address = os.environ['DBUS_SESSION_BUS_ADDRESS'] + conn = _dbus_bindings.Connection(address) + try: + ref = weakref.ref(conn) + self.assertTrue(ref() is conn) + finally: + conn.close() + del conn + self.assertTrue(ref() is None) + def testInterfaceKeyword(self): #test dbus_interface parameter print(self.remote_object.Echo("dbus_interface on Proxy test Passed",
signature.asc
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE+JIdOnQEyG4RNSIVxxl2mbKbIyoFAmqBumUACgkQxxl2mbKb Iyro3g/9EHffZENxLbCDoyX8YZvKJ+MA4Zyx/Td8w/+ztSVK78TnhUnsmU7694ba B5qNYxWvMnV4j8lSPTvd1bbZNDnUtWsMSf8+M24cc9UXtMHxgQ1LCbdCta+dG2AT oNt+o0wIIq1o+ODKvtWoFwuhip6m40YKiehK/816J/aTG2/n8C4aSpLCzV1RoGSo 3ujjaif2GfZaFLxNrjsScLp0hGA1h2Z4CabEXLJhumYn6Dv9GZ5w2Ge1TavnElMB oy0xBz01RIK+XsMIXR/ACgjgITZNKMAD865ZdxS18AuBkPCqIrJhe0HX0HlnHXda xjpvIrE3Pyw5cCdwbyWAvkCUy0u+lB7HQ7vvxZqVx1+0xft2aZqjTrrvyj2kIy2E 3TRVYYg5V/fAD1aNuZFNxuIVEkL7dZ7vh5GhAwOa6L9S0FH29/aIR5G3E9WinluK fxcZAK2ahwJiTKCZB3W2crLu8Vgsx79abKI9oW+95ygZ53dDLC2bimjCEIJYIgSd KMp+JMDEoHSZX/PMjKTYBNZGP02dy9ePANBvWHRSioEQX+DQU0VN0m6YqmukPrFr AaOsIY+euPd1LxgWi9ZroCWtJUR8LulrjpzWVcpByzJl74WPoqvKwGh1eRFVx8+x 9g/tcVhdYsSi5tTST/3CQe/fteHvlJQ63lelhA/qVjA+VGBBY4M= =2k7R -----END PGP SIGNATURE-----