Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable adding listeners to event before the event is registered #97

Merged
merged 3 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions jupyter_events/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,16 @@ def register_event_schema(self, schema: SchemaType) -> None:

Get this registered schema using the EventLogger.schema.get() method.
"""

event_schema = self.schemas.register(schema) # type:ignore[arg-type]
key = event_schema.id
self._modifiers[key] = set()
self._modified_listeners[key] = set()
self._unmodified_listeners[key] = set()
# It's possible that listeners and modifiers have been added for this
# schema before the schema is registered.
if key not in self._modifiers:
self._modifiers[key] = set()
if key not in self._modified_listeners:
self._modified_listeners[key] = set()
if key not in self._unmodified_listeners:
self._unmodified_listeners[key] = set()

def register_handler(self, handler: logging.Handler) -> None:
"""Register a new logging handler to the Event Logger.
Expand Down Expand Up @@ -205,7 +209,11 @@ def add_modifier(
# If the schema ID and version is given, only add
# this modifier to that schema
if schema_id:
self._modifiers[schema_id].add(modifier)
# If the schema hasn't been added yet,
# start a placeholder set.
modifiers = self._modifiers.get(schema_id, set())
modifiers.add(modifier)
self._modifiers[schema_id] = modifiers
return
for id_ in self._modifiers:
if schema_id is None or id_ == schema_id:
Expand Down Expand Up @@ -264,9 +272,16 @@ def add_listener(
# this modifier to that schema
if schema_id:
if modified:
self._modified_listeners[schema_id].add(listener)
# If the schema hasn't been added yet,
# start a placeholder set.
listeners = self._modified_listeners.get(schema_id, set())
listeners.add(listener)
self._modified_listeners[schema_id] = listeners
return
self._unmodified_listeners[schema_id].add(listener)
listeners = self._unmodified_listeners.get(schema_id, set())
listeners.add(listener)
self._unmodified_listeners[schema_id] = listeners
return
for id_ in self.schemas.schema_ids:
if schema_id is None or id_ == schema_id:
if modified:
Expand Down
40 changes: 39 additions & 1 deletion tests/test_listeners.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest

from jupyter_events.logger import EventLogger
from jupyter_events.logger import EventLogger, SchemaNotRegistered
from jupyter_events.schema import EventSchema

from .utils import SCHEMA_PATH
Expand Down Expand Up @@ -138,3 +138,41 @@ async def my_listener(logger: EventLogger, schema_id: str, data: dict) -> None:
assert listener_was_called
# Check that the active listeners are cleaned up.
assert len(event_logger._active_listeners) == 0


@pytest.mark.parametrize(
# Make sure no schemas are added at the start of this test.
"jp_event_schemas",
[
# Empty events list.
[]
],
)
async def test_listener_added_before_schemas_passes(jp_event_logger, schema):
# Ensure there are no schemas listed.
assert len(jp_event_logger.schemas.schema_ids) == 0

listener_was_called = False

async def my_listener(logger: EventLogger, schema_id: str, data: dict) -> None:
nonlocal listener_was_called
listener_was_called = True

# Add the listener without any schemas
jp_event_logger.add_listener(schema_id=schema.id, listener=my_listener)

# Proof that emitting the event won't success
with pytest.warns(SchemaNotRegistered):
jp_event_logger.emit(schema_id=schema.id, data={"prop": "hello, world"})

assert not listener_was_called

# Now register the event and emit.
jp_event_logger.register_event_schema(schema)

# Try emitting the event again and ensure the listener saw it.
jp_event_logger.emit(schema_id=schema.id, data={"prop": "hello, world"})
await jp_event_logger.gather_listeners()
assert listener_was_called
# Check that the active listeners are cleaned up.
assert len(jp_event_logger._active_listeners) == 0
Loading