mirror of
https://github.com/avatao-content/baseimage-tutorial-framework
synced 2024-11-14 02:57:18 +00:00
Improve EventHandlerFactoryBase
This commit is contained in:
parent
f1679ffb50
commit
f73c059429
@ -4,25 +4,34 @@ from .event_handler import EventHandler
|
|||||||
|
|
||||||
|
|
||||||
class EventHandlerFactoryBase:
|
class EventHandlerFactoryBase:
|
||||||
def build(self, event_handler, *, keys=None):
|
def build(self, event_handler, *, keys=None, event_handler_type=EventHandler):
|
||||||
analyzer = EventHandlerAnalyzer(event_handler, keys)
|
builder = EventHandlerBuilder(event_handler, keys, event_handler_type)
|
||||||
event_handler = self._build_from_callable(analyzer)
|
|
||||||
event_handler.start()
|
|
||||||
return event_handler
|
|
||||||
|
|
||||||
def _build_from_callable(self, analyzer):
|
|
||||||
server_connector = self._build_server_connector()
|
server_connector = self._build_server_connector()
|
||||||
server_connector.subscribe(analyzer.keys)
|
real_event_handler = builder.build(server_connector)
|
||||||
event_handler = EventHandler(server_connector)
|
event_handler.server_connector = server_connector
|
||||||
event_handler.handle_event = analyzer.handle_event
|
|
||||||
with suppress(AttributeError):
|
with suppress(AttributeError):
|
||||||
event_handler.cleanup = analyzer.cleanup
|
event_handler.start()
|
||||||
return event_handler
|
real_event_handler.start()
|
||||||
|
return real_event_handler
|
||||||
|
|
||||||
def _build_server_connector(self):
|
def _build_server_connector(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
class EventHandlerBuilder:
|
||||||
|
def __init__(self, event_handler, supplied_keys, event_handler_type):
|
||||||
|
self._analyzer = EventHandlerAnalyzer(event_handler, supplied_keys)
|
||||||
|
self._event_handler_type = event_handler_type
|
||||||
|
|
||||||
|
def build(self, server_connector):
|
||||||
|
server_connector.subscribe(*self._analyzer.keys)
|
||||||
|
event_handler = self._event_handler_type(server_connector)
|
||||||
|
event_handler.handle_event = self._analyzer.handle_event
|
||||||
|
with suppress(AttributeError):
|
||||||
|
event_handler.cleanup = self._analyzer.cleanup
|
||||||
|
return event_handler
|
||||||
|
|
||||||
|
|
||||||
class EventHandlerAnalyzer:
|
class EventHandlerAnalyzer:
|
||||||
def __init__(self, event_handler, supplied_keys):
|
def __init__(self, event_handler, supplied_keys):
|
||||||
self._event_handler = event_handler
|
self._event_handler = event_handler
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name,attribute-defined-outside-init
|
||||||
from secrets import token_urlsafe
|
from secrets import token_urlsafe
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
@ -18,16 +18,16 @@ class MockServerConnector:
|
|||||||
self.keys = []
|
self.keys = []
|
||||||
self._on_message = None
|
self._on_message = None
|
||||||
|
|
||||||
def register_callback(self, callback):
|
|
||||||
self._on_message = callback
|
|
||||||
|
|
||||||
def simulate_message(self, message):
|
def simulate_message(self, message):
|
||||||
self._on_message(message)
|
self._on_message(message)
|
||||||
|
|
||||||
def subscribe(self, keys):
|
def register_callback(self, callback):
|
||||||
|
self._on_message = callback
|
||||||
|
|
||||||
|
def subscribe(self, *keys):
|
||||||
self.keys.extend(keys)
|
self.keys.extend(keys)
|
||||||
|
|
||||||
def unsubscribe(self, keys):
|
def unsubscribe(self, *keys):
|
||||||
for key in keys:
|
for key in keys:
|
||||||
self.keys.remove(key)
|
self.keys.remove(key)
|
||||||
|
|
||||||
@ -38,17 +38,31 @@ class MockServerConnector:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MockEventHandler:
|
class MockEventHandlerStub:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.server_connector = None
|
||||||
|
self.last_message = None
|
||||||
self.cleaned_up = False
|
self.cleaned_up = False
|
||||||
|
self.started = False
|
||||||
|
|
||||||
def handle_event(self, message, server_connector):
|
def start(self):
|
||||||
pass
|
self.started = True
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self.cleaned_up = True
|
self.cleaned_up = True
|
||||||
|
|
||||||
|
|
||||||
|
class MockEventHandler(MockEventHandlerStub):
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
def handle_event(self, message, server_connector):
|
||||||
|
self.last_message = message
|
||||||
|
|
||||||
|
|
||||||
|
class MockCallable(MockEventHandlerStub):
|
||||||
|
def __call__(self, message, server_connector):
|
||||||
|
self.last_message = message
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def test_msg():
|
def test_msg():
|
||||||
yield token_urlsafe(randint(16, 64))
|
yield token_urlsafe(randint(16, 64))
|
||||||
@ -63,12 +77,16 @@ def test_keys():
|
|||||||
|
|
||||||
|
|
||||||
def test_build_from_object(test_keys, test_msg):
|
def test_build_from_object(test_keys, test_msg):
|
||||||
mock_eh = MockEventHandler()
|
mock_eh = MockEventHandlerStub()
|
||||||
def test_handle_event(message, server_connector):
|
def handle_event(message, server_connector):
|
||||||
raise RuntimeError(message, server_connector.keys)
|
raise RuntimeError(message, server_connector.keys)
|
||||||
mock_eh.handle_event = test_handle_event
|
mock_eh.handle_event = handle_event
|
||||||
|
|
||||||
|
assert not mock_eh.started
|
||||||
eh = MockEventHandlerFactory().build(mock_eh, keys=test_keys)
|
eh = MockEventHandlerFactory().build(mock_eh, keys=test_keys)
|
||||||
|
|
||||||
|
assert mock_eh.started
|
||||||
|
assert mock_eh.server_connector is eh.server_connector
|
||||||
with pytest.raises(RuntimeError) as err:
|
with pytest.raises(RuntimeError) as err:
|
||||||
eh.server_connector.simulate_message(test_msg)
|
eh.server_connector.simulate_message(test_msg)
|
||||||
msg, keys = err.args
|
msg, keys = err.args
|
||||||
@ -79,34 +97,52 @@ def test_build_from_object(test_keys, test_msg):
|
|||||||
assert mock_eh.cleaned_up
|
assert mock_eh.cleaned_up
|
||||||
|
|
||||||
|
|
||||||
def test_build_from_object_with_keys(test_keys):
|
def test_build_from_object_with_keys(test_keys, test_msg):
|
||||||
mock_eh = MockEventHandler()
|
mock_eh = MockEventHandler()
|
||||||
mock_eh.keys = test_keys # pylint: disable=attribute-defined-outside-init
|
mock_eh.keys = test_keys
|
||||||
|
|
||||||
|
assert not mock_eh.started
|
||||||
eh = MockEventHandlerFactory().build(mock_eh)
|
eh = MockEventHandlerFactory().build(mock_eh)
|
||||||
|
|
||||||
|
assert mock_eh.server_connector.keys == test_keys
|
||||||
|
assert eh.server_connector is mock_eh.server_connector
|
||||||
|
assert mock_eh.started
|
||||||
|
assert not mock_eh.last_message
|
||||||
|
eh.server_connector.simulate_message(test_msg)
|
||||||
|
assert mock_eh.last_message == test_msg
|
||||||
assert not mock_eh.cleaned_up
|
assert not mock_eh.cleaned_up
|
||||||
EventHandler.stop_all_instances()
|
EventHandler.stop_all_instances()
|
||||||
assert mock_eh.cleaned_up
|
assert mock_eh.cleaned_up
|
||||||
assert eh.server_connector.keys == test_keys
|
|
||||||
|
|
||||||
|
def test_build_from_simple_object(test_keys, test_msg):
|
||||||
|
class SimpleMockEventHandler:
|
||||||
|
# pylint: disable=no-self-use
|
||||||
|
def handle_event(self, message, server_connector):
|
||||||
|
raise RuntimeError(message, server_connector)
|
||||||
|
|
||||||
|
mock_eh = SimpleMockEventHandler()
|
||||||
|
eh = MockEventHandlerFactory().build(mock_eh, keys=test_keys)
|
||||||
|
|
||||||
|
with pytest.raises(RuntimeError) as err:
|
||||||
|
eh.server_connector.simulate_message(test_msg)
|
||||||
|
msg, keys = err.args
|
||||||
|
assert msg == test_msg
|
||||||
|
assert keys == test_keys
|
||||||
|
|
||||||
|
|
||||||
def test_build_from_callable(test_keys, test_msg):
|
def test_build_from_callable(test_keys, test_msg):
|
||||||
class SomeCallable:
|
mock_eh = MockCallable()
|
||||||
def __init__(self):
|
|
||||||
self.message = None
|
|
||||||
self.cleaned_up = False
|
|
||||||
def __call__(self, message, server_connector):
|
|
||||||
self.message = message
|
|
||||||
def cleanup(self):
|
|
||||||
self.cleaned_up = True
|
|
||||||
|
|
||||||
mock_eh = SomeCallable()
|
assert not mock_eh.started
|
||||||
eh = MockEventHandlerFactory().build(mock_eh, keys=test_keys)
|
eh = MockEventHandlerFactory().build(mock_eh, keys=test_keys)
|
||||||
|
|
||||||
|
assert mock_eh.started
|
||||||
|
assert mock_eh.server_connector is eh.server_connector
|
||||||
assert eh.server_connector.keys == test_keys
|
assert eh.server_connector.keys == test_keys
|
||||||
assert not mock_eh.message
|
assert not mock_eh.last_message
|
||||||
eh.server_connector.simulate_message(test_msg)
|
eh.server_connector.simulate_message(test_msg)
|
||||||
assert mock_eh.message == test_msg
|
assert mock_eh.last_message == test_msg
|
||||||
assert not mock_eh.cleaned_up
|
assert not mock_eh.cleaned_up
|
||||||
eh.stop()
|
eh.stop()
|
||||||
assert mock_eh.cleaned_up
|
assert mock_eh.cleaned_up
|
||||||
@ -133,7 +169,7 @@ def test_build_from_lambda(test_keys, test_msg):
|
|||||||
eh.server_connector.simulate_message(test_msg)
|
eh.server_connector.simulate_message(test_msg)
|
||||||
|
|
||||||
|
|
||||||
def test_build_raises_if_no_key():
|
def test_build_raises_if_no_key(test_keys):
|
||||||
eh = MockEventHandler()
|
eh = MockEventHandler()
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
MockEventHandlerFactory().build(eh)
|
MockEventHandlerFactory().build(eh)
|
||||||
@ -145,3 +181,6 @@ def test_build_raises_if_no_key():
|
|||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
MockEventHandlerFactory().build(lambda msg, sc: None)
|
MockEventHandlerFactory().build(lambda msg, sc: None)
|
||||||
|
|
||||||
|
eh.keys = test_keys
|
||||||
|
MockEventHandlerFactory().build(eh)
|
||||||
|
Loading…
Reference in New Issue
Block a user