Skip to content

Commit 0287063

Browse files
committed
fix(translator): Apply translation to kwargs passed to state.change callbacks
1 parent 94b489d commit 0287063

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

tests/test_translator.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
import logging
22

3-
from trame_server.core import State
3+
from trame_server.core import State, Translator
44

55
logger = logging.getLogger(__name__)
66

77

8+
def test_translator():
9+
a_translator = Translator()
10+
a_translator.add_translation("foo", "a_foo")
11+
12+
assert a_translator.translate_key("foo") == "a_foo"
13+
assert a_translator.translate_key("bar") == "bar"
14+
assert a_translator.reverse_translate_key("a_foo") == "foo"
15+
assert a_translator.reverse_translate_key("bar") == "bar"
16+
17+
b_translator = Translator()
18+
b_translator.set_prefix("b_")
19+
20+
assert b_translator.translate_key("foo") == "b_foo"
21+
assert b_translator.translate_key("bar") == "b_bar"
22+
assert b_translator.reverse_translate_key("b_foo") == "foo"
23+
assert b_translator.reverse_translate_key("b_bar") == "bar"
24+
25+
826
def test_translation():
927
root_state = State()
1028
a_state = State(internal=root_state)
@@ -131,3 +149,50 @@ def test_prefix_and_translation():
131149
common_shared_value=789,
132150
)
133151
assert expected_state == root_state.to_dict()
152+
153+
154+
def test_change_callback():
155+
# Ensure change callbacks are passed translated kwargs when using translations
156+
test_passed = False
157+
158+
a_state = State()
159+
a_state.translator.add_translation("foo", "a_foo")
160+
161+
a_state.bar = 1
162+
163+
def on_a_foo_change(*args, **kwargs):
164+
nonlocal test_passed
165+
assert "foo" in kwargs
166+
assert "a_foo" not in kwargs
167+
assert kwargs["foo"] == 123
168+
test_passed = "foo" in kwargs and "a_foo" not in kwargs
169+
170+
a_state.change("foo")(on_a_foo_change)
171+
a_state.ready()
172+
a_state.foo = 123
173+
a_state.flush()
174+
175+
assert test_passed
176+
177+
# Ensure change callbacks are passed translated kwargs when using prefix
178+
test_passed = False
179+
180+
b_state = State()
181+
b_state.translator.set_prefix("b_")
182+
183+
def on_b_foo_change(*args, **kwargs):
184+
nonlocal test_passed
185+
assert "foo" in kwargs
186+
assert "b_foo" not in kwargs
187+
assert kwargs["foo"] == 456
188+
test_passed = "foo" in kwargs and "b_foo" not in kwargs
189+
190+
b_state.change("foo")(on_b_foo_change)
191+
192+
b_state.ready()
193+
194+
b_state.foo = 456
195+
196+
b_state.flush()
197+
198+
assert test_passed

trame_server/state.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,17 @@ def flush(self):
238238

239239
# Execute state listeners
240240
self._state_listeners.add_all(_keys)
241+
242+
pushed_state = self.translator.reverse_translate_dict(
243+
self._pushed_state
244+
)
245+
241246
for callback in self._state_listeners:
242247
if self._hot_reload:
243248
if not inspect.iscoroutinefunction(callback):
244249
callback = reload(callback)
245250

246-
coroutine = callback(**self._pushed_state)
251+
coroutine = callback(**pushed_state)
247252
if inspect.isawaitable(coroutine):
248253
asynchronous.create_task(coroutine)
249254

trame_server/utils/namespace.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,14 @@ def __init__(self, prefix=None):
6262
logger.info("Translator(prefix=%s)", prefix)
6363
self._prefix = prefix
6464
self._transl = {}
65+
self._reverse_transl = {}
6566

6667
def set_prefix(self, prefix):
6768
self._prefix = prefix
6869

6970
def add_translation(self, key, translated_key):
7071
self._transl[key] = translated_key
72+
self._reverse_transl[translated_key] = key
7173

7274
def translate_key(self, key):
7375
# Reserved keys
@@ -82,12 +84,31 @@ def translate_key(self, key):
8284

8385
return key
8486

87+
def reverse_translate_key(self, translated_key):
88+
# Reserved keys
89+
if is_name_reserved(translated_key):
90+
return translated_key
91+
92+
if translated_key in self._reverse_transl:
93+
return self._reverse_transl[translated_key]
94+
95+
if self._prefix:
96+
return translated_key.removeprefix(self._prefix)
97+
98+
return translated_key
99+
85100
def translate_list(self, key_list):
86101
return [self.translate_key(v) for v in key_list]
87102

88103
def translate_dict(self, key_dict):
89104
return {self.translate_key(k): v for k, v in key_dict.items()}
90105

106+
def reverse_translate_list(self, key_list):
107+
return [self.reverse_translate_key(v) for v in key_list]
108+
109+
def reverse_translate_dict(self, key_dict):
110+
return {self.reverse_translate_key(k): v for k, v in key_dict.items()}
111+
91112
def translate_js_expression(self, state, expression):
92113
tokens = []
93114
for token in split_when(expression, js_tokenizer):

0 commit comments

Comments
 (0)