from typing import Type from marshmallow import fields, validate from apollo_utils.core.utils.ext_enum import ExtEnum, ALL from apollo_utils.service.schemas.fields.list import SplitUniqueListField from apollo_utils.service.schemas.mixins.enum import EnumFieldMixin class EnumField(EnumFieldMixin, fields.String): """Validate and convert string to enum.""" pass class EnumIntField(EnumFieldMixin, fields.Int): pass class EnumListField(SplitUniqueListField): """Deserialize list of strings using enum as allowed values and with possible converting ALL to all enum values. It has pretty similar naming to EnumField, but EnumField returns enum while this field returns a list of strings, this is because of possible ALL value. TODO: Return a list of enum values. """ def __init__( self, enum: Type[ExtEnum], allow_all: bool = False, as_enum: bool = False, missing_all: bool = False, ignore_unknown: bool = False, int_enum: bool = False, *args, **kwargs, ): """Init object. Args: enum: Possible values container. allow_all: Allow using ALL as a value. as_enum: Result should be a list of enums, not strings. missing_all: All values as missing. ignore_unknown: Ignore unknown values. int_enum: Int or str enum. """ self._enum = enum self._allow_all = allow_all self._as_enum = as_enum self._ignore_unknown = ignore_unknown self._int_enum = int_enum if missing_all: kwargs["missing"] = list(enum) super().__init__( ( fields.Integer() if int_enum else fields.String( **( {} if ignore_unknown else {"validate": validate.OneOf(self._enum.values(with_all=self._allow_all))} ) ) ), *args, **kwargs, ) def _deserialize(self, value, attr, data, **kwargs): value = super()._deserialize(value, attr, data, **kwargs) all_values = self._enum.values() if self._allow_all and ALL in value: value = all_values if self._ignore_unknown: value = [i for i in value if (i if self._int_enum else i.lower()) in all_values] if self._as_enum: value = [self._enum(i) for i in value] return value