Skip to content

Commit

Permalink
Add support for optional enums
Browse files Browse the repository at this point in the history
  • Loading branch information
Dobiasd committed Aug 12, 2022
1 parent 4fcaaca commit 4b6ad48
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
10 changes: 10 additions & 0 deletions undictify/_unpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ def _get_value(func: WrappedOrFunc[TypeT],
if value == entry.value:
return entry
raise TypeError(f'Unable to instantiate {func} from {value}.')
if _is_optional_enum_type(func):
for entry in _get_optional_type(func): # type: ignore
if value == entry.value:
return entry
raise TypeError(f'Unable to instantiate {func} from {value}.')
if optional_converters and param_name in optional_converters:
result = optional_converters[param_name](value)
if not _isinstanceofone(result, allowed_types):
Expand Down Expand Up @@ -498,6 +503,11 @@ def _is_enum_type(the_type: Callable[..., TypeT]) -> bool:
return False


def _is_optional_enum_type(the_type: Callable[..., TypeT]) -> bool:
"""Return True if the type is an Optional[Enum]."""
return _is_optional_type(the_type) and _is_enum_type(_get_optional_type(the_type))


def _is_union_of_builtins_type(the_type: Callable[..., TypeT]) -> bool:
"""Return True if the type is an Union only made of
None, str, int, float and bool."""
Expand Down
36 changes: 36 additions & 0 deletions undictify/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,24 @@ class WithAutoEnum(NamedTuple):
auto_enum: SomeAutoEnum


@type_checked_constructor()
class WithOptionalIntEnum(NamedTuple):
"""Some dummy class with int enum."""
int_enum: Optional[SomeIntEnum]


@type_checked_constructor()
class WithOptionalStrEnum(NamedTuple):
"""Some dummy class with str enum."""
str_enum: Optional[SomeStrEnum]


@type_checked_constructor()
class WithOptionalAutoEnum(NamedTuple):
"""Some dummy class with auto enum."""
auto_enum: Optional[SomeAutoEnum]


class TestWithEnums(unittest.TestCase):
"""Enums should work too"""

Expand Down Expand Up @@ -1453,6 +1471,24 @@ def test_auto_enum(self) -> None:
obj = WithAutoEnum(**json.loads(object_repr))
self.assertEqual(SomeAutoEnum.FOO, obj.auto_enum)

def test_optional_int_enum(self) -> None:
"""Valid JSON string."""
object_repr = '''{"int_enum": 2}'''
obj = WithOptionalIntEnum(**json.loads(object_repr))
self.assertEqual(SomeIntEnum.BAR, obj.int_enum)

def test_optional_str_enum(self) -> None:
"""Valid JSON string."""
object_repr = '''{"str_enum": "NOTEXACTLYBAR"}'''
obj = WithOptionalStrEnum(**json.loads(object_repr))
self.assertEqual(SomeStrEnum.BAR, obj.str_enum)

def test_optional_auto_enum(self) -> None:
"""Valid JSON string."""
object_repr = '''{"auto_enum": ''' + str(SomeAutoEnum.FOO.value) + '''}'''
obj = WithOptionalAutoEnum(**json.loads(object_repr))
self.assertEqual(SomeAutoEnum.FOO, obj.auto_enum)


@type_checked_constructor(convert=False, skip=False) # pylint: disable=too-few-public-methods
class WithOneMember(NamedTuple):
Expand Down

0 comments on commit 4b6ad48

Please sign in to comment.