From 6187faf20384b0c5a4966343b2d4ca47f8b11e45 Mon Sep 17 00:00:00 2001 From: Philip Paquette Date: Wed, 26 Sep 2018 07:48:55 -0400 Subject: Release v1.0.0 - Diplomacy Game Engine - AGPL v3+ License --- diplomacy/utils/network_data.py | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 diplomacy/utils/network_data.py (limited to 'diplomacy/utils/network_data.py') diff --git a/diplomacy/utils/network_data.py b/diplomacy/utils/network_data.py new file mode 100644 index 0000000..48b285a --- /dev/null +++ b/diplomacy/utils/network_data.py @@ -0,0 +1,79 @@ +# ============================================================================== +# Copyright (C) 2019 - Philip Paquette, Steven Bocco +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU Affero General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along +# with this program. If not, see . +# ============================================================================== +""" Abstract Jsonable class to create data intended to be exchanged on network. + Used for requests, responses and notifications. + To write a sub-class, you must first write a base class for data category (e.g. notifications): + + - Define header model for network data. + + - Define ID field for data category (e.g. "notification_id"). This will be used to create unique + identifier for every data exchanged on network. + + - Then every sub-class from base class must define parameters (params) model. Params and header + must not share any field. +""" +import uuid + +from diplomacy.utils import strings, exceptions +from diplomacy.utils.common import assert_no_common_keys, camel_case_to_snake_case +from diplomacy.utils.jsonable import Jsonable + +class NetworkData(Jsonable): + """ Abstract class for network-exchanged data. """ + __slots__ = ['name'] + # NB: header must have a `name` field and a field named `id_field`. + header = {} + params = {} + id_field = None + + def __init__(self, **kwargs): + self.name = None # type: str + + # Setting default values + kwargs[strings.NAME] = kwargs.get(strings.NAME, None) or self.get_class_name() + kwargs[self.id_field] = kwargs.get(self.id_field, None) or str(uuid.uuid4()) + if kwargs[strings.NAME] != self.get_class_name(): + raise exceptions.DiplomacyException('Expected request name %s, got %s' % + (self.get_class_name(), kwargs[strings.NAME])) + + # Building + super(NetworkData, self).__init__(**kwargs) + + @classmethod + def get_class_name(cls): + """ Returns the class name in snake_case. """ + return camel_case_to_snake_case(cls.__name__) + + @classmethod + def validate_params(cls): + """ Called when getting model to validate parameters. Called once per class. """ + pass + + @classmethod + def build_model(cls): + """ Return model associated to current class. You can either define model class field + or override this function. + """ + # Validating model parameters (header and params must have different keys) + assert_no_common_keys(cls.header, cls.params) + cls.validate_params() + + # Building model. + model = cls.header.copy() + model.update(cls.params.copy()) + model[strings.NAME] = (cls.get_class_name(),) + return model -- cgit v1.2.3