Skip to content

Commit c220d3e

Browse files
authored
Add deserialize method to Trigger base class and annotate classes dict (#596)
* Add deserialize method to Trigger base class and annotate classes dict The classes dict in decode_trigger was inferred as dict[str, type] by mypy, causing "type has no attribute deserialize" error. Add a type annotation and a base class deserialize method to fix this. * Add tests for Trigger.deserialize and decode_trigger
1 parent 93bf0f0 commit c220d3e

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

api/library/python/iterm2/iterm2/triggers.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def decode_trigger(encoded: dict) -> 'Trigger':
3737
3838
:returns: A :class:`~Trigger`.
3939
"""
40-
classes = {
40+
classes: typing.Dict[str, typing.Type[Trigger]] = {
4141
AlertTrigger._name(): AlertTrigger,
4242
AnnotateTrigger._name(): AnnotateTrigger,
4343
BellTrigger._name(): BellTrigger,
@@ -136,6 +136,10 @@ def enabled(self) -> bool:
136136
def enabled(self, value: bool):
137137
self.__enabled = value
138138

139+
@staticmethod
140+
def deserialize(regex: str, param: str, instant: bool, enabled: bool) -> 'Trigger':
141+
return Trigger(regex, param, instant, enabled)
142+
139143
@property
140144
def encode(self) -> dict:
141145
return { "regex": self.regex,
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""Tests for iterm2.triggers module."""
2+
from iterm2.triggers import (
3+
Trigger,
4+
AlertTrigger,
5+
BellTrigger,
6+
HighlightTrigger,
7+
decode_trigger,
8+
)
9+
10+
11+
class TestTriggerDeserialize:
12+
"""Tests for the Trigger base class deserialize method."""
13+
14+
def test_returns_trigger_instance(self):
15+
"""Test that Trigger.deserialize returns a Trigger instance."""
16+
trigger = Trigger.deserialize("regex", "param", True, False)
17+
assert isinstance(trigger, Trigger)
18+
19+
def test_fields_are_set(self):
20+
"""Test that deserialize sets all fields correctly."""
21+
trigger = Trigger.deserialize("pattern", "value", False, True)
22+
assert trigger.regex == "pattern"
23+
assert trigger.param == "value"
24+
assert trigger.instant is False
25+
assert trigger.enabled is True
26+
27+
28+
class TestDecodeTrigger:
29+
"""Tests for decode_trigger using the classes dict and deserialize."""
30+
31+
def test_decode_known_trigger(self):
32+
"""Test decoding a known trigger type calls its deserialize."""
33+
encoded = {
34+
"action": "AlertTrigger",
35+
"regex": "error",
36+
"parameter": "Alert!",
37+
"partial": False,
38+
"disabled": False,
39+
}
40+
trigger = decode_trigger(encoded)
41+
assert isinstance(trigger, AlertTrigger)
42+
assert trigger.regex == "error"
43+
assert trigger.instant is False
44+
assert trigger.enabled is True
45+
46+
def test_decode_unknown_trigger_falls_back_to_base(self):
47+
"""Test that an unknown action falls back to Trigger.deserialize."""
48+
encoded = {
49+
"action": "SomeFutureTrigger",
50+
"regex": "test",
51+
"parameter": "param_value",
52+
}
53+
trigger = decode_trigger(encoded)
54+
assert type(trigger) is Trigger
55+
assert trigger.regex == "test"
56+
assert trigger.param == "param_value"
57+
58+
def test_decode_defaults(self):
59+
"""Test that missing optional fields get default values."""
60+
encoded = {
61+
"action": "BellTrigger",
62+
"regex": "bell",
63+
}
64+
trigger = decode_trigger(encoded)
65+
assert isinstance(trigger, BellTrigger)
66+
assert trigger.instant is False
67+
assert trigger.enabled is True
68+
69+
def test_decode_disabled(self):
70+
"""Test that disabled flag is correctly inverted."""
71+
encoded = {
72+
"action": "BellTrigger",
73+
"regex": "bell",
74+
"disabled": True,
75+
}
76+
trigger = decode_trigger(encoded)
77+
assert trigger.enabled is False

0 commit comments

Comments
 (0)