class Test(Model):
        first = Keyword()

        @first.setter
        def first(self, value):
            assert isinstance(value, str)
            if value.startswith('cat'):
                raise CatError()
            return value
def get_random_tags() -> dict:
    desired_tag_types = [
        'attribution.actor',
        'network.static.ip',
        'network.dynamic.ip',
        'network.static.domain',
        'network.dynamic.domain',
        'network.static.uri',
        'network.dynamic.uri',
        'av.virus_name',
        'attribution.implant',
        'file.rule.yara',
        'file.behavior',
        'attribution.exploit',
        'technique.packer',
        'technique.obfuscation'
    ]
    out = {}
    flat_fields = Tagging.flat_fields()
    # noinspection PyUnresolvedReferences
    flat_fields.pop('file.rule')
    tag_list = random.choices(list(flat_fields.keys()), k=random.randint(0, 2))
    tag_list.extend(random.choices(desired_tag_types, k=random.randint(1, 2)))
    for key in tag_list:
        parts = key.split(".")
        d = out
        for part in parts[:-1]:
            if part not in d:
                d[part] = dict()
            d = d[part]

        if parts[-1] not in d:
            d[parts[-1]] = []

        for _ in range(random.randint(1, 2)):
            d[parts[-1]].append(random_data_for_field(flat_fields.get(key, Keyword()), key.split(".")[-1]))

    return out
 class Test(Model):
     first = Keyword()
     second = Integer()
 class A(Model):
     fast = Integer(default=1)
     slow = Keyword(default='abc')
     count = List(Integer())
 class Flag(Model):
     uuid = UUID()
     name = Keyword()
     fans = List(Integer(), default=[])
 class A(Model):
     fast = Integer(default=1)
     slow = Keyword(default='abc')
     flags = List(Keyword(), default=['cat-snack'])
 class SubModel(Model):
     default = Keyword()
     indexed = Keyword(index=True)
     not_indexed = Keyword(index=False)
 class Test3(Model):
     default = Keyword()
     indexed = Keyword(index=True)
     not_indexed = Keyword(index=False)
 class InnerB(Model):
     number = Integer()
     value = Keyword()
 class InnerA(Model):
     number = Integer(default=10)
     value = Keyword()
 class Entry(Model):
     value = Integer()
     key = Keyword()
 class TestCompound(Model):
     key = Keyword()
     value = Keyword()
    def _validate_operations(self, operations):
        """
        Validate the different operations received for a partial update

        TODO: When the field is of type Mapping, the validation/check only works for depth 1. A full recursive
              solution is needed to support multi-depth cases.

        :param operations: list of operation tuples
        :raises: DatastoreException if operation not valid
        """
        if self.model_class:
            fields = self.model_class.flat_fields(show_compound=True)
            if 'classification in fields':
                fields.update({
                    "__access_lvl__": Integer(),
                    "__access_req__": List(Keyword()),
                    "__access_grp1__": List(Keyword()),
                    "__access_grp2__": List(Keyword())
                })
        else:
            fields = None

        ret_ops = []
        for op, doc_key, value in operations:
            if op not in self.UPDATE_OPERATIONS:
                raise DataStoreException(f"Not a valid Update Operation: {op}")

            if fields is not None:
                prev_key = None
                if doc_key not in fields:
                    if '.' in doc_key:
                        prev_key = doc_key[:doc_key.rindex('.')]
                        if prev_key in fields and not isinstance(
                                fields[prev_key], Mapping):
                            raise DataStoreException(
                                f"Invalid field for model: {prev_key}")
                    else:
                        raise DataStoreException(
                            f"Invalid field for model: {doc_key}")

                if prev_key:
                    field = fields[prev_key].child_type
                else:
                    field = fields[doc_key]

                if op in [self.UPDATE_APPEND, self.UPDATE_REMOVE]:
                    try:
                        value = field.check(value)
                    except (ValueError, TypeError, AttributeError):
                        raise DataStoreException(
                            f"Invalid value for field {doc_key}: {value}")

                elif op in [self.UPDATE_SET, self.UPDATE_DEC, self.UPDATE_INC]:
                    try:
                        value = field.check(value)
                    except (ValueError, TypeError):
                        raise DataStoreException(
                            f"Invalid value for field {doc_key}: {value}")

                if isinstance(value, Model):
                    value = value.as_primitives()
                elif isinstance(value, datetime):
                    value = value.isoformat()
                elif isinstance(value, ClassificationObject):
                    value = str(value)

            ret_ops.append((op, doc_key, value))

        return ret_ops