From 744e23b695f3b6524fde4ea82e9792c97aa3a485 Mon Sep 17 00:00:00 2001 From: Josh Karpel Date: Tue, 27 Feb 2024 21:55:27 -0600 Subject: [PATCH] Allow early `return` from effects (#121) --- counterweight/_utils.py | 7 +++++++ docs/reference/changelog.md | 14 ++++++++++++++ pyproject.toml | 2 +- tests/utils/test_cancel.py | 11 +++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/counterweight/_utils.py b/counterweight/_utils.py index 75e692ac..1351492f 100644 --- a/counterweight/_utils.py +++ b/counterweight/_utils.py @@ -81,7 +81,14 @@ async def forever() -> None: async def cancel(task: Task[T]) -> None: # Based on https://discuss.python.org/t/asyncio-cancel-a-cancellation-utility-as-a-coroutine-this-time-with-feeling/26304/2 + if task.done(): + # If the task has already completed, there's nothing to cancel. + # This can happen if, for example, an effect aborts itself by returning, + # and then we try to cancel it when reconciling effects. + return + task.cancel() + try: await task except CancelledError: diff --git a/docs/reference/changelog.md b/docs/reference/changelog.md index e4920b35..7e682069 100644 --- a/docs/reference/changelog.md +++ b/docs/reference/changelog.md @@ -2,8 +2,22 @@ ## Next +## `0.0.9` + +Released `2024-02-27` + +### Fixed + +- [#121](https://github.com/JoshKarpel/counterweight/pull/121) + A change in effect reconciliation introduced in `0.0.8` caused a regression in the behavior of `use_effect`, + where if the `setup` function `return`ed (i.e., stopped itself), + Counterweight would crash when trying to cancel the effect. + This now works again. + ## `0.0.8` +Released `2024-02-17` + ### Changed - [#110](https://github.com/JoshKarpel/counterweight/pull/110) diff --git a/pyproject.toml b/pyproject.toml index d74bfe86..29429052 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "counterweight" -version = "0.0.8" +version = "0.0.9" description = "An experimental TUI framework for Python, inspired by React and Tailwind" readme="README.md" homepage="https://github.com/JoshKarpel/counterweight" diff --git a/tests/utils/test_cancel.py b/tests/utils/test_cancel.py index 49984e2f..90be2c7e 100644 --- a/tests/utils/test_cancel.py +++ b/tests/utils/test_cancel.py @@ -50,3 +50,14 @@ async def t() -> None: with pytest.raises(RuntimeError): await cancel(task) + + +async def test_cancel_with_task_that_has_already_finished() -> None: + async def t() -> None: + return + + task = create_task(t()) + + await task # run the task to completion + + await cancel(task)