Skip to content

Commit

Permalink
Fix set validator (#52)
Browse files Browse the repository at this point in the history
* Fix issue with SetValidator and large valid_set (#50)

A new function stringify_set only stringifies n elements of a given set.

* Use itertools.islice for better python2 performance

* Add SetValidator test for coverage

* Fix stringify_set: Return {...} instead of [...]

* Add test cases for stringify_set

Fix stringify_set: Sort the elements before displaying for small sets

* Remove previously introduced test case for set validator

* Add parameter checks for stringify_set

* Rename stringify_set to _stringify_set

* Revert d355def
  • Loading branch information
syxolk authored and di committed Jan 2, 2018
1 parent 53cd400 commit 8c75eda
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
13 changes: 12 additions & 1 deletion vladiate/test/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ..validators import (
CastValidator, EmptyValidator, FloatValidator, Ignore, IntValidator,
NotEmptyValidator, RangeValidator, RegexValidator, SetValidator,
UniqueValidator, Validator
UniqueValidator, Validator, _stringify_set
)
from ..exceptions import BadValidatorException, ValidationException

Expand Down Expand Up @@ -216,3 +216,14 @@ def test_base_class_raises():
def test_all_validators_support_empty_ok(validator_class, args):
validator = validator_class(*args, empty_ok=True)
validator.validate('')


@pytest.mark.parametrize('a_set, max_len, stringified', [
({'A', 'B', 'C'}, 4, "{'A', 'B', 'C'}"),
({'A', 'B', 'C'}, 3, "{'A', 'B', 'C'}"),
({'A', 'B', 'C'}, 2, "{'A', 'B'} (1 more suppressed)"),
({'A', 'B', 'C'}, 0, "{} (3 more suppressed)"),
({}, 5, "{}"),
])
def test_stringify_set(a_set, max_len, stringified):
assert _stringify_set(a_set, max_len) == stringified
22 changes: 21 additions & 1 deletion vladiate/validators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
from itertools import islice

from vladiate.exceptions import ValidationException, BadValidatorException

Expand Down Expand Up @@ -70,7 +71,8 @@ def validate(self, field, row={}):
if field not in self.valid_set:
self.invalid_set.add(field)
raise ValidationException(
"'{}' is not in {}".format(field, self.valid_set))
"'{}' is not in {}".format(field,
_stringify_set(self.valid_set, 100)))

@property
def bad(self):
Expand Down Expand Up @@ -208,3 +210,21 @@ def validate(self, field, row={}):
@property
def bad(self):
pass


def _stringify_set(a_set, max_len, max_sort_size=8192):
''' Stringify `max_len` elements of `a_set` and count the remainings
Small sets (len(a_set) <= max_sort_size) are displayed sorted.
Large sets won't be sorted for performance reasons.
This may result in an arbitrary ordering in the returned string.
'''
# Don't convert `a_set` to a list for performance reasons
text = "{{{}}}".format(", ".join(
"'{}'".format(value) for value in islice(
sorted(a_set) if len(a_set) <= max_sort_size else a_set,
max_len)
))
if len(a_set) > max_len:
text += " ({} more suppressed)".format(len(a_set) - max_len)
return text

0 comments on commit 8c75eda

Please sign in to comment.