Skip to content

Commit 19c384b

Browse files
committed
Store asyncio to prevent (unlikely? impossible?) garbage collection.
1 parent 3cecfd4 commit 19c384b

2 files changed

Lines changed: 22 additions & 17 deletions

File tree

datashuttle/tui/shared/validate_content.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import asyncio
43
import platform
54
from typing import TYPE_CHECKING, Optional, Union
65

@@ -192,14 +191,11 @@ def on_button_pressed(self, event: Button.Pressed) -> None:
192191
self.validating_central_popup
193192
)
194193

195-
asyncio.create_task(
196-
self.run_validate_and_dismiss_popup(
197-
top_level_folder=top_level_folder,
198-
include_central=include_central,
199-
strict_mode=strict_mode,
200-
allow_letters_in_sub_ses_values=allow_letters_in_sub_ses_values,
201-
),
202-
name="validate_async_task",
194+
self.run_validate_and_dismiss_popup(
195+
top_level_folder=top_level_folder,
196+
include_central=include_central,
197+
strict_mode=strict_mode,
198+
allow_letters_in_sub_ses_values=allow_letters_in_sub_ses_values,
203199
)
204200
else:
205201
path_ = self.query_one("#validate_path_input").value
@@ -229,14 +225,21 @@ def set_select_path(self, path_):
229225
if path_:
230226
self.query_one("#validate_path_input").value = path_.as_posix()
231227

228+
@work(group="validate_async", exclusive=True)
232229
async def run_validate_and_dismiss_popup(
233230
self,
234231
top_level_folder,
235232
include_central,
236233
strict_mode,
237234
allow_letters_in_sub_ses_values,
238235
) -> None:
239-
"""Run validation in a worker thread and dismiss the waiting popup when done."""
236+
"""Run validation in a worker thread and dismiss the waiting popup when done.
237+
238+
Decorated with ``@work`` so Textual owns the task lifecycle (no need to
239+
hold an ``asyncio.Task`` reference to prevent premature GC), and so a
240+
repeat button-press cancels the previous in-flight invocation via
241+
``exclusive=True``.
242+
"""
240243
worker = self.validate_project_worker(
241244
top_level_folder=top_level_folder,
242245
include_central=include_central,

datashuttle/tui/tabs/create_folders.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import asyncio
43
from typing import TYPE_CHECKING, List, Optional
54

65
if TYPE_CHECKING:
@@ -316,7 +315,7 @@ def suggest_next_sub_ses(
316315
Shows a pop up screen in cases when searching for next sub/ses takes
317316
time such as searching central in SSH connection method.
318317
319-
Creates an asyncio task which handles the suggestion logic and
318+
Spawns a Textual worker which handles the suggestion logic and
320319
dismissing the pop up.
321320
322321
Parameters
@@ -346,13 +345,11 @@ def suggest_next_sub_ses(
346345
)
347346
self.mainwindow.push_screen(self.searching_central_popup_widget)
348347

349-
asyncio.create_task(
350-
self.fill_suggestion_and_dismiss_popup(
351-
prefix, input_id, include_central
352-
),
353-
name=f"suggest_next_{prefix}_async_task",
348+
self.fill_suggestion_and_dismiss_popup(
349+
prefix, input_id, include_central
354350
)
355351

352+
@work(group="suggest_next_async", exclusive=True)
356353
async def fill_suggestion_and_dismiss_popup(
357354
self, prefix, input_id, include_central
358355
) -> None:
@@ -364,6 +361,11 @@ async def fill_suggestion_and_dismiss_popup(
364361
Else, if the worker successfully exits, this function handles dismissal
365362
of the popup.
366363
364+
Decorated with ``@work`` so Textual owns the task lifecycle (no need to
365+
hold an ``asyncio.Task`` reference to prevent premature GC), and so a
366+
repeat invocation cancels the previous in-flight one via
367+
``exclusive=True``.
368+
367369
see `suggest_next_sub_ses()` for parameters.
368370
"""
369371
worker = self.fill_input_with_next_sub_or_ses_template(

0 commit comments

Comments
 (0)