diff --git a/CHANGELOG.md b/CHANGELOG.md index 91ab0e788e..7e02eb239b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,19 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased - ### Changed - Textual now writes to stderr rather than stdout ### Added +- Added an `asyncio` lock attribute `Widget.lock` to be used to synchronize widget state https://github.com/Textualize/textual/issues/4134 - Added support for environment variable `TEXTUAL_ANIMATIONS` to control what animations Textual displays https://github.com/Textualize/textual/pull/4062 - Add attribute `App.animation_level` to control whether animations on that app run or not https://github.com/Textualize/textual/pull/4062 - Added support for a `TEXTUAL_SCREENSHOT_LOCATION` environment variable to specify the location of an automated screenshot https://github.com/Textualize/textual/pull/4181/ - Added support for a `TEXTUAL_SCREENSHOT_FILENAME` environment variable to specify the filename of an automated screenshot https://github.com/Textualize/textual/pull/4181/ - ## [0.51.0] - 2024-02-15 ### Added diff --git a/src/textual/widget.py b/src/textual/widget.py index 4a3f6c12fe..b70596b78d 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -4,7 +4,7 @@ from __future__ import annotations -from asyncio import create_task, wait +from asyncio import Lock, create_task, wait from collections import Counter from fractions import Fraction from itertools import islice @@ -373,6 +373,14 @@ def __init__( if self.BORDER_SUBTITLE: self.border_subtitle = self.BORDER_SUBTITLE + self.lock = Lock() + """`asyncio` lock to be used to synchronize the state of the widget. + + Two different tasks might call methods on a widget at the same time, which + might result in a race condition. + This can be fixed by adding `async with widget.lock:` around the method calls. + """ + virtual_size: Reactive[Size] = Reactive(Size(0, 0), layout=True) """The virtual (scrollable) [size][textual.geometry.Size] of the widget.""" diff --git a/src/textual/widgets/_tree.py b/src/textual/widgets/_tree.py index 3e0a2d8cb4..f218ae86f2 100644 --- a/src/textual/widgets/_tree.py +++ b/src/textual/widgets/_tree.py @@ -2,7 +2,6 @@ from __future__ import annotations -from asyncio import Lock from dataclasses import dataclass from typing import TYPE_CHECKING, ClassVar, Generic, Iterable, NewType, TypeVar, cast @@ -618,8 +617,6 @@ def __init__( self._line_cache: LRUCache[LineCacheKey, Strip] = LRUCache(1024) self._tree_lines_cached: list[_TreeLine[TreeDataType]] | None = None self._cursor_node: TreeNode[TreeDataType] | None = None - self.lock = Lock() - """Used to synchronise stateful directory tree operations.""" super().__init__(name=name, id=id, classes=classes, disabled=disabled)