{'sender': 'Example sender'}
A dictionary can be given to the constructor:
- >>> m = Message('Example sender', {'key 1': 'value 1', 'key 2': 'value 2'})
+ >>> m = Message('Example sender',
+ ... {'key 1': 'value 1', 'key 2': 'value 2'})
>>> print(m)
{'sender': 'Example sender', 'key 1': 'value 1', 'key 2': 'value 2'}
+ A 'sender' set in the initial dictionary is overwritten by the explicitly
+ given sender in the first argument:
+ >>> m = Message('Example sender',
+ ... {'sender': 'Original sender', 'key': 'value'})
+ >>> print(m)
+ {'sender': 'Example sender', 'key': 'value'}
+
Or the message can be modified after construction:
>>> m = Message('Example sender', {'key 1': 'value 1'})
>>> m['key 2'] = 'value 2'
>>> print(m)
{'sender': 'Example sender', 'key 1': 'value 1', 'key 2': 'value 2'}
+
+ The 'sender' key can be overwritten, but this should only be done in
+ exceptional cases:
+ >>> m = Message('Example sender', {'key': 'value'})
+ >>> m['sender'] = 'New sender'
+ >>> print(m)
+ {'sender': 'New sender', 'key': 'value'}
"""
def __init__(self, sender: str,
>>> m = Message('Example sender', {'key 1': 'value 1'})
>>> print(m)
{'sender': 'Example sender', 'key 1': 'value 1'}
-
- The sender can be overwritten by the key-value pairs:
- >>> m = Message('Example sender', {'sender': 'Another sender'})
- >>> print(m)
- {'sender': 'Another sender'}
"""
if not isinstance(sender, str):
raise TypeError(f"'{sender}' is not a valid sender name"
" (not a string).")
- self['sender'] = sender
+ self['sender'] = ''
if init is not None:
self.update(init)
+ self['sender'] = sender
@staticmethod
def check_value(value: MessageValue) -> bool:
The "filter" key is required:
>>> asyncio.run(controlpi.test(
... {"Test Log": {"plugin": "Log"}}, []))
- 'filter' is a required property
- <BLANKLINE>
- Failed validating 'required' in schema:
- {'properties': {'filter': {'items': {'type': 'object'},
- 'type': 'array'}},
- 'required': ['filter']}
- <BLANKLINE>
- On instance:
- {'plugin': 'Log'}
+ data must contain ['filter'] properties
Configuration for 'Test Log' is not valid.
The "filter" key has to contain a list of message templates, i.e.,
>>> asyncio.run(controlpi.test(
... {"Test Log": {"plugin": "Log",
... "filter": [42]}}, []))
- 42 is not of type 'object'
- <BLANKLINE>
- Failed validating 'type' in schema['properties']['filter']['items']:
- {'type': 'object'}
- <BLANKLINE>
- On instance['filter'][0]:
- 42
+ data.filter[0] must be object
Configuration for 'Test Log' is not valid.
"""
The "messages" key is required:
>>> asyncio.run(controlpi.test(
... {"Test Init": {"plugin": "Init"}}, []))
- 'messages' is a required property
- <BLANKLINE>
- Failed validating 'required' in schema:
- {'properties': {'messages': {'items': {'type': 'object'},
- 'type': 'array'}},
- 'required': ['messages']}
- <BLANKLINE>
- On instance:
- {'plugin': 'Init'}
+ data must contain ['messages'] properties
Configuration for 'Test Init' is not valid.
The "messages" key has to contain a list of (partial) messages, i.e.,
>>> asyncio.run(controlpi.test(
... {"Test Init": {"plugin": "Init",
... "messages": [42]}}, []))
- 42 is not of type 'object'
- <BLANKLINE>
- Failed validating 'type' in schema['properties']['messages']['items']:
- {'type': 'object'}
- <BLANKLINE>
- On instance['messages'][0]:
- 42
+ data.messages[0] must be object
Configuration for 'Test Init' is not valid.
"""
"""Translate messages to an alias.
The "from" configuration key gets a message template and the
- configuration key "to" a (partial) message. All messages matching the
- template are received by the Alias instance and a message translated by
- removing the keys of the "from" template and adding the keys and values
- of the "to" message is sent. Keys that are neither in "from" nor in "to"
- are retained.
+ configuration key "to" a (partial) message. The "translate"
+ configuration key contains pairs of message keys, where the "from"
+ message key is translated to the "to" message key if present in the
+ message.
+
+ All messages matching the "from" template are received by the Alias
+ instance and a message translated by adding the keys and values of the
+ "to" message and the translated key-value pairs according to
+ "translate" is sent. Keys that are not "sender" and not modified by
+ "to" or "translate" are retained.
In the example, the two messages sent by the test are translated by the
Alias instance and the translated messages are sent by it preserving
test(): {'sender': 'test()', 'id': 42,
'content': 'Test Message', 'old': 'content'}
test(): {'sender': 'Test Alias', 'id': 'translated',
- 'content': 'Test Message', 'new': 'content'}
+ 'content': 'Test Message', 'old': 'content', 'new': 'content'}
test(): {'sender': 'test()', 'id': 42,
'content': 'Second Message', 'old': 'content'}
test(): {'sender': 'Test Alias', 'id': 'translated',
- 'content': 'Second Message', 'new': 'content'}
+ 'content': 'Second Message', 'old': 'content', 'new': 'content'}
- The "from" and "to" keys are required:
+ The "from" key is required:
>>> asyncio.run(controlpi.test(
... {"Test Alias": {"plugin": "Alias"}}, []))
- 'from' is a required property
- <BLANKLINE>
- Failed validating 'required' in schema:
- {'properties': {'from': {'type': 'object'},
- 'to': {'type': 'object'},
- 'translate': {'items': {'properties': {'from': {'type': 'string'},
- 'to': {'type': 'string'}},
- 'type': 'object'},
- 'type': 'array'}},
- 'required': ['from', 'to']}
- <BLANKLINE>
- On instance:
- {'plugin': 'Alias'}
- 'to' is a required property
- <BLANKLINE>
- Failed validating 'required' in schema:
- {'properties': {'from': {'type': 'object'},
- 'to': {'type': 'object'},
- 'translate': {'items': {'properties': {'from': {'type': 'string'},
- 'to': {'type': 'string'}},
- 'type': 'object'},
- 'type': 'array'}},
- 'required': ['from', 'to']}
- <BLANKLINE>
- On instance:
- {'plugin': 'Alias'}
+ data must contain ['from'] properties
Configuration for 'Test Alias' is not valid.
The "from" key has to contain a message template and the "to" key a
... {"Test Alias": {"plugin": "Alias",
... "from": 42,
... "to": 42}}, []))
- 42 is not of type 'object'
- <BLANKLINE>
- Failed validating 'type' in schema['properties']['from']:
- {'type': 'object'}
- <BLANKLINE>
- On instance['from']:
- 42
- 42 is not of type 'object'
- <BLANKLINE>
- Failed validating 'type' in schema['properties']['to']:
- {'type': 'object'}
- <BLANKLINE>
- On instance['to']:
- 42
+ data.from must be object
+ Configuration for 'Test Alias' is not valid.
+ >>> asyncio.run(controlpi.test(
+ ... {"Test Alias": {"plugin": "Alias",
+ ... "from": {"id": {"const": 42}},
+ ... "to": 42}}, []))
+ data.to must be object
Configuration for 'Test Alias' is not valid.
"""
CONF_SCHEMA = {'properties': {'from': {'type': 'object'},
'to': {'type': 'object'},
'translate': {'type': 'array',
- 'items': {'type': 'object',
- 'properties': {'from': {'type': 'string'},
- 'to': {'type': 'string'}}}}},
- 'required': ['from', 'to']}
+ 'items':
+ {'type': 'object',
+ 'properties':
+ {'from':
+ {'type': 'string'},
+ 'to':
+ {'type': 'string'}}}}},
+ 'required': ['from']}
"""Schema for Alias plugin configuration.
Required configuration keys:
- 'from': template of messages to be translated.
+
+ Optional configuration keys:
+
- 'to': translated message to be sent.
+ - 'translate': array of pairs of keys to be translated.
"""
- async def alias(self, message: Message) -> None:
- """Translate and send message."""
- alias_message = Message(self.name)
- alias_message.update(self.conf['to'])
- for key in message:
- if key != 'sender' and key not in self.conf['from']:
- if key in self._translate:
- alias_message[self._translate[key]] = message[key]
- else:
- alias_message[key] = message[key]
- await self.bus.send(alias_message)
-
def process_conf(self) -> None:
"""Register plugin as bus client."""
+ self._to = {}
+ if 'to' in self.conf:
+ self._to = self.conf['to']
self._translate = {}
if 'translate' in self.conf:
for pair in self.conf['translate']:
[self.conf['from']],
self.alias)
+ async def alias(self, message: Message) -> None:
+ """Translate and send message."""
+ alias_message = Message(self.name, message)
+ alias_message.update(self._to)
+ for key in self._translate:
+ if key in message:
+ alias_message[self._translate[key]] = message[key]
+ await self.bus.send(alias_message)
+
async def run(self) -> None:
"""Run no code proactively."""
pass