Tests failing with python 3.12

Bug #2076095 reported by Miriam España Acebal
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
magicgui (Debian)
New
Unknown
magicgui (Ubuntu)
New
Undecided
Unassigned

Bug Description

When pysignal trigger magicgui, we found regressions for all archs. The relevant part of the failures are (from [1]):

 pybuild-autopkgtest
269s I: pybuild base:311: cd /tmp/autopkgtest.RWhG6j/autopkgtest_tmp/build; python3.12 -m pytest tests
270s ============================= test session starts ==============================
270s platform linux -- Python 3.12.4, pytest-7.4.4, pluggy-1.5.0
270s PyQt5 5.15.11 -- Qt runtime 5.15.13 -- Qt compiled 5.15.13
270s rootdir: /tmp/autopkgtest.RWhG6j/autopkgtest_tmp/build
270s configfile: pyproject.toml
270s plugins: qt-4.3.1, xvfb-3.0.0
270s collected 313 items / 3 skipped
270s
270s tests/test_application.py . [ 0%]
270s tests/test_backends.py s......... [ 3%]
270s tests/test_container.py .............. [ 7%]
270s tests/test_docs.py ss. [ 8%]
270s tests/test_factory.py .......... [ 12%]
270s tests/test_gui_class.py F.FFF [ 13%]
271s tests/test_magicgui.py ...................x............................. [ 29%]
271s [ 29%]
272s tests/test_persistence.py ... [ 30%]
272s tests/test_signature.py .... [ 31%]
272s tests/test_table.py ............................sss......... [ 44%]
272s tests/test_types.py ............... [ 49%]
272s tests/test_ui_field.py ..ss....ss. [ 52%]
273s tests/test_widgets.py ......s.s..ss..s.ss..ss.sss.s..s.........s......s. [ 68%]
275s s.......s..s............................................................ [ 91%]
275s .......................... [100%]
275s
275s =================================== FAILURES ===================================
275s ________________________________ test_guiclass _________________________________
275s
275s def test_guiclass():
275s """Test that the guiclass decorator works as expected."""
275s mock = Mock()
275s
275s @guiclass
275s class Foo:
275s a: int = 1
275s b: str = "bar"
275s
275s @button
275s def func(self):
275s mock(asdict(self))
275s
275s # example recommended for type checking
275s if TYPE_CHECKING:
275s gui: ClassVar[Container]
275s events: ClassVar[psygnal.SignalGroup]
275s
275s foo = Foo()
275s
275s assert foo.a == 1
275s assert foo.b == "bar"
275s
275s > assert isinstance(foo.gui, Container)
275s
275s tests/test_gui_class.py:43:
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:233: in __get__
275s bind_gui_to_instance(wdg, instance)
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:274: in bind_gui_to_instance
275s widget.changed.connect_setattr(
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s
275s self = <SignalInstance 'changed' on SpinBox(value=1, annotation=<class 'int'>, name='a')>
275s obj = test_guiclass.<locals>.Foo(a=1, b='bar'), attr = 'a'
275s maxargs = <object object at 0x74ef2bd01e60>
275s
275s def connect_setattr(
275s self,
275s obj: object,
275s attr: str,
275s maxargs: int | None | object = _NULL,
275s *,
275s on_ref_error: RefErrorChoice = "warn",
275s priority: int = 0,
275s ) -> WeakCallback[None]:
275s """Bind an object attribute to the emitted value of this signal.
275s
275s Equivalent to calling `self.connect(functools.partial(setattr, obj, attr))`,
275s but with additional weakref safety (i.e. a strong reference to `obj` will not
275s be retained). The return object can be used to
275s [`disconnect()`][psygnal.SignalInstance.disconnect], (or you can use
275s [`disconnect_setattr()`][psygnal.SignalInstance.disconnect_setattr]).
275s
275s Parameters
275s ----------
275s obj : object
275s An object.
275s attr : str
275s The name of an attribute on `obj` that should be set to the value of this
275s signal when emitted.
275s maxargs : Optional[int]
275s max number of positional args to accept
275s on_ref_error: {'raise', 'warn', 'ignore'}, optional
275s What to do if a weak reference cannot be created. If 'raise', a
275s ReferenceError will be raised. If 'warn' (default), a warning will be
275s issued and a strong-reference will be used. If 'ignore' a strong-reference
275s will be used (silently).
275s priority : int
275s The priority of the callback. This is used to determine the order in which
275s callbacks are called when multiple are connected to the same signal.
275s Higher priority callbacks are called first. Negative values are allowed.
275s The default is 0.
275s
275s Returns
275s -------
275s Tuple
275s (weakref.ref, name, callable). Reference to the object, name of the
275s attribute, and setattr closure. Can be used to disconnect the slot.
275s
275s Raises
275s ------
275s ValueError
275s If this is not a single-value signal
275s AttributeError
275s If `obj` has no attribute `attr`.
275s
275s Examples
275s --------
275s >>> class T:
275s ... sig = Signal(int)
275s >>> class SomeObj:
275s ... x = 1
275s >>> t = T()
275s >>> my_obj = SomeObj()
275s >>> t.sig.connect_setattr(my_obj, "x")
275s >>> t.sig.emit(5)
275s >>> assert my_obj.x == 5
275s """
275s if maxargs is _NULL:
275s > warnings.warn(
275s "The default value of maxargs will change from `None` to `1` in "
275s "version 0.11. To silence this warning, provide an explicit value for "
275s "maxargs (`None` for current behavior, `1` for future behavior).",
275s FutureWarning,
275s stacklevel=2,
275s )
275s E FutureWarning: The default value of maxargs will change from `None` to `1` in version 0.11. To silence this warning, provide an explicit value for maxargs (`None` for current behavior, `1` for future behavior).
275s
275s /usr/lib/python3/dist-packages/psygnal/_signal.py:858: FutureWarning
275s __________________________ test_on_existing_dataclass __________________________
275s
275s def test_on_existing_dataclass():
275s """Test that the guiclass decorator works on pre-existing dataclasses."""
275s
275s @guiclass
275s @dataclass
275s class Foo:
275s a: int = 1
275s b: str = "bar"
275s
275s foo = Foo()
275s assert foo.a == 1
275s assert foo.b == "bar"
275s > assert isinstance(foo.gui, Container)
275s
275s tests/test_gui_class.py:83:
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:233: in __get__
275s bind_gui_to_instance(wdg, instance)
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:274: in bind_gui_to_instance
275s widget.changed.connect_setattr(
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s
275s self = <SignalInstance 'changed' on SpinBox(value=1, annotation=<class 'int'>, name='a')>
275s obj = test_on_existing_dataclass.<locals>.Foo(a=1, b='bar'), attr = 'a'
275s maxargs = <object object at 0x74ef2bd01e60>
275s
275s def connect_setattr(
275s self,
275s obj: object,
275s attr: str,
275s maxargs: int | None | object = _NULL,
275s *,
275s on_ref_error: RefErrorChoice = "warn",
275s priority: int = 0,
275s ) -> WeakCallback[None]:
275s """Bind an object attribute to the emitted value of this signal.
275s
275s Equivalent to calling `self.connect(functools.partial(setattr, obj, attr))`,
275s but with additional weakref safety (i.e. a strong reference to `obj` will not
275s be retained). The return object can be used to
275s [`disconnect()`][psygnal.SignalInstance.disconnect], (or you can use
275s [`disconnect_setattr()`][psygnal.SignalInstance.disconnect_setattr]).
275s
275s Parameters
275s ----------
275s obj : object
275s An object.
275s attr : str
275s The name of an attribute on `obj` that should be set to the value of this
275s signal when emitted.
275s maxargs : Optional[int]
275s max number of positional args to accept
275s on_ref_error: {'raise', 'warn', 'ignore'}, optional
275s What to do if a weak reference cannot be created. If 'raise', a
275s ReferenceError will be raised. If 'warn' (default), a warning will be
275s issued and a strong-reference will be used. If 'ignore' a strong-reference
275s will be used (silently).
275s priority : int
275s The priority of the callback. This is used to determine the order in which
275s callbacks are called when multiple are connected to the same signal.
275s Higher priority callbacks are called first. Negative values are allowed.
275s The default is 0.
275s
275s Returns
275s -------
275s Tuple
275s (weakref.ref, name, callable). Reference to the object, name of the
275s attribute, and setattr closure. Can be used to disconnect the slot.
275s
275s Raises
275s ------
275s ValueError
275s If this is not a single-value signal
275s AttributeError
275s If `obj` has no attribute `attr`.
275s
275s Examples
275s --------
275s >>> class T:
275s ... sig = Signal(int)
275s >>> class SomeObj:
275s ... x = 1
275s >>> t = T()
275s >>> my_obj = SomeObj()
275s >>> t.sig.connect_setattr(my_obj, "x")
275s >>> t.sig.emit(5)
275s >>> assert my_obj.x == 5
275s """
275s if maxargs is _NULL:
275s > warnings.warn(
275s "The default value of maxargs will change from `None` to `1` in "
275s "version 0.11. To silence this warning, provide an explicit value for "
275s "maxargs (`None` for current behavior, `1` for future behavior).",
275s FutureWarning,
275s stacklevel=2,
275s )
275s E FutureWarning: The default value of maxargs will change from `None` to `1` in version 0.11. To silence this warning, provide an explicit value for maxargs (`None` for current behavior, `1` for future behavior).
275s
275s /usr/lib/python3/dist-packages/psygnal/_signal.py:858: FutureWarning
275s _____________________________ test_slots_guiclass ______________________________
275s
275s @pytest.mark.skipif(sys.version_info < (3, 10), reason="slots are python3.10 or higher")
275s def test_slots_guiclass():
275s """Test that the guiclass decorator works as expected."""
275s
275s psyg_v = tuple(int(x.split("r")[0]) for x in psygnal.__version__.split(".")[:3])
275s old_psygnal = psyg_v < (0, 6, 1)
275s
275s @guiclass(slots=True)
275s class Foo:
275s a: int = 1
275s b: str = "bar"
275s
275s foo = Foo()
275s
275s with (
275s pytest.warns(UserWarning, match="Please update psygnal")
275s if old_psygnal
275s else contextlib.nullcontext()
275s ):
275s > gui = foo.gui
275s
275s tests/test_gui_class.py:105:
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:233: in __get__
275s bind_gui_to_instance(wdg, instance)
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:274: in bind_gui_to_instance
275s widget.changed.connect_setattr(
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s
275s self = <SignalInstance 'changed' on SpinBox(value=1, annotation=<class 'int'>, name='a')>
275s obj = test_slots_guiclass.<locals>.Foo(a=1, b='bar'), attr = 'a'
275s maxargs = <object object at 0x74ef2bd01e60>
275s
275s def connect_setattr(
275s self,
275s obj: object,
275s attr: str,
275s maxargs: int | None | object = _NULL,
275s *,
275s on_ref_error: RefErrorChoice = "warn",
275s priority: int = 0,
275s ) -> WeakCallback[None]:
275s """Bind an object attribute to the emitted value of this signal.
275s
275s Equivalent to calling `self.connect(functools.partial(setattr, obj, attr))`,
275s but with additional weakref safety (i.e. a strong reference to `obj` will not
275s be retained). The return object can be used to
275s [`disconnect()`][psygnal.SignalInstance.disconnect], (or you can use
275s [`disconnect_setattr()`][psygnal.SignalInstance.disconnect_setattr]).
275s
275s Parameters
275s ----------
275s obj : object
275s An object.
275s attr : str
275s The name of an attribute on `obj` that should be set to the value of this
275s signal when emitted.
275s maxargs : Optional[int]
275s max number of positional args to accept
275s on_ref_error: {'raise', 'warn', 'ignore'}, optional
275s What to do if a weak reference cannot be created. If 'raise', a
275s ReferenceError will be raised. If 'warn' (default), a warning will be
275s issued and a strong-reference will be used. If 'ignore' a strong-reference
275s will be used (silently).
275s priority : int
275s The priority of the callback. This is used to determine the order in which
275s callbacks are called when multiple are connected to the same signal.
275s Higher priority callbacks are called first. Negative values are allowed.
275s The default is 0.
275s
275s Returns
275s -------
275s Tuple
275s (weakref.ref, name, callable). Reference to the object, name of the
275s attribute, and setattr closure. Can be used to disconnect the slot.
275s
275s Raises
275s ------
275s ValueError
275s If this is not a single-value signal
275s AttributeError
275s If `obj` has no attribute `attr`.
275s
275s Examples
275s --------
275s >>> class T:
275s ... sig = Signal(int)
275s >>> class SomeObj:
275s ... x = 1
275s >>> t = T()
275s >>> my_obj = SomeObj()
275s >>> t.sig.connect_setattr(my_obj, "x")
275s >>> t.sig.emit(5)
275s >>> assert my_obj.x == 5
275s """
275s if maxargs is _NULL:
275s > warnings.warn(
275s "The default value of maxargs will change from `None` to `1` in "
275s "version 0.11. To silence this warning, provide an explicit value for "
275s "maxargs (`None` for current behavior, `1` for future behavior).",
275s FutureWarning,
275s stacklevel=2,
275s )
275s E FutureWarning: The default value of maxargs will change from `None` to `1` in version 0.11. To silence this warning, provide an explicit value for maxargs (`None` for current behavior, `1` for future behavior).
275s
275s /usr/lib/python3/dist-packages/psygnal/_signal.py:858: FutureWarning
275s ____________________________ test_guiclass_as_class ____________________________
275s
275s def test_guiclass_as_class():
275s # variant on @guiclass, using class instead of decorator
275s class T2(GuiClass):
275s x: int
275s y: str = "hi"
275s
275s @button
275s def foo(self):
275s return asdict(self)
275s
275s t2 = T2(1)
275s assert t2.x == 1
275s assert t2.y == "hi"
275s > assert t2.gui.x.value == 1
275s
275s tests/test_gui_class.py:141:
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:233: in __get__
275s bind_gui_to_instance(wdg, instance)
275s /usr/lib/python3/dist-packages/magicgui/schema/_guiclass.py:274: in bind_gui_to_instance
275s widget.changed.connect_setattr(
275s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
275s
275s self = <SignalInstance 'changed' on SpinBox(value=1, annotation=<class 'int'>, name='x')>
275s obj = test_guiclass_as_class.<locals>.T2(x=1, y='hi'), attr = 'x'
275s maxargs = <object object at 0x74ef2bd01e60>
275s
275s def connect_setattr(
275s self,
275s obj: object,
275s attr: str,
275s maxargs: int | None | object = _NULL,
275s *,
275s on_ref_error: RefErrorChoice = "warn",
275s priority: int = 0,
275s ) -> WeakCallback[None]:
275s """Bind an object attribute to the emitted value of this signal.
275s
275s Equivalent to calling `self.connect(functools.partial(setattr, obj, attr))`,
275s but with additional weakref safety (i.e. a strong reference to `obj` will not
275s be retained). The return object can be used to
275s [`disconnect()`][psygnal.SignalInstance.disconnect], (or you can use
275s [`disconnect_setattr()`][psygnal.SignalInstance.disconnect_setattr]).
275s
275s Parameters
275s ----------
275s obj : object
275s An object.
275s attr : str
275s The name of an attribute on `obj` that should be set to the value of this
275s signal when emitted.
275s maxargs : Optional[int]
275s max number of positional args to accept
275s on_ref_error: {'raise', 'warn', 'ignore'}, optional
275s What to do if a weak reference cannot be created. If 'raise', a
275s ReferenceError will be raised. If 'warn' (default), a warning will be
275s issued and a strong-reference will be used. If 'ignore' a strong-reference
275s will be used (silently).
275s priority : int
275s The priority of the callback. This is used to determine the order in which
275s callbacks are called when multiple are connected to the same signal.
275s Higher priority callbacks are called first. Negative values are allowed.
275s The default is 0.
275s
275s Returns
275s -------
275s Tuple
275s (weakref.ref, name, callable). Reference to the object, name of the
275s attribute, and setattr closure. Can be used to disconnect the slot.
275s
275s Raises
275s ------
275s ValueError
275s If this is not a single-value signal
275s AttributeError
275s If `obj` has no attribute `attr`.
275s
275s Examples
275s --------
275s >>> class T:
275s ... sig = Signal(int)
275s >>> class SomeObj:
275s ... x = 1
275s >>> t = T()
275s >>> my_obj = SomeObj()
275s >>> t.sig.connect_setattr(my_obj, "x")
275s >>> t.sig.emit(5)
275s >>> assert my_obj.x == 5
275s """
275s if maxargs is _NULL:
275s > warnings.warn(
275s "The default value of maxargs will change from `None` to `1` in "
275s "version 0.11. To silence this warning, provide an explicit value for "
275s "maxargs (`None` for current behavior, `1` for future behavior).",
275s FutureWarning,
275s stacklevel=2,
275s )
275s E FutureWarning: The default value of maxargs will change from `None` to `1` in version 0.11. To silence this warning, provide an explicit value for maxargs (`None` for current behavior, `1` for future behavior).
275s
275s /usr/lib/python3/dist-packages/psygnal/_signal.py:858: FutureWarning
275s =========================== short test summary info ============================
275s FAILED tests/test_gui_class.py::test_guiclass - FutureWarning: The default va...
275s FAILED tests/test_gui_class.py::test_on_existing_dataclass - FutureWarning: T...
275s FAILED tests/test_gui_class.py::test_slots_guiclass - FutureWarning: The defa...
275s FAILED tests/test_gui_class.py::test_guiclass_as_class - FutureWarning: The d...
275s ============= 4 failed, 279 passed, 32 skipped, 1 xfailed in 5.97s =============
276s E: pybuild pybuild:389: test: plugin pyproject failed with: exit code=1: cd /tmp/autopkgtest.RWhG6j/autopkgtest_tmp/build; python3.12 -m pytest tests
276s pybuild-autopkgtest: error: pybuild --autopkgtest --test-pytest -i python{version} -p 3.12 returned exit code 13
276s make: *** [/tmp/dc8bKKY9VU/run:4: pybuild-autopkgtest] Error 25

On upstream, this test are passing [2] with pyside6 (installing from pip). I tried adding python3-pyqt and python3-pyqt6 to d/control to see if this overcomes it and mimic the upstream's actions [3], with no luck

[1] https://objectstorage.prodstack5.canonical.com/swift/v1/AUTH_0f9aae918d5b4744bf7b827671c86842/autopkgtest-oracular/oracular/amd64/m/magicgui/20240804_072247_72842@/log.gz
[2] https://github.com/pyapp-kit/magicgui/actions/runs/10240968558/job/28328574711
[3] https://github.com/pyapp-kit/magicgui/actions/runs/10240968558/workflow

Changed in magicgui (Debian):
status: Unknown → New
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.