Skip to content

Commit 51e00c7

Browse files
authored
Merge pull request #5869 from Textualize/startup-optimizations
Startup optimizations
2 parents c52d2c8 + e16f592 commit 51e00c7

File tree

188 files changed

+9119
-9242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

188 files changed

+9119
-9242
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ 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+
### Changed
11+
12+
- Optimized startup https://github.com/Textualize/textual/pull/5869
13+
- New blank visual which makes background faster to render (note this will break snapshots tests this version) https://github.com/Textualize/textual/pull/5869
14+
815
## [3.4.0] - 2025-06-14
916

1017
### Fixed

poetry.lock

Lines changed: 224 additions & 311 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ tree-sitter-yaml = { version = ">=0.6.0", optional = true, python = ">=3.9" }
6363
tree-sitter-html = { version = ">=0.23.0", optional = true, python = ">=3.9" }
6464
tree-sitter-css = { version = ">=0.23.0", optional = true, python = ">=3.9" }
6565
tree-sitter-javascript = { version = ">=0.23.0", optional = true, python = ">=3.9" }
66-
tree-sitter-rust = { version = ">=0.23.0", optional = true, python = ">=3.9" }
66+
tree-sitter-rust = { version = ">=0.23.0,<=0.23.2", optional = true, python = ">=3.9" }
6767
tree-sitter-go = { version = ">=0.23.0", optional = true, python = ">=3.9" }
6868
tree-sitter-regex = { version = ">=0.24.0", optional = true, python = ">=3.9" }
6969
tree-sitter-xml = { version = ">=0.7.0", optional = true, python = ">=3.9" }

src/textual/app.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -791,8 +791,8 @@ def __init__(
791791
perform work after the app has resumed.
792792
"""
793793

794-
self.set_class(self.current_theme.dark, "-dark-mode")
795-
self.set_class(not self.current_theme.dark, "-light-mode")
794+
self.set_class(self.current_theme.dark, "-dark-mode", update=False)
795+
self.set_class(not self.current_theme.dark, "-light-mode", update=False)
796796

797797
self.animation_level: AnimationLevel = constants.TEXTUAL_ANIMATIONS
798798
"""Determines what type of animations the app will display.

src/textual/dom.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,9 +1684,9 @@ def set_class(self, add: bool, *class_names: str, update: bool = True) -> Self:
16841684
Self.
16851685
"""
16861686
if add:
1687-
self.add_class(*class_names, update=update and self.is_attached)
1687+
self.add_class(*class_names, update=update)
16881688
else:
1689-
self.remove_class(*class_names, update=update and self.is_attached)
1689+
self.remove_class(*class_names, update=update)
16901690
return self
16911691

16921692
def set_classes(self, classes: str | Iterable[str]) -> Self:
@@ -1707,6 +1707,8 @@ def _update_styles(self) -> None:
17071707
17081708
Should be called whenever CSS classes / pseudo classes change.
17091709
"""
1710+
if not self.is_attached:
1711+
return
17101712
try:
17111713
self.app.update_styles(self)
17121714
except NoActiveAppError:

src/textual/renderables/blank.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,39 @@
11
from __future__ import annotations
22

3-
from rich.console import Console, ConsoleOptions, RenderResult
4-
from rich.segment import Segment
5-
from rich.style import Style
3+
from rich.style import Style as RichStyle
64

75
from textual.color import Color
6+
from textual.content import Style
7+
from textual.css.styles import RulesMap
8+
from textual.selection import Selection
9+
from textual.strip import Strip
10+
from textual.visual import Visual
811

912

10-
class Blank:
13+
class Blank(Visual):
1114
"""Draw solid background color."""
1215

1316
def __init__(self, color: Color | str = "transparent") -> None:
14-
background = Color.parse(color)
15-
self._style = Style.from_color(bgcolor=background.rich_color)
16-
17-
def __rich_console__(
18-
self, console: Console, options: ConsoleOptions
19-
) -> RenderResult:
20-
width = options.max_width
21-
height = options.height or options.max_height
22-
23-
segment = Segment(" " * width, self._style)
24-
line = Segment.line()
25-
for _ in range(height):
26-
yield segment
27-
yield line
17+
self._rich_style = RichStyle.from_color(bgcolor=Color.parse(color).rich_color)
18+
19+
def visualize(self) -> Blank:
20+
return self
21+
22+
def get_optimal_width(self, rules: RulesMap, container_width: int) -> int:
23+
return container_width
24+
25+
def get_height(self, rules: RulesMap, width: int) -> int:
26+
return 1
27+
28+
def render_strips(
29+
self,
30+
rules: RulesMap,
31+
width: int,
32+
height: int | None,
33+
style: Style,
34+
selection: Selection | None = None,
35+
selection_style: Style | None = None,
36+
post_style: Style | None = None,
37+
) -> list[Strip]:
38+
line_count = 1 if height is None else height
39+
return [Strip.blank(width, self._rich_style)] * line_count

src/textual/screen.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,14 +1318,16 @@ def _get_inline_height(self, size: Size) -> int:
13181318

13191319
def _screen_resized(self, size: Size) -> None:
13201320
"""Called by App when the screen is resized."""
1321-
if self.stack_updates:
1321+
if self.stack_updates and self.is_attached:
13221322
self._refresh_layout(size)
13231323

13241324
def _on_screen_resume(self) -> None:
13251325
"""Screen has resumed."""
13261326
if self.app.SUSPENDED_SCREEN_CLASS:
13271327
self.remove_class(self.app.SUSPENDED_SCREEN_CLASS)
1328+
13281329
self.stack_updates += 1
1330+
13291331
self.app._refresh_notifications()
13301332
size = self.app.size
13311333

@@ -1340,10 +1342,11 @@ def _on_screen_resume(self) -> None:
13401342
self.set_focus(widget)
13411343
break
13421344

1343-
self._compositor_refresh()
1344-
self.app.stylesheet.update(self)
1345-
self._refresh_layout(size)
1346-
self.refresh()
1345+
if self.is_attached:
1346+
self._compositor_refresh()
1347+
self.app.stylesheet.update(self)
1348+
self._refresh_layout(size)
1349+
self.refresh()
13471350

13481351
def _on_screen_suspend(self) -> None:
13491352
"""Screen has suspended."""

tests/snapshot_tests/__snapshots__/test_snapshots/test_add_remove_tabs.svg

Lines changed: 7 additions & 7 deletions
Loading

0 commit comments

Comments
 (0)