Skip to content

Commit e7784fd

Browse files
authored
Enable adding listeners to event before the event is registered (#97)
* Enable adding listeners to event before the event is registered * pre-commit issues * use pytest.warns when schema is not registered
1 parent 8654e87 commit e7784fd

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

jupyter_events/logger.py

+22-7
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,16 @@ def register_event_schema(self, schema: SchemaType) -> None:
142142
143143
Get this registered schema using the EventLogger.schema.get() method.
144144
"""
145-
146145
event_schema = self.schemas.register(schema) # type:ignore[arg-type]
147146
key = event_schema.id
148-
self._modifiers[key] = set()
149-
self._modified_listeners[key] = set()
150-
self._unmodified_listeners[key] = set()
147+
# It's possible that listeners and modifiers have been added for this
148+
# schema before the schema is registered.
149+
if key not in self._modifiers:
150+
self._modifiers[key] = set()
151+
if key not in self._modified_listeners:
152+
self._modified_listeners[key] = set()
153+
if key not in self._unmodified_listeners:
154+
self._unmodified_listeners[key] = set()
151155

152156
def register_handler(self, handler: logging.Handler) -> None:
153157
"""Register a new logging handler to the Event Logger.
@@ -205,7 +209,11 @@ def add_modifier(
205209
# If the schema ID and version is given, only add
206210
# this modifier to that schema
207211
if schema_id:
208-
self._modifiers[schema_id].add(modifier)
212+
# If the schema hasn't been added yet,
213+
# start a placeholder set.
214+
modifiers = self._modifiers.get(schema_id, set())
215+
modifiers.add(modifier)
216+
self._modifiers[schema_id] = modifiers
209217
return
210218
for id_ in self._modifiers:
211219
if schema_id is None or id_ == schema_id:
@@ -264,9 +272,16 @@ def add_listener(
264272
# this modifier to that schema
265273
if schema_id:
266274
if modified:
267-
self._modified_listeners[schema_id].add(listener)
275+
# If the schema hasn't been added yet,
276+
# start a placeholder set.
277+
listeners = self._modified_listeners.get(schema_id, set())
278+
listeners.add(listener)
279+
self._modified_listeners[schema_id] = listeners
268280
return
269-
self._unmodified_listeners[schema_id].add(listener)
281+
listeners = self._unmodified_listeners.get(schema_id, set())
282+
listeners.add(listener)
283+
self._unmodified_listeners[schema_id] = listeners
284+
return
270285
for id_ in self.schemas.schema_ids:
271286
if schema_id is None or id_ == schema_id:
272287
if modified:

tests/test_listeners.py

+39-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import pytest
77

8-
from jupyter_events.logger import EventLogger
8+
from jupyter_events.logger import EventLogger, SchemaNotRegistered
99
from jupyter_events.schema import EventSchema
1010

1111
from .utils import SCHEMA_PATH
@@ -138,3 +138,41 @@ async def my_listener(logger: EventLogger, schema_id: str, data: dict) -> None:
138138
assert listener_was_called
139139
# Check that the active listeners are cleaned up.
140140
assert len(event_logger._active_listeners) == 0
141+
142+
143+
@pytest.mark.parametrize(
144+
# Make sure no schemas are added at the start of this test.
145+
"jp_event_schemas",
146+
[
147+
# Empty events list.
148+
[]
149+
],
150+
)
151+
async def test_listener_added_before_schemas_passes(jp_event_logger, schema):
152+
# Ensure there are no schemas listed.
153+
assert len(jp_event_logger.schemas.schema_ids) == 0
154+
155+
listener_was_called = False
156+
157+
async def my_listener(logger: EventLogger, schema_id: str, data: dict) -> None:
158+
nonlocal listener_was_called
159+
listener_was_called = True
160+
161+
# Add the listener without any schemas
162+
jp_event_logger.add_listener(schema_id=schema.id, listener=my_listener)
163+
164+
# Proof that emitting the event won't success
165+
with pytest.warns(SchemaNotRegistered):
166+
jp_event_logger.emit(schema_id=schema.id, data={"prop": "hello, world"})
167+
168+
assert not listener_was_called
169+
170+
# Now register the event and emit.
171+
jp_event_logger.register_event_schema(schema)
172+
173+
# Try emitting the event again and ensure the listener saw it.
174+
jp_event_logger.emit(schema_id=schema.id, data={"prop": "hello, world"})
175+
await jp_event_logger.gather_listeners()
176+
assert listener_was_called
177+
# Check that the active listeners are cleaned up.
178+
assert len(jp_event_logger._active_listeners) == 0

0 commit comments

Comments
 (0)