Skip to content

declearn.communication.utils.verify_client_messages_validity

Verify that received serialized messages match an expected type.

  • If all received messages matches expected type, deserialize them.
  • If any received message is an unexpected Error message, send an Error to non-error-send clients, then raise.
  • If any received message belongs to any other type, send an Error to each and every client, then raise.

Parameters:

Name Type Description Default
netwk NetworkServer

NetworkClient endpoint, from which the processed message was received.

required
received Dict[str, SerializedMessage]

Received SerializedMessage to type-check and deserialize.

required
expected Type[MessageT]

Expected Message subtype. Any subclass will be considered as valid.

required

Returns:

Name Type Description
messages Dict[str, MessageT]

Deserialized messages from received, with expected type, wrapped as a {client_name: client_message} dict.

Raises:

Type Description
ErrorMessageException

If any received message wraps an unexpected Error message.

MessageTypeException

If any received wrapped message does not match expected type.

Source code in declearn/communication/utils/_parse.py
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
async def verify_client_messages_validity(
    netwk: NetworkServer,
    received: Dict[str, SerializedMessage],
    expected: Type[MessageT],
) -> Dict[str, MessageT]:
    """Verify that received serialized messages match an expected type.

    - If all received messages matches expected type, deserialize them.
    - If any received message is an unexpected `Error` message, send an
      `Error` to non-error-send clients, then raise.
    - If any received message belongs to any other type, send an `Error`
      to each and every client, then raise.

    Parameters
    ----------
    netwk:
        `NetworkClient` endpoint, from which the processed message
        was received.
    received:
        Received `SerializedMessage` to type-check and deserialize.
    expected:
        Expected `Message` subtype. Any subclass will be considered
        as valid.

    Returns
    -------
    messages:
        Deserialized messages from `received`, with `expected` type,
        wrapped as a `{client_name: client_message}` dict.

    Raises
    ------
    ErrorMessageException
        If any `received` message wraps an unexpected `Error` message.
    MessageTypeException
        If any `received` wrapped message does not match `expected` type.
    """
    # Iterate over received messages to identify any unexpected 'Error' ones
    # or unexpected-type message.
    wrong_types = ""
    unexp_errors = {}  # type: Dict[str, str]
    for client, srm in received.items():
        if issubclass(srm.message_cls, expected):
            pass
        elif issubclass(srm.message_cls, Error):
            unexp_errors[client] = srm.deserialize().message
        else:
            wrong_types += f"\n\t{client}: '{srm.message_cls}'"
    # In case of Error messages, send an Error to other clients and raise.
    if unexp_errors:
        await netwk.broadcast_message(
            Error("Some clients reported errors."),
            clients=set(received).difference(unexp_errors),
        )
        error = "".join(
            f"\n\t{key}:{val}" for key, val in unexp_errors.items()
        )
        raise ErrorMessageException(
            f"Expected '{expected.__name__}' messages, got the following "
            f"Error messages:{error}"
        )
    # In case of unproper messages, send an Error to all clients and raise.
    if wrong_types:
        error = (
            f"Expected '{expected.__name__}' messages, got the following "
            f"unproper message types:{wrong_types}"
        )
        await netwk.broadcast_message(Error(error), clients=set(received))
        raise MessageTypeException(error)
    # If everyting is fine, deserialized and return the received messages.
    return {cli: srm.deserialize() for cli, srm in received.items()}