Skip to content

Commit 5f81f15

Browse files
committed
simplify to singular StaticEventHandler
1 parent 1abfd76 commit 5f81f15

File tree

4 files changed

+42
-59
lines changed

4 files changed

+42
-59
lines changed

docs/source/core-concepts.rst

+9-6
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,23 @@ which we can re-render and see what changed:
7575
.. testcode::
7676

7777
from idom.core.layout import LayoutEvent
78+
from idom.testing import StaticEventHandler
7879

80+
static_handler = StaticEventHandler()
7981

8082
@idom.component
8183
def ClickCount():
8284
count, set_count = idom.hooks.use_state(0)
83-
return idom.html.button(
84-
{"onClick": lambda event: set_count(count + 1)},
85-
[f"Click count: {count}"],
86-
)
85+
86+
# we do this in order to capture the event handler's target ID
87+
handler = static_handler.use(lambda event: set_count(count + 1))
88+
89+
return idom.html.button({"onClick": handler}, [f"Click count: {count}"])
8790

8891
async with idom.Layout(ClickCount()) as layout:
8992
patch_1 = await layout.render()
9093

91-
fake_event = LayoutEvent(target="/onClick", data=[{}])
94+
fake_event = LayoutEvent(target=static_handler.target, data=[{}])
9295
await layout.dispatch(fake_event)
9396
patch_2 = await layout.render()
9497

@@ -135,7 +138,7 @@ callback that's called by the dispatcher to events it should execute.
135138

136139

137140
async def recv():
138-
event = LayoutEvent(target="/onClick", data=[{}])
141+
event = LayoutEvent(target=static_handler.target, data=[{}])
139142

140143
# We need this so we don't flood the render loop with events.
141144
# In practice this is never an issue since events won't arrive

src/idom/testing.py

+17-39
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@
1313
Type,
1414
TypeVar,
1515
Union,
16-
overload,
1716
)
1817
from urllib.parse import urlencode, urlunparse
1918
from weakref import ref
2019

2120
from selenium.webdriver import Chrome
2221
from selenium.webdriver.remote.webdriver import WebDriver
23-
from typing_extensions import Literal
2422

2523
from idom.core.events import EventHandler
2624
from idom.core.hooks import LifeCycleHook, current_hook
@@ -229,52 +227,32 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
229227
return wrapper
230228

231229

