Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better disconnect cleanup on qmenus #160

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ classifiers = [
]
dynamic = ["version"]
dependencies = [
"psygnal>=0.3.4",
"psygnal>=0.9.5",
"pydantic>=1.8",
"pydantic-compat>=0.1.1",
"in-n-out>=0.1.5",
Expand Down
24 changes: 11 additions & 13 deletions src/app_model/backends/qt/_qmenu.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import contextlib
from typing import TYPE_CHECKING, Collection, Iterable, Mapping, Sequence, cast

from qtpy.QtWidgets import QMenu, QMenuBar, QToolBar
Expand Down Expand Up @@ -52,7 +51,11 @@ def __init__(
self.setObjectName(menu_id)
self.rebuild()
self._app.menus.menus_changed.connect(self._on_registry_changed)
self.destroyed.connect(self._disconnect)

@self.destroyed.connect # type: ignore
def _disconnect() -> None:
self._app.menus.menus_changed.disconnect(self._on_registry_changed)

# ----------------------

if title is not None:
Expand Down Expand Up @@ -106,15 +109,9 @@ def _on_about_to_show(self) -> None:
if isinstance(action, QCommandRuleAction):
action._refresh()

def _disconnect(self) -> None:
self._app.menus.menus_changed.disconnect(self._on_registry_changed)

def _on_registry_changed(self, changed_ids: set[str]) -> None:
if self._menu_id in changed_ids:
# if this (sub)menu has been removed from the registry,
# we may hit a RuntimeError when trying to rebuild it.
with contextlib.suppress(RuntimeError):
self.rebuild()
self.rebuild()


class QModelSubmenu(QModelMenu):
Expand Down Expand Up @@ -192,7 +189,11 @@ def __init__(
self.setObjectName(menu_id)
self.rebuild()
self._app.menus.menus_changed.connect(self._on_registry_changed)
self.destroyed.connect(self._disconnect)

@self.destroyed.connect # type: ignore
def _disconnect() -> None:
self._app.menus.menus_changed.disconnect(self._on_registry_changed)

# ----------------------

if title is not None:
Expand Down Expand Up @@ -243,9 +244,6 @@ def rebuild(
exclude=self._exclude if exclude is None else exclude,
)

def _disconnect(self) -> None:
self._app.menus.menus_changed.disconnect(self._on_registry_changed)

def _on_registry_changed(self, changed_ids: set[str]) -> None:
if self._menu_id in changed_ids:
self.rebuild()
Expand Down
7 changes: 6 additions & 1 deletion src/app_model/registries/_menus_reg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from logging import getLogger
from typing import TYPE_CHECKING, Any, Callable, Final, Iterable, Iterator, Sequence

from psygnal import Signal
Expand All @@ -10,6 +11,7 @@
from app_model.types import DisposeCallable, MenuOrSubmenu

MenuId = str
logger = getLogger(__name__)


class MenusRegistry:
Expand Down Expand Up @@ -55,7 +57,10 @@
for id_ in changed_ids:
if not self._menu_items.get(id_):
del self._menu_items[id_]
self.menus_changed.emit(changed_ids)
try:
self.menus_changed.emit(changed_ids)
except Exception as e:
logger.exception("Error during menu disposal: %s", e)

Check warning on line 63 in src/app_model/registries/_menus_reg.py

View check run for this annotation

Codecov / codecov/patch

src/app_model/registries/_menus_reg.py#L62-L63

Added lines #L62 - L63 were not covered by tests

if changed_ids:
self.menus_changed.emit(changed_ids)
Expand Down
2 changes: 0 additions & 2 deletions tests/test_qt/test_qmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ def test_menu(
with pytest.raises(NameError, match="Names required to eval this expression"):
menu.update_from_context({})

menu._disconnect()


def test_submenu(qtbot: QtBot, full_app: FullApp) -> None:
app = full_app
Expand Down
Loading