Skip to content

Commit ba9a913

Browse files
authored
Merge pull request #4313 from davep/bug/4248/click-markup-crash
Fix a crash in `run_action` when an action is an empty tuple
2 parents 482cf24 + 0907da1 commit ba9a913

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/textual/app.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3006,11 +3006,18 @@ async def _broker_event(
30063006
return False
30073007
else:
30083008
event.stop()
3009-
if isinstance(action, (str, tuple)):
3009+
if isinstance(action, str) or (isinstance(action, tuple) and len(action) == 2):
30103010
await self.run_action(action, default_namespace=default_namespace) # type: ignore[arg-type]
30113011
elif callable(action):
30123012
await action()
30133013
else:
3014+
if isinstance(action, tuple) and self.debug:
3015+
# It's a tuple and made it this far, which means it'll be a
3016+
# malformed action. This is a no-op, but let's log that
3017+
# anyway.
3018+
log.warning(
3019+
f"Can't parse @{event_name} action from style meta; check your console markup syntax"
3020+
)
30143021
return False
30153022
return True
30163023

tests/test_issue_4248.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Test https://github.com/Textualize/textual/issues/4248"""
2+
3+
from textual.app import App, ComposeResult
4+
from textual.widgets import Label
5+
6+
7+
async def test_issue_4248() -> None:
8+
"""Various forms of click parameters should be fine."""
9+
10+
bumps = 0
11+
12+
class ActionApp(App[None]):
13+
14+
def compose(self) -> ComposeResult:
15+
yield Label("[@click]click me and crash[/]", id="nothing")
16+
yield Label("[@click=]click me and crash[/]", id="no-params")
17+
yield Label("[@click=()]click me and crash[/]", id="empty-params")
18+
yield Label("[@click=foobar]click me[/]", id="unknown-sans-parens")
19+
yield Label("[@click=foobar()]click me[/]", id="unknown-with-parens")
20+
yield Label("[@click=bump]click me[/]", id="known-sans-parens")
21+
yield Label("[@click=bump()]click me[/]", id="known-empty-parens")
22+
yield Label("[@click=bump(100)]click me[/]", id="known-with-param")
23+
24+
def action_bump(self, by_value: int = 1) -> None:
25+
nonlocal bumps
26+
bumps += by_value
27+
28+
app = ActionApp()
29+
async with app.run_test() as pilot:
30+
assert bumps == 0
31+
await pilot.click("#nothing")
32+
assert bumps == 0
33+
await pilot.click("#no-params")
34+
assert bumps == 0
35+
await pilot.click("#empty-params")
36+
assert bumps == 0
37+
await pilot.click("#unknown-sans-parens")
38+
assert bumps == 0
39+
await pilot.click("#unknown-with-parens")
40+
assert bumps == 0
41+
await pilot.click("#known-sans-parens")
42+
assert bumps == 1
43+
await pilot.click("#known-empty-parens")
44+
assert bumps == 2
45+
await pilot.click("#known-with-param")
46+
assert bumps == 102

0 commit comments

Comments
 (0)