Skip to content

Commit f76670e

Browse files
authored
Merge pull request #6041 from Textualize/prettier-fix
don't ineherit from Static
2 parents 6ffe40c + 8ef31c9 commit f76670e

File tree

9 files changed

+209
-29
lines changed

9 files changed

+209
-29
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1212
- Fix type hint for SelectType: only hashable types are allowed. https://github.com/Textualize/textual/pull/6034
1313
- Fixed `Content.expand_tabs` https://github.com/Textualize/textual/pull/6038
1414
- Fixed return value for `Pilot.double_click` and `Pilot.triple_click` https://github.com/Textualize/textual/pull/6035
15-
- Fixed sizing issue with `Pretty` widget https://github.com/Textualize/textual/pull/6040
15+
- Fixed sizing issue with `Pretty` widget https://github.com/Textualize/textual/pull/6040 https://github.com/Textualize/textual/pull/6041
1616

1717
### Added
1818

1919
- Added `bar_renderable` to `ProgressBar` widget https://github.com/Textualize/textual/pull/5963
2020

21+
22+
### Changed
23+
24+
- Breaking change: The `renderable` property on the `Static` widget has been changed to `content`. https://github.com/Textualize/textual/pull/6041
25+
2126
# [5.3.0] - 2025-08-07
2227

2328
### Added

src/textual/widgets/_pretty.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
from rich.pretty import Pretty as PrettyRenderable
88

9-
from textual.widgets import Static
9+
from textual.app import RenderResult
10+
from textual.widget import Widget
1011

1112

12-
class Pretty(Static):
13+
class Pretty(Widget):
1314
"""A pretty-printing widget.
1415
1516
Used to pretty-print any object.
@@ -38,12 +39,18 @@ def __init__(
3839
classes: The CSS classes of the pretty.
3940
"""
4041
super().__init__(name=name, id=id, classes=classes)
41-
self.update(object)
42+
self.shrink = False
43+
self._pretty_renderable = PrettyRenderable(object)
4244

43-
def update(self, object: Any) -> None:
45+
def render(self) -> RenderResult:
46+
return self._pretty_renderable
47+
48+
def update(self, object: object) -> None:
4449
"""Update the content of the pretty widget.
4550
4651
Args:
4752
object: The object to pretty-print.
4853
"""
49-
super().update(PrettyRenderable(object))
54+
self._pretty_renderable = PrettyRenderable(object)
55+
self.clear_cached_dimensions()
56+
self.refresh(layout=True)

src/textual/widgets/_static.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ def visual(self) -> Visual:
5858
return self._visual
5959

6060
@property
61-
def renderable(self) -> VisualType:
62-
return self._content or ""
63-
64-
# TODO: Should probably be renamed to `content`.
65-
@renderable.setter
66-
def renderable(self, renderable: VisualType) -> None:
67-
self._renderable = renderable
68-
self._visual = None
61+
def content(self) -> VisualType:
62+
"""The content set in the constructor."""
63+
return self._content
64+
65+
@content.setter
66+
def content(self, content: VisualType) -> None:
67+
self._visual = visualize(self, content, markup=self._render_markup)
6968
self.clear_cached_dimensions()
69+
self.refresh(layout=True)
7070

