File: 2001_avoid_too_new_pygobject.patch

package info (click to toggle)
dialect 2.6.0%2B~2.6.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,656 kB
  • sloc: python: 3,273; xml: 20; makefile: 4; sh: 4
file content (150 lines) | stat: -rw-r--r-- 4,244 bytes parent folder | download
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