Skip to content

Commit

Permalink
fix: allow unsortable containers in In and NotIn validators (fixes #451
Browse files Browse the repository at this point in the history
…) (#506)

credits to: @spacegaier and @beastd
  • Loading branch information
antoni-szych-rtbhouse authored Feb 1, 2024
1 parent 09d0f06 commit 503dd34
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 7 deletions.
37 changes: 36 additions & 1 deletion voluptuous/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,54 @@ def test_in():
assert isinstance(ctx.value.errors[0], InInvalid)


def test_in_unsortable_container():
"""Verify that In works with unsortable container."""
schema = Schema({"type": In((int, str, float))})
schema({"type": float})
with pytest.raises(
MultipleInvalid,
match=(
r"value must be one of \[<class 'float'>, <class 'int'>, <class 'str'>\] for dictionary value "
r"@ data\['type'\]"
),
) as ctx:
schema({"type": 42})
assert len(ctx.value.errors) == 1
assert isinstance(ctx.value.errors[0], InInvalid)


def test_not_in():
"""Verify that NotIn works."""
schema = Schema({"color": NotIn(frozenset(["red", "blue", "yellow"]))})
schema({"color": "orange"})
with pytest.raises(
MultipleInvalid,
match=r"value must not be one of \['blue', 'red', 'yellow'\] for dictionary value @ data\['color'\]",
match=(
r"value must not be one of \['blue', 'red', 'yellow'\] for dictionary "
r"value @ data\['color'\]"
),
) as ctx:
schema({"color": "blue"})
assert len(ctx.value.errors) == 1
assert isinstance(ctx.value.errors[0], NotInInvalid)


def test_not_in_unsortable_container():
"""Verify that NotIn works with unsortable container."""
schema = Schema({"type": NotIn((int, str, float))})
schema({"type": 42})
with pytest.raises(
MultipleInvalid,
match=(
r"value must not be one of \[<class 'float'>, <class 'int'>, "
r"<class 'str'>\] for dictionary value @ data\['type'\]"
),
) as ctx:
schema({"type": str})
assert len(ctx.value.errors) == 1
assert isinstance(ctx.value.errors[0], NotInInvalid)


def test_contains():
"""Verify contains validation method."""
schema = Schema({'color': Contains('red')})
Expand Down
24 changes: 18 additions & 6 deletions voluptuous/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,9 +821,15 @@ def __call__(self, v):
except TypeError:
check = True
if check:
raise InInvalid(
self.msg or 'value must be one of {}'.format(sorted(self.container))
)
try:
raise InInvalid(
self.msg or f'value must be one of {sorted(self.container)}'
)
except TypeError:
raise InInvalid(
self.msg
or f'value must be one of {sorted(self.container, key=str)}'
)
return v

def __repr__(self):
Expand All @@ -845,9 +851,15 @@ def __call__(self, v):
except TypeError:
check = True
if check:
raise NotInInvalid(
self.msg or 'value must not be one of {}'.format(sorted(self.container))
)
try:
raise NotInInvalid(
self.msg or f'value must not be one of {sorted(self.container)}'
)
except TypeError:
raise NotInInvalid(
self.msg
or f'value must not be one of {sorted(self.container, key=str)}'
)
return v

def __repr__(self):
Expand Down

0 comments on commit 503dd34

Please sign in to comment.