import logging, operator from typing import Dict, List, Tuple, Union from common.orm.Database import Database from common.orm.HighLevel import get_or_create_object, update_or_create_object from common.orm.backend.Tools import key_to_str from common.orm.fields.ForeignKeyField import ForeignKeyField from common.orm.fields.IntegerField import IntegerField from common.orm.fields.PrimaryKeyField import PrimaryKeyField from common.orm.fields.StringField import StringField from common.orm.model.Model import Model from context.proto.context_pb2 import Constraint from context.service.database.Tools import fast_hasher, remove_dict_key LOGGER = logging.getLogger(__name__) class ConstraintsModel(Model): # pylint: disable=abstract-method pk = PrimaryKeyField() def dump(self) -> List[Dict]: db_constraint_pks = self.references(ConstraintModel) constraints = [ConstraintModel(self.database, pk).dump(include_position=True) for pk,_ in db_constraint_pks] constraints = sorted(constraints, key=operator.itemgetter('position')) return [remove_dict_key(constraint, 'position') for constraint in constraints] class ConstraintModel(Model): # pylint: disable=abstract-method pk = PrimaryKeyField() constraints_fk = ForeignKeyField(ConstraintsModel) position = IntegerField(min_value=0, required=True) constraint_type = StringField(required=True, allow_empty=False) constraint_value = StringField(required=True, allow_empty=False) def dump(self, include_position=True) -> Dict: # pylint: disable=arguments-differ result = { 'constraint_type': self.constraint_type, 'constraint_value': self.constraint_value, } if include_position: result['position'] = self.position return result def set_constraint( database : Database, db_constraints : ConstraintsModel, grpc_constraint, position : int ) -> Tuple[Constraint, bool]: str_constraint_key_hash = fast_hasher(grpc_constraint.constraint_type) str_constraint_key = key_to_str([db_constraints.pk, str_constraint_key_hash], separator=':') result : Tuple[ConstraintModel, bool] = update_or_create_object(database, ConstraintModel, str_constraint_key, { 'constraints_fk' : db_constraints, 'position' : position, 'constraint_type' : grpc_constraint.constraint_type, 'constraint_value': grpc_constraint.constraint_value, }) db_config_rule, updated = result return db_config_rule, updated def set_constraints( database : Database, db_parent_pk : str, constraints_name : str, grpc_constraints ) -> List[Tuple[Union[ConstraintsModel, ConstraintModel], bool]]: str_constraints_key = key_to_str([db_parent_pk, constraints_name], separator=':') result : Tuple[ConstraintsModel, bool] = get_or_create_object(database, ConstraintsModel, str_constraints_key) db_constraints, created = result db_objects = [(db_constraints, created)] for position,grpc_constraint in enumerate(grpc_constraints): result : Tuple[ConstraintModel, bool] = set_constraint(database, db_constraints, grpc_constraint, position) db_constraint, updated = result db_objects.append((db_constraint, updated)) return db_objects