messaging

Messaging framework foundations.

class frequent.messaging.HandlerRegistry[source]

Bases: collections.abc.Mapping

A registry containing mappings of message type to handler(s).

Examples

To add mappings:

>>> registry = HandlerRegistry()
>>> msg_bus = MessageBus()
>>> my_handler = MyMessageHandler(msg_bus)
>>> registry.add(MyMessage, my_handler)
>>> registry
<HandlerRegistry mappings={
   'MyMessage': [1 handler],
}>
add(msg_cls: Type[frequent.messaging.Message], handler: Union[Callable[[Message], None], MessageHandler], *handlers) → None[source]

Adds message handler(s) for the specified message type.

Parameters
  • msg_cls (type of Message) – The message class to add handler mappings for.

  • handler (MessageHandler or Callable) – The message handler to map to the given msg_cls type.

  • handlers (optional) – Additional message handler(s) to map to the given msg_cls type.

clear() → None[source]

Clears all the registered message handler mappings.

get(key: Type[frequent.messaging.Message], default: Any = None) → Sequence[Union[Callable[[frequent.messaging.Message], None], frequent.messaging.MessageHandler]][source]

Gets the message handler(s) associated with the given type.

Parameters
  • key (type of Message) – The message type to get the associated handlers for.

  • default (optional) – The value to return if no associated handlers are found.

Returns

The message handlers found (if any) or the default value given if no message handlers are found.

Return type

Sequence of Callable or object

remove(msg_cls: Type[frequent.messaging.Message]) → Sequence[Union[Callable[[frequent.messaging.Message], None], frequent.messaging.MessageHandler]][source]

Removes all mappings for the specified message type.

Parameters

msg_cls (type of Message) – The message type to remove all handler mappings for.

Returns

The message handlers which were mapped to the specified msg_cls type.

Return type

Sequence of Callable

Raises

NoHandlersFoundException – If no handlers were mapped to the specified msg_cls type.

class frequent.messaging.Message[source]

Bases: abc.ABC

Base class for all message objects.

id

A unique universal identifier for this message.

Type

UUID

Example

Derived message classes can be created from this class, though the message decorator is simpler to use. To create a message class directly from this base class:

from dataclasses import dataclass

@dataclass
class DirectMessage(Message):
    to: str
    sender: str
    text: str
>>> msg = DirectMessage('Liz', 'Doug', 'Hello!')
>>> msg
DirectMessage(to='Liz', sender='Doug', text='Hello!')
>>> msg.id
UUID('5a47c192-a50b-11e9-bc30-a434d9ba8632')
id = UUID('6236b68c-b6f5-11e9-a651-0242ac110002')
class frequent.messaging.MessageBus(registry: Optional[frequent.messaging.HandlerRegistry] = None)[source]

Bases: object

Message bus for routing messages to the appropriate handlers.

Parameters

registry (HandlerRegistry, optional) – The initial message type to handler mapping registry to use.

handle(msg: frequent.messaging.Message) → None[source]

Handles the given message.

Parameters

msg (Message) – The message object to handle.

Raises

NoHandlersFoundException – This exception will be raised if no message handlers were registered for the given type of message.

property registry

The handler mapping registry in use.

Type

HandlerRegistry

class frequent.messaging.MessageHandler(bus: frequent.messaging.MessageBus)[source]

Bases: object

Message handling base class.

property bus

The message bus to use for subsequent messages.

Type

MessageBus

abstract handle(msg: frequent.messaging.Message, successor: Union[Callable[[Message], None], MessageHandler, None] = None) → None[source]

Handles the given message object.

Parameters
  • msg (Message) – The message object to handle.

  • successor (MessageHandler or Callable, optional) – The next handler in the chain.

exception frequent.messaging.MessagingException[source]

Bases: Exception

Messaging framework base exception.

exception frequent.messaging.NoHandlersFoundException(msg_cls: Type[frequent.messaging.Message])[source]

Bases: frequent.messaging.MessagingException

Exception thrown if no message handlers were found.

Parameters

msg_cls (type of Message) – The message type which caused this exception to be thrown.

frequent.messaging.chain(*handlers) → Union[Callable[[frequent.messaging.Message], None], frequent.messaging.MessageHandler][source]

Chains multiple handlers together.

Parameters

handlers (MessageHandler or Callable) – The handlers to chain together, with each being passed the next handler via the successor keyword-argument.

Returns

The chained callable to use for message handling.

Return type

Callable

Examples

To chain together two handlers into one:

>>> class MessageIdLogger(MessageHandler):
...     def handle(self, msg, successor=None):
...         # Print our message's ID
...         print(msg.id)
...         # ... then call the next handler.
...         return successor(msg)
...
>>> def my_next_handler(msg):
...     if msg.code == 42:
...         print('The answer!')
...     else:
...         print('Not the answer...')
...     return
>>> chained_handler = chain(MessageIdLogger(), my_next_handler)
>>> ans_msg = MyMessage(42)
>>> not_ans_msg = MyMessage(41)
>>> chained_handler(answer_msg)
5a47c192-a50b-11e9-bc30-a434d9ba8632
The answer!
>>> chained_handler(not_ans_msg)
9a47c651-a52b-11f9-bc80-a484d9ba8633
Not the answer
frequent.messaging.convert_to_message(cls: type, target_cls: Type[frequent.messaging.Message]) → Type[frequent.messaging.Message][source]

Converts the given cls to the specified Message class.

User’s should prefer to use the message decorator as it’s easier to use and acts purely as a pass-through to this function. This function is provided to allow users to create decorators/functions to convert classes to their own custom Message subclasses.

Parameters
  • cls (type) – The class to convert to a Message subclass.

  • target_cls (type of Message) – The Message (sub)class to convert the given cls to.

Returns

The new class, converted to a subclass of Message.

Return type

type of Message

See also

message(), Message()

frequent.messaging.message(cls: type) → Type[frequent.messaging.Message][source]

Decorator for easily creating new Message sub-classes.

Parameters

cls (type) – The class to convert to a Message subclass.

Returns

The new class, converted to a subclass of Message.

Return type

type of Message

Example

To create a new Message class using this decorator:

@message
class MyMessage:
    target: str
    value: int

Then new instances are created just like named tuples:

>>> msg = MyMessage('calc_func', 42)
>>> msg
<MyMessage target='calc_func' value=42>