Skip to content
This repository has been archived by the owner on Apr 10, 2023. It is now read-only.

Commit

Permalink
Add FrozenSet field
Browse files Browse the repository at this point in the history
  • Loading branch information
rossmacarthur committed Dec 2, 2019
1 parent ec44671 commit 1d2f0cd
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions RELEASES.rst
Expand Up @@ -6,6 +6,7 @@ Releases

*Unreleased*

- Add ``FrozenSet`` field.
- Add ``Deque`` field.
- Add ``default`` keyword argument to ``Field``. (`#111`_)
- Fix bug in ``Uuid.normalize()``.
Expand Down
22 changes: 22 additions & 0 deletions src/serde/fields.py
Expand Up @@ -913,6 +913,28 @@ def __init__(self, key=None, value=None, **kwargs):
self.value = _resolve_to_field_instance(value)


class FrozenSet(_Container):
"""
This field represents the built-in `frozenset` type.
Each element is serialized, deserialized, normalized and validated with the
specified element type. The element type can be specified using `Field`
classes, `Field` instances, `~serde.Model` classes, or built-in types that
have a corresponding field type in this library.
Args:
element: the `Field` class or instance for elements in the `Set`.
**kwargs: keyword arguments for the `Field` constructor.
"""

def __init__(self, element=None, **kwargs):
"""
Create a new `FrozenSet`.
"""
super(FrozenSet, self).__init__(frozenset, **kwargs)
self.element = _resolve_to_field_instance(element)


class List(_Container):
"""
This field represents the built-in `list` type.
Expand Down
74 changes: 74 additions & 0 deletions tests/test_fields.py
Expand Up @@ -28,6 +28,7 @@
Dict,
Field,
Float,
FrozenSet,
Instance,
Int,
List,
Expand Down Expand Up @@ -950,6 +951,79 @@ def test___init___options(self):
assert field.validators == [None]


class TestFrozenSet:
def test___init___basic(self):
# Construct a basic FrozenSet and check values are set correctly.
field = FrozenSet()
assert field.element == Field()
assert field.validators == []

def test___init___options(self):
# Construct a FrozenSet with extra options and make sure values are passed to
# Field.
field = FrozenSet(element=Int, validators=[None])
assert field.element == Int()
assert field.validators == [None]

def test_serialize(self):
# A FrozenSet should serialize values based on the element Field.
field = FrozenSet(element=Reversed)
assert field.serialize(frozenset({'test', 'hello'})) == frozenset(
{'tset', 'olleh'}
)

def test_serialize_extra(self):
# A FrozenSet should serialize values based on the element Field.
field = FrozenSet(element=Field(serializers=[lambda x: x[::-1]]))
assert field.serialize(frozenset({'test', 'hello'})) == frozenset(
{'tset', 'olleh'}
)

def test_deserialize(self):
# A FrozenSet should deserialize values based on the element Field.
field = FrozenSet(element=Reversed)
assert field.deserialize(frozenset({'tset', 'olleh'})) == frozenset(
{'test', 'hello'}
)

def test_deserialize_extra(self):
# A FrozenSet should deserialize values based on the element Field.
field = FrozenSet(element=Field(deserializers=[lambda x: x[::-1]]))
assert field.deserialize(frozenset({'tset', 'olleh'})) == frozenset(
{'test', 'hello'}
)

def test_normalize(self):
# A FrozenSet should normalize values based on the element Field.
field = FrozenSet(element=Field)
assert field.normalize(frozenset({'test', 'hello'})) == frozenset(
{'test', 'hello'}
)

def test_normalize_extra(self):
# A FrozenSet should normalize values based on the element Field.
field = FrozenSet(element=Field(normalizers=[lambda x: x[::-1]]))
assert field.normalize(frozenset({'tset', 'olleh'})) == frozenset(
{'test', 'hello'}
)

def test_validate(self):
# A FrozenSet should validate values based on the element Field.
field = FrozenSet(element=Int)
field.validate(frozenset({0, 1, 2, 3, 4}))

with raises(ValidationError):
field.validate(frozenset({'1', '2', 'a', 'string'}))

def test_validate_extra(self):
# A FrozenSet should validate values based on the element Field.
field = FrozenSet(element=Field(validators=[validators.Between(10, 10)]))
field.validate(frozenset({10, 10, 10}))

with raises(ValidationError):
field.validate(frozenset({10, 11, 12, 13}))


class TestList:
def test___init___basic(self):
# Construct a basic List and check values are set correctly.
Expand Down

0 comments on commit 1d2f0cd

Please sign in to comment.