232-
class StaticEventHandlers:
233-
"""Utility for capturing the target of a static set of event handlers
230+
class StaticEventHandler:
231+
"""Utility for capturing the target of one event handler
234232
235233
Example:
236234
.. code-block::
237235
238-
static_handlers = StaticEventHandlers("first", "second")
236+
static_handler = StaticEventHandler()
239237
240238
@idom.component
241-
def MyComponent(key):
239+
def MyComponent():
242240
state, set_state = idom.hooks.use_state(0)
243-
handler = static_handlers.use(key, lambda event: set_state(state + 1))
241+
handler = static_handler.use(lambda event: set_state(state + 1))
244242
return idom.html.button({"onClick": handler}, "Click me!")
245243
246-
# gives the target ID for onClick where MyComponent(key="first")
247-
first_target = static_handlers.targets["first"]
244+
# gives the target ID for onClick where from the last render of MyComponent
245+
static_handlers.target
248246
"""
249247

250-
def __init__(self, *index: Any) -> None:
251-
if not index:
252-
raise ValueError("Static set of index keys are required")
253-
self._handlers: Dict[Any, EventHandler] = {i: EventHandler() for i in index}
254-
self.targets: Dict[Any, str] = {i: hex_id(h) for i, h in self._handlers.items()}
248+
def __init__(self) -> None:
249+
self._handler = EventHandler()
255250

256-
@overload
257-
def use(
258-
self,
259-
index: Any,
260-
function: Literal[None] = ...,
261-
) -> Callable[[Callable[..., Any]], EventHandler]:
262-
...
263-
264-
@overload
265-
def use(self, index: Any, function: Callable[..., Any]) -> EventHandler:
266-
...
267-
268-
def use(self, index: Any, function: Optional[Callable[..., Any]] = None) -> Any:
269-
"""Decorator for capturing an event handler function"""
270-
271-
def setup(function: Callable[..., Any]) -> EventHandler:
272-
handler = self._handlers[index]
273-
handler.clear()
274-
handler.add(function)
275-
return handler
276-
277-
if function is not None:
278-
return setup(function)
279-
else:
280-
return setup
251+
@property
252+
def target(self) -> str:
253+
return hex_id(self._handler)
254+
255+
def use(self, function: Callable[..., Any]) -> EventHandler:
256+
self._handler.clear()
257+
self._handler.add(function)
258+
return self._handler

tests/test_core/test_dispatcher.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
SingleViewDispatcher,
1111
)
1212
from idom.core.layout import Layout, LayoutEvent
13-
from idom.testing import StaticEventHandlers
13+
from idom.testing import StaticEventHandler
1414
from tests.general_utils import assert_same_items
1515

1616

@@ -20,9 +20,9 @@ async def test_shared_state_dispatcher():
2020
changes_2 = []
2121

2222
event_name = "onEvent"
23-
event_handlers = StaticEventHandlers(event_name)
23+
event_handler = StaticEventHandler()
2424

25-
events_to_inject = [LayoutEvent(event_handlers.targets[event_name], [])] * 4
25+
events_to_inject = [LayoutEvent(event_handler.target, [])] * 4
2626

2727
async def send_1(patch):
2828
changes_1.append(patch.changes)
@@ -48,7 +48,7 @@ async def recv_2():
4848
@idom.component
4949
def Clickable():
5050
count, set_count = idom.hooks.use_state(0)
51-
handler = event_handlers.use(event_name, lambda: set_count(count + 1))
51+
handler = event_handler.use(lambda: set_count(count + 1))
5252
return idom.html.div({event_name: handler, "count": count})
5353

5454
async with SharedViewDispatcher(Layout(Clickable())) as dispatcher:
@@ -62,7 +62,7 @@ def Clickable():
6262
"path": "/eventHandlers",
6363
"value": {
6464
event_name: {
65-
"target": event_handlers.targets[event_name],
65+
"target": event_handler.target,
6666
"preventDefault": False,
6767
"stopPropagation": False,
6868
}

tests/test_core/test_layout.py

+11-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import idom
88
from idom.core.layout import LayoutEvent, LayoutUpdate
99
from idom.core.utils import hex_id
10-
from idom.testing import HookCatcher, StaticEventHandlers
10+
from idom.testing import HookCatcher, StaticEventHandler
1111
from tests.general_utils import assert_same_items
1212

1313

@@ -287,18 +287,19 @@ def use_toggle(init=False):
287287

288288
async def test_model_key_preserves_callback_identity_for_common_elements():
289289
called_good_trigger = idom.Ref(False)
290-
event_handlers = StaticEventHandlers("good", "bad")
290+
good_handler = StaticEventHandler()
291+
bad_handler = StaticEventHandler()
291292

292293
@idom.component
293294
def MyComponent():
294295
reverse_children, set_reverse_children = use_toggle()
295296

296-
@event_handlers.use("good")
297+
@good_handler.use
297298
def good_trigger():
298299
called_good_trigger.current = True
299300
set_reverse_children()
300301

301-
@event_handlers.use("bad")
302+
@bad_handler.use
302303
def bad_trigger():
303304
raise ValueError("Called bad trigger")
304305

@@ -317,7 +318,7 @@ def bad_trigger():
317318
async with idom.Layout(MyComponent()) as layout:
318319
await layout.render()
319320
for i in range(3):
320-
event = LayoutEvent(event_handlers.targets["good"], [])
321+
event = LayoutEvent(good_handler.target, [])
321322
await layout.dispatch(event)
322323

323324
assert called_good_trigger.current
@@ -329,7 +330,8 @@ def bad_trigger():
329330

330331
async def test_model_key_preserves_callback_identity_for_components():
331332
called_good_trigger = idom.Ref(False)
332-
event_handlers = StaticEventHandlers("good", "bad")
333+
good_handler = StaticEventHandler()
334+
bad_handler = StaticEventHandler()
333335

334336
@idom.component
335337
def RootComponent():
@@ -346,14 +348,14 @@ def RootComponent():
346348
def Trigger(set_reverse_children, key):
347349
if key == "good":
348350

349-
@event_handlers.use("good")
351+
@good_handler.use
350352
def callback():
351353
called_good_trigger.current = True
352354
set_reverse_children()
353355

354356
else:
355357

356-
@event_handlers.use("bad")
358+
@bad_handler.use
357359
def callback():
358360
raise ValueError("Called bad trigger")
359361

@@ -362,7 +364,7 @@ def callback():
362364
async with idom.Layout(RootComponent()) as layout:
363365
await layout.render()
364366
for _ in range(3):
365-
event = LayoutEvent(event_handlers.targets["good"], [])
367+
event = LayoutEvent(good_handler.target, [])
366368
await layout.dispatch(event)
367369

368370
assert called_good_trigger.current

0 commit comments

Comments
 (0)