1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
Description: avoid too new pygobject
This essentially reverts upstream git commit 6205a6c.
Author: Jonas Smedegaard <dr@jones.dk>
Bug-Debian: https://bugs.debian.org/1111931
Last-Update: 2025-08-26
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/dialect/asyncio.py
+++ b/dialect/asyncio.py
@@ -1,12 +1,41 @@
+import asyncio
+import contextlib
import functools
from typing import Callable, Coroutine
-from gi.repository import Gio
+from gi.events import GLibEventLoopPolicy
+
+
+@contextlib.contextmanager
+def glib_event_loop_policy():
+ original = asyncio.get_event_loop_policy()
+ policy = GLibEventLoopPolicy()
+ asyncio.set_event_loop_policy(policy)
+ try:
+ yield policy
+ finally:
+ asyncio.set_event_loop_policy(original)
+
+
+_background_tasks: set[asyncio.Task] = set()
+
+
+def create_background_task(coro: Coroutine) -> asyncio.Task:
+ """
+ Create and track a task.
+
+ Normally tasks are weak-referenced by asyncio.
+ We keep track of them, so they can be completed before GC kicks in.
+ """
+ task = asyncio.create_task(coro)
+ _background_tasks.add(task)
+ task.add_done_callback(_background_tasks.discard)
+ return task
def background_task(f: Callable[..., Coroutine]):
"""
- Wraps an async function to be run using ``Gio.Application.create_asyncio_task``.
+ Wraps an async function to be run using ``create_background_task``.
Useful to use async functions like signal handlers or GTK template callbacks.
@@ -16,7 +45,6 @@
@functools.wraps(f)
def decor(*args, **kwargs):
- app = Gio.Application.get_default()
- app.create_asyncio_task(f(*args, **kwargs))
+ create_background_task(f(*args, **kwargs))
return decor
--- a/dialect/main.py
+++ b/dialect/main.py
@@ -4,12 +4,10 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# Initial setup
-import asyncio
import logging
import sys
import gi
-from gi.events import GLibEventLoopPolicy
try:
gi.require_version("Gdk", "4.0")
@@ -25,6 +23,7 @@
except ImportError or ValueError:
logging.error("Error: GObject dependencies not met.")
+from dialect.asyncio import glib_event_loop_policy
from dialect.define import APP_ID, RES_PATH, VERSION
from dialect.preferences import DialectPreferencesDialog
from dialect.settings import Settings
@@ -197,8 +196,11 @@
def main():
- # Set the asyncio event loop policy from PyGObject
- asyncio.set_event_loop_policy(GLibEventLoopPolicy())
# Run the Application
app = Dialect()
- return app.run(sys.argv)
+ exit_code = 0
+
+ with glib_event_loop_policy():
+ exit_code = app.run(sys.argv)
+
+ return exit_code
--- a/dialect/widgets/provider_preferences.py
+++ b/dialect/widgets/provider_preferences.py
@@ -10,7 +10,7 @@
from gi.repository import Adw, GObject, Gtk
-from dialect.asyncio import background_task
+from dialect.asyncio import create_background_task
from dialect.define import RES_PATH
from dialect.providers import ProviderCapability, RequestError
@@ -74,9 +74,8 @@
self.api_usage_group.props.visible = False
if self.provider.supports_api_usage:
- self._load_api_usage()
+ create_background_task(self._load_api_usage())
- @background_task
async def _load_api_usage(self):
if not self.provider:
return
@@ -93,9 +92,11 @@
logging.error(exc)
@Gtk.Template.Callback()
- @background_task
- async def _on_instance_apply(self, _row):
+ def _on_instance_apply(self, _row):
"""Called on self.instance_entry::apply signal"""
+ create_background_task(self._instance_apply())
+
+ async def _instance_apply(self):
if not self.provider:
return
@@ -159,9 +160,11 @@
self.instance_entry.props.text = self.provider.instance_url
@Gtk.Template.Callback()
- @background_task
- async def _on_api_key_apply(self, _row):
+ def _on_api_key_apply(self, _row):
"""Called on self.api_key_entry::apply signal"""
+ create_background_task(self._api_key_apply())
+
+ async def _api_key_apply(self):
if not self.provider:
return
|