Skip to content

Commit ba17dfb

Browse files
Merge pull request #4139 from Textualize/add-widget-lock
Adds `Widget.lock` attribute.
2 parents 1604c2b + dfeea7d commit ba17dfb

File tree

3 files changed

+10
-6
lines changed

3 files changed

+10
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10-
1110
### Changed
1211

1312
- Textual now writes to stderr rather than stdout
1413

1514
### Added
1615

16+
- Added an `asyncio` lock attribute `Widget.lock` to be used to synchronize widget state https://github.com/Textualize/textual/issues/4134
1717
- Added support for environment variable `TEXTUAL_ANIMATIONS` to control what animations Textual displays https://github.com/Textualize/textual/pull/4062
1818
- Add attribute `App.animation_level` to control whether animations on that app run or not https://github.com/Textualize/textual/pull/4062
1919
- Added support for a `TEXTUAL_SCREENSHOT_LOCATION` environment variable to specify the location of an automated screenshot https://github.com/Textualize/textual/pull/4181/
2020
- Added support for a `TEXTUAL_SCREENSHOT_FILENAME` environment variable to specify the filename of an automated screenshot https://github.com/Textualize/textual/pull/4181/
2121

22-
2322
## [0.51.0] - 2024-02-15
2423

2524
### Added

src/textual/widget.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from __future__ import annotations
66

7-
from asyncio import create_task, wait
7+
from asyncio import Lock, create_task, wait
88
from collections import Counter
99
from fractions import Fraction
1010
from itertools import islice
@@ -373,6 +373,14 @@ def __init__(
373373
if self.BORDER_SUBTITLE:
374374
self.border_subtitle = self.BORDER_SUBTITLE
375375

376+
self.lock = Lock()
377+
"""`asyncio` lock to be used to synchronize the state of the widget.
378+
379+
Two different tasks might call methods on a widget at the same time, which
380+
might result in a race condition.
381+
This can be fixed by adding `async with widget.lock:` around the method calls.
382+
"""
383+
376384
virtual_size: Reactive[Size] = Reactive(Size(0, 0), layout=True)
377385
"""The virtual (scrollable) [size][textual.geometry.Size] of the widget."""
378386

src/textual/widgets/_tree.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from __future__ import annotations
44

5-
from asyncio import Lock
65
from dataclasses import dataclass
76
from typing import TYPE_CHECKING, ClassVar, Generic, Iterable, NewType, TypeVar, cast
87

@@ -618,8 +617,6 @@ def __init__(
618617
self._line_cache: LRUCache[LineCacheKey, Strip] = LRUCache(1024)
619618
self._tree_lines_cached: list[_TreeLine[TreeDataType]] | None = None
620619
self._cursor_node: TreeNode[TreeDataType] | None = None
621-
self.lock = Lock()
622-
"""Used to synchronise stateful directory tree operations."""
623620

624621
super().__init__(name=name, id=id, classes=classes, disabled=disabled)
625622

0 commit comments

Comments
 (0)