Skip to content

Commit ac5d571

Browse files
authored
Merge pull request Textualize#5190 from Textualize/fix-focus-within
fixed focus-within
2 parents ffd780e + c8db1d6 commit ac5d571

File tree

4 files changed

+16
-8
lines changed

4 files changed

+16
-8
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8+
## Unreleased
9+
10+
- Fixed broken focus-within https://github.com/Textualize/textual/pull/5190
11+
812
## [0.85.1] - 2024-10-26
913

1014
### Fixed

src/textual/css/stylesheet.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from itertools import chain
66
from operator import itemgetter
77
from pathlib import Path, PurePath
8-
from typing import Iterable, NamedTuple, Sequence, cast
8+
from typing import Final, Iterable, NamedTuple, Sequence, cast
99

1010
import rich.repr
1111
from rich.console import Console, ConsoleOptions, RenderableType, RenderResult
@@ -433,13 +433,14 @@ def _check_rule(
433433
if _check_selectors(selector_set.selectors, css_path_nodes):
434434
yield selector_set.specificity
435435

436-
# pseudo classes which iterate over many nodes
437-
# these have the potential to be slow, and shouldn't be used in a cache key
438-
EXPENSIVE_PSEUDO_CLASSES = {
436+
# pseudo classes which iterate over multiple nodes
437+
# These shouldn't be used in a cache key
438+
_EXCLUDE_PSEUDO_CLASSES_FROM_CACHE: Final[set[str]] = {
439439
"first-of-type",
440440
"last-of_type",
441441
"odd",
442442
"even",
443+
"focus-within",
443444
}
444445

445446
def apply(
@@ -487,7 +488,7 @@ def apply(
487488
cache_key: tuple | None = None
488489

489490
if cache is not None and all_pseudo_classes.isdisjoint(
490-
self.EXPENSIVE_PSEUDO_CLASSES
491+
self._EXCLUDE_PSEUDO_CLASSES_FROM_CACHE
491492
):
492493
cache_key = (
493494
node._parent,

src/textual/dom.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,9 +1592,9 @@ def set_class(self, add: bool, *class_names: str, update: bool = True) -> Self:
15921592
Self.
15931593
"""
15941594
if add:
1595-
self.add_class(*class_names, update=update)
1595+
self.add_class(*class_names, update=update and self.is_attached)
15961596
else:
1597-
self.remove_class(*class_names, update=update)
1597+
self.remove_class(*class_names, update=update and self.is_attached)
15981598
return self
15991599

16001600
def set_classes(self, classes: str | Iterable[str]) -> Self:

src/textual/message_pump.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,10 @@ def app(self) -> "App[object]":
237237
@property
238238
def is_attached(self) -> bool:
239239
"""Is this node linked to the app through the DOM?"""
240-
if self.app._exit:
240+
try:
241+
if self.app._exit:
242+
return False
243+
except NoActiveAppError:
241244
return False
242245
node: MessagePump | None = self
243246
while (node := node._parent) is not None:

0 commit comments

Comments
 (0)