Skip to content

Commit

Permalink
Add empty_ok kwarg to all validators (#42)
Browse files Browse the repository at this point in the history
* Add failing tests

* Move empty_ok kwargs to Validator base class

* Update docs

* Version bump
  • Loading branch information
di authored Sep 20, 2017
1 parent 81892a0 commit fa5faeb
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 32 deletions.
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,17 @@ Vladiate comes with a few common validators built-in:

:``unique_with=[]``:
List of field names to make the primary field unique with.
:``empty_ok=False``:
Specify whether a field which is an empty string should be ignored.

*class* ``RegexValidator``

Validates whether a field matches the given regex using `re.match()`.

:``pattern=r'di^'``:
The regex pattern. Fails for all fields by default.
:``empty_ok=False``:
Specify whether a field which is an empty string should be ignored.

*class* ``RangeValidator``

Expand All @@ -253,6 +257,8 @@ Vladiate comes with a few common validators built-in:
The low value of the range.
:``high``:
The high value of the range.
:``empty_ok=False``:
Specify whether a field which is an empty string should be ignored.

*class* ``EmptyValidator``

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from setuptools import setup, find_packages
from setuptools.command.test import test as TestCommand

__version__ = '0.0.17'
__version__ = '0.0.18'


class PyTest(TestCommand):
Expand Down
23 changes: 13 additions & 10 deletions vladiate/test/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@ def test_set_validator_works(field_set, field):
assert field in validator.valid_set


def test_set_validator_empty_ok():
validator = SetValidator(['foo'], empty_ok=True)
validator.validate('')
assert '' in validator.valid_set


@pytest.mark.parametrize('field_set, field', [
([], 'bar'),
(['foo'], 'bar'),
Expand Down Expand Up @@ -139,10 +133,6 @@ def test_regex_validator_works(pattern, field):
RegexValidator(pattern).validate(field)


def test_regex_validator_allows_empty():
RegexValidator(r'foo.*', empty_ok=True).validate('')


@pytest.mark.parametrize('pattern, field', [
(r'foo.*', 'afoo'),
(r'^$', 'foo'),
Expand Down Expand Up @@ -213,3 +203,16 @@ def test_base_class_raises():

with pytest.raises(NotImplementedError):
validator.validate(stub(), stub())


@pytest.mark.parametrize('validator_class,args', [
(SetValidator, [['foo']]),
(RegexValidator, [r'foo.*']),
(IntValidator, []),
(FloatValidator, []),
(RangeValidator, [0, 42]),
(UniqueValidator, []),
])
def test_all_validators_support_empty_ok(validator_class, args):
validator = validator_class(*args, empty_ok=True)
validator.validate('')
44 changes: 23 additions & 21 deletions vladiate/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
class Validator(object):
''' Generic Validator class '''

def __init__(self):
def __init__(self, empty_ok=False):
self.fail_count = 0
self.empty_ok = empty_ok

@property
def bad(self):
Expand All @@ -22,8 +23,8 @@ def validate(self, field, row):
class CastValidator(Validator):
''' Validates that a field can be cast to a float '''

def __init__(self):
super(CastValidator, self).__init__()
def __init__(self, **kwargs):
super(CastValidator, self).__init__(**kwargs)
self.invalid_set = set([])

def validate(self, field, row={}):
Expand All @@ -42,29 +43,27 @@ def bad(self):
class FloatValidator(CastValidator):
''' Validates that a field can be cast to a float '''

def __init__(self, empty_ok=False):
super(FloatValidator, self).__init__()
self.empty_ok = empty_ok
def __init__(self, **kwargs):
super(FloatValidator, self).__init__(**kwargs)
self.cast = float


class IntValidator(CastValidator):
''' Validates that a field can be cast to an int '''

def __init__(self, empty_ok=False):
super(IntValidator, self).__init__()
self.empty_ok = empty_ok
def __init__(self, **kwargs):
super(IntValidator, self).__init__(**kwargs)
self.cast = int


class SetValidator(Validator):
''' Validates that a field is in the given set '''

def __init__(self, valid_set=[], empty_ok=False):
super(SetValidator, self).__init__()
def __init__(self, valid_set=[], **kwargs):
super(SetValidator, self).__init__(**kwargs)
self.valid_set = set(valid_set)
self.invalid_set = set([])
if empty_ok:
if self.empty_ok:
self.valid_set.add('')

def validate(self, field, row={}):
Expand All @@ -81,8 +80,8 @@ def bad(self):
class UniqueValidator(Validator):
''' Validates that a field is unique within the file '''

def __init__(self, unique_with=[]):
super(UniqueValidator, self).__init__()
def __init__(self, unique_with=[], **kwargs):
super(UniqueValidator, self).__init__(**kwargs)
self.unique_values = set([])
self.duplicates = set([])
self.unique_with = unique_with
Expand Down Expand Up @@ -119,10 +118,9 @@ def bad(self):
class RegexValidator(Validator):
''' Validates that a field matches a given regex '''

def __init__(self, pattern=r'di^', empty_ok=False):
super(RegexValidator, self).__init__()
def __init__(self, pattern=r'di^', **kwargs):
super(RegexValidator, self).__init__(**kwargs)
self.regex = re.compile(pattern)
self.empty_ok = empty_ok
self.failures = set([])

def validate(self, field, row={}):
Expand All @@ -137,13 +135,16 @@ def bad(self):


class RangeValidator(Validator):
def __init__(self, low, high):
def __init__(self, low, high, **kwargs):
super(RangeValidator, self).__init__(**kwargs)
self.fail_count = 0
self.low = low
self.high = high
self.outside = set()

def validate(self, field, row={}):
if field == '' and self.empty_ok:
return
try:
value = float(field)
if not self.low <= value <= self.high:
Expand All @@ -164,8 +165,8 @@ def bad(self):
class EmptyValidator(Validator):
''' Validates that a field is always empty '''

def __init__(self):
super(EmptyValidator, self).__init__()
def __init__(self, **kwargs):
super(EmptyValidator, self).__init__(**kwargs)
self.nonempty = set([])

def validate(self, field, row={}):
Expand All @@ -183,7 +184,8 @@ def bad(self):
class NotEmptyValidator(Validator):
''' Validates that a field is not empty '''

def __init__(self):
def __init__(self, **kwargs):
super(NotEmptyValidator, self).__init__(**kwargs)
self.fail_count = 0
self.failed = False

Expand Down

0 comments on commit fa5faeb

Please sign in to comment.