7171
def render(self) -> RenderResult:
7272
"""Get a rich renderable for the widget's content.

tests/listview/test_listview_navigation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def _on_list_view_highlighted(self, message: ListView.Highlighted) -> None:
2121
if message.item is None:
2222
self.highlighted.append(None)
2323
else:
24-
self.highlighted.append(str(message.item.children[0].renderable))
24+
self.highlighted.append(str(message.item.children[0].content))
2525

2626

2727
async def test_keyboard_navigation_with_disabled_items() -> None:

tests/listview/test_listview_remove_items.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def _on_list_view_highlighted(self, message: ListView.Highlighted) -> None:
4444
if message.item is None:
4545
self.highlighted.append(None)
4646
else:
47-
self.highlighted.append(str(message.item.children[0].renderable))
47+
self.highlighted.append(str(message.item.children[0].content))
4848

4949

5050
async def test_listview_remove_items() -> None:

tests/select/test_prompt.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ def compose(self):
2222
select_current_label = select_current.query_one("#label", Static)
2323
select_overlay = select_widget.query_one(SelectOverlay)
2424

25-
assert select_current_label.renderable == "Old prompt"
25+
assert select_current_label.content == "Old prompt"
2626
assert select_overlay._options[0].prompt == Text("Old prompt")
2727

2828
select_widget.prompt = "New prompt"
29-
assert select_current_label.renderable == "New prompt"
29+
assert select_current_label.content == "New prompt"
3030
assert select_overlay._options[0].prompt == Text("New prompt")
3131

3232

@@ -46,9 +46,9 @@ def compose(self):
4646
select_current_label = select_current.query_one("#label", Static)
4747
select_overlay = select_widget.query_one(SelectOverlay)
4848

49-
assert select_current_label.renderable == "0"
49+
assert select_current_label.content == "0"
5050
assert select_overlay._options[0].prompt == "0"
5151

5252
select_widget.prompt = "New prompt"
53-
assert select_current_label.renderable == "0"
53+
assert select_current_label.content == "0"
5454
assert select_overlay._options[0].prompt == "0"
Lines changed: 150 additions & 0 deletions
Loading

tests/snapshot_tests/test_snapshots.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4570,3 +4570,21 @@ def compose(self) -> ComposeResult:
45704570
yield Pretty("hello world")
45714571

45724572
assert snap_compare(Demo())
4573+
4574+
4575+
def test_static_content_property(snap_compare):
4576+
"""Test that the Static.content property.
4577+
4578+
You should see the text "FOO BAR"
4579+
4580+
"""
4581+
4582+
class StaticApp(App):
4583+
4584+
def compose(self) -> ComposeResult:
4585+
yield Static("Hello, World")
4586+
4587+
def on_mount(self) -> None:
4588+
self.query_one(Static).content = "FOO BAR"
4589+
4590+
assert snap_compare(StaticApp())

tests/test_screen_modes.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,25 @@ async def test_mode_setup(ModesApp: Type[App]):
8282
app = ModesApp()
8383
async with app.run_test():
8484
assert isinstance(app.screen, BaseScreen)
85-
assert str(app.screen.query_one(Label).renderable) == "one"
85+
assert str(app.screen.query_one(Label).content) == "one"
8686

8787

8888
async def test_switch_mode(ModesApp: Type[App]):
8989
app = ModesApp()
9090
async with app.run_test() as pilot:
9191
await pilot.press("2")
92-
assert str(app.screen.query_one(Label).renderable) == "two"
92+
assert str(app.screen.query_one(Label).content) == "two"
9393
await pilot.press("1")
94-
assert str(app.screen.query_one(Label).renderable) == "one"
94+
assert str(app.screen.query_one(Label).content) == "one"
9595

9696

9797
async def test_switch_same_mode(ModesApp: Type[App]):
9898
app = ModesApp()
9999
async with app.run_test() as pilot:
100100
await pilot.press("1")
101-
assert str(app.screen.query_one(Label).renderable) == "one"
101+
assert str(app.screen.query_one(Label).content) == "one"
102102
await pilot.press("1")
103-
assert str(app.screen.query_one(Label).renderable) == "one"
103+
assert str(app.screen.query_one(Label).content) == "one"
104104

105105

106106
async def test_switch_unknown_mode(ModesApp: Type[App]):
@@ -115,7 +115,7 @@ async def test_remove_mode(ModesApp: Type[App]):
115115
async with app.run_test() as pilot:
116116
await app.switch_mode("two")
117117
await pilot.pause()
118-
assert str(app.screen.query_one(Label).renderable) == "two"
118+
assert str(app.screen.query_one(Label).content) == "two"
119119
app.remove_mode("one")
120120
assert "one" not in app._modes
121121

@@ -133,7 +133,7 @@ async def test_add_mode(ModesApp: Type[App]):
133133
app.add_mode("three", lambda: BaseScreen("three"))
134134
await app.switch_mode("three")
135135
await pilot.pause()
136-
assert str(app.screen.query_one(Label).renderable) == "three"
136+
assert str(app.screen.query_one(Label).content) == "three"
137137

138138

139139
async def test_add_mode_duplicated(ModesApp: Type[App]):
@@ -152,7 +152,7 @@ async def test_screen_stack_preserved(ModesApp: Type[App]):
152152
# Build the stack up.
153153
for _ in range(N):
154154
await pilot.press("p")
155-
fruits.append(str(app.screen.query_one(Label).renderable))
155+
fruits.append(str(app.screen.query_one(Label).content))
156156

157157
assert len(app.screen_stack) == N + 1
158158

@@ -164,7 +164,7 @@ async def test_screen_stack_preserved(ModesApp: Type[App]):
164164
# Check the stack.
165165
assert len(app.screen_stack) == N + 1
166166
for _ in range(N):
167-
assert str(app.screen.query_one(Label).renderable) == fruits.pop()
167+
assert str(app.screen.query_one(Label).content) == fruits.pop()
168168
await pilot.press("o")
169169

170170

0 commit comments

Comments
 (0)