-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
94 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,10 @@ | ||
import enum | ||
from typing import ClassVar | ||
|
||
from addon_service.common.enums import IntEnumForEnum | ||
from addon_toolkit.categories.storage import StorageCapability | ||
|
||
|
||
__all__ = ("IntStorageCapability",) | ||
|
||
|
||
class _IntEnumForEnum(enum.IntEnum): | ||
__base_enum: ClassVar[type[enum.Enum]] | ||
|
||
def __init_subclass__(cls, /, base_enum: type[enum.Enum], **kwargs): | ||
super().__init_subclass__(**kwargs) | ||
cls.__base_enum = base_enum | ||
# ensure enums have same names | ||
_base_names = {_item.name for _item in base_enum} | ||
_int_names = {_item.name for _item in cls} | ||
assert _base_names == _int_names | ||
|
||
@classmethod | ||
def to_int(cls, base_enum_member): | ||
return cls[base_enum_member.name] | ||
|
||
@classmethod | ||
def as_django_choices(cls): | ||
return [(int(_item), _item.name) for _item in cls] | ||
|
||
def to_base_enum(self) -> enum.Enum: | ||
return self.__base_enum[self.name] | ||
|
||
|
||
class IntStorageCapability(_IntEnumForEnum, base_enum=StorageCapability): | ||
class IntStorageCapability(IntEnumForEnum, base_enum=StorageCapability): | ||
ACCESS = 1 | ||
UPDATE = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,11 @@ | ||
import enum | ||
from addon_service.capability.models import IntStorageCapability | ||
from addon_service.common.enums.serializers import DualEnumsListField | ||
from addon_toolkit.categories.storage import StorageCapability | ||
|
||
from rest_framework_json_api import serializers | ||
|
||
from addon_service.capability.models import ( | ||
IntStorageCapability, | ||
StorageCapability, | ||
) | ||
|
||
|
||
class EnumsMultipleChoiceField(serializers.MultipleChoiceField): | ||
__internal_enum: type[enum.Enum] | ||
__external_enum: type[enum.Enum] | ||
|
||
def __init__(self, /, internal_enum, external_enum, **kwargs): | ||
_choices = {_external_member.value for _external_member in external_enum} | ||
super().__init__(**kwargs, choices=_choices) | ||
self.__internal_enum = internal_enum | ||
self.__external_enum = external_enum | ||
|
||
def to_internal_value(self, data): | ||
_names = super().to_internal_value(data) | ||
return [self._to_internal_enum_member(_name) for _name in _names] | ||
|
||
def to_representation(self, value): | ||
_member_list = super().to_representation(value) | ||
return {self._to_external_enum_value(_member) for _member in _member_list} | ||
|
||
def _to_internal_enum_member(self, external_value): | ||
_external_member = self.__external_enum(external_value) | ||
return self.__internal_enum[_external_member.name] | ||
|
||
def _to_external_enum_value(self, internal_value): | ||
_internal_member = self.__internal_enum(internal_value) | ||
_external_member = self.__external_enum[_internal_member.name] | ||
return _external_member.value | ||
|
||
|
||
def StorageCapabilityField(**kwargs): | ||
return EnumsMultipleChoiceField( | ||
external_enum=StorageCapability, | ||
internal_enum=IntStorageCapability, | ||
**kwargs, | ||
) | ||
class StorageCapabilityListField( | ||
DualEnumsListField, | ||
external_enum=StorageCapability, | ||
internal_enum=IntStorageCapability, | ||
): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import enum | ||
from typing import ClassVar | ||
|
||
|
||
def same_enum_names(enum_a: type[enum.Enum], enum_b: type[enum.Enum]) -> bool: | ||
# ensure enums have same names | ||
_names_a = {_item.name for _item in enum_a} | ||
_names_b = {_item.name for _item in enum_b} | ||
return _names_a == _names_b | ||
|
||
|
||
class IntEnumForEnum(enum.IntEnum): | ||
__base_enum: ClassVar[type[enum.Enum]] | ||
|
||
def __init_subclass__(cls, /, base_enum: type[enum.Enum], **kwargs): | ||
super().__init_subclass__(**kwargs) | ||
assert same_enum_names(base_enum, cls) | ||
cls.__base_enum = base_enum | ||
|
||
@classmethod | ||
def to_int(cls, base_enum_member): | ||
return cls[base_enum_member.name] | ||
|
||
@classmethod | ||
def as_django_choices(cls): | ||
return [(int(_item), _item.name) for _item in cls] | ||
|
||
def to_base_enum(self) -> enum.Enum: | ||
return self.__base_enum[self.name] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import enum | ||
from typing import ClassVar | ||
|
||
from rest_framework_json_api import serializers | ||
|
||
from addon_service.common.enums import same_enum_names | ||
|
||
|
||
class DualEnumsListField(serializers.MultipleChoiceField): | ||
"""use one enum in your database and another in your api!""" | ||
|
||
__internal_enum: ClassVar[type[enum.Enum]] | ||
__external_enum: ClassVar[type[enum.Enum]] | ||
|
||
def __init__(self, **kwargs): | ||
super().__init__( | ||
**kwargs, | ||
choices={ # valid serialized values come from the external enum | ||
_external_member.value for _external_member in self.__external_enum | ||
}, | ||
) | ||
|
||
def __init_subclass__( | ||
cls, | ||
/, | ||
internal_enum: type[enum.Enum], | ||
external_enum: type[enum.Enum], | ||
**kwargs, | ||
): | ||
super().__init_subclass__(**kwargs) | ||
assert same_enum_names(internal_enum, external_enum) | ||
cls.__internal_enum = internal_enum | ||
cls.__external_enum = external_enum | ||
|
||
def to_internal_value(self, data) -> list[enum.Enum]: | ||
_names: set = super().to_internal_value(data) | ||
return [self._to_internal_enum_member(_name) for _name in _names] | ||
|
||
def to_representation(self, value): | ||
_member_list = super().to_representation(value) | ||
return {self._to_external_enum_value(_member) for _member in _member_list} | ||
|
||
def _to_internal_enum_member(self, external_value) -> enum.Enum: | ||
_external_member = self.__external_enum(external_value) | ||
return self.__internal_enum[_external_member.name] | ||
|
||
def _to_external_enum_value(self, internal_value: enum.Enum): | ||
_internal_member = self.__internal_enum(internal_value) | ||
_external_member = self.__external_enum[_internal_member.name] | ||
return _external_member.value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters