Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added PythonRegex validator that is not ECMA262 compliant #108

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion jsonmodels/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def modify_schema(self, field_schema):
field_schema['exclusiveMaximum'] = True


class Regex(object):
class ECMA262Regex(object):

"""Validator for regular expressions."""

Expand Down Expand Up @@ -133,6 +133,45 @@ def modify_schema(self, field_schema):
self.pattern, self.flags)


class Regex(ECMA262Regex):
"""
Deprecated. Use the more explicit `ECMA262Regex`
"""
pass


class PythonRegex(object):

def __init__(self, pattern, flags=0):
"""
Initialize a new `PythonRegex` validator.

:param pattern: The regex pattern to validate against.
:param flags: Bitwise OR of valid `re` flags.
Notice that these flags WILL NOT be written to a schema generated
by this validator.
"""
self.regex = re.compile(pattern, flags=flags)

def validate(self, value):
try:
match = self.regex.search(value)
except TypeError as e:
raise ValidationError(*e.args)
if match is None:
raise ValidationError(
'Value "{value}" did not match pattern "{pattern}".'.format(
value=value, pattern=self.regex.pattern
))

def modify_schema(self, schema):
"""
Adds the "pattern" keyword to the given schema.
Note that all `re` flags are discarded and are not added to the schema.
"""
schema["pattern"] = self.regex.pattern


class Length(object):

"""Validator for length."""
Expand Down
17 changes: 17 additions & 0 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import pytest

from jsonmodels import models, fields, validators, errors, builders
Expand Down Expand Up @@ -270,6 +271,22 @@ class Person(models.Base):
assert compare_schemas(pattern, schema)


def test_python_regex_validator():
pattern = "some pattern"
schema = {}
validator = validators.PythonRegex(pattern)
validator.modify_schema(schema)
assert schema["pattern"] == pattern


def test_python_regex_validator_ignore_flags():
pattern = "some pattern"
schema = {}
validator = validators.PythonRegex(pattern, re.DOTALL | re.VERBOSE)
validator.modify_schema(schema)
assert schema["pattern"] == pattern


def test_regex_validator_when_ecma_regex_given():

class Person(models.Base):
Expand Down
32 changes: 19 additions & 13 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,22 @@ def test_max_exclusive_validation():

def test_regex_validation():

validator = validators.Regex('some')
assert 'some' == validator.pattern
v1 = validators.Regex('some')
v2 = validators.PythonRegex('some')
assert 'some' == v1.pattern == v2.regex.pattern

validator.validate('some string')
validator.validate('get some chips')
with pytest.raises(errors.ValidationError):
validator.validate('asdf')
with pytest.raises(errors.ValidationError):
validator.validate('trololo')
for s in ('some string', 'get some chips'):
v1.validate(s)
v2.validate(s)

for v in (v1, v2):
with pytest.raises(errors.ValidationError):
v.validate('asdf')
with pytest.raises(errors.ValidationError):
v.validate('trololo')


def test_regex_validation_flags():
def test_ecma_regex_validation_flags():
# Invalid flags ignored
validator = validators.Regex("foo", bla=True, ble=False, ignorecase=True)
assert validator.flags == [validators.Regex.FLAGS["ignorecase"]]
Expand All @@ -167,11 +171,13 @@ def test_regex_validation_flags():

def test_regex_validation_for_wrong_type():

validator = validators.Regex('some')
assert 'some' == validator.pattern
v1 = validators.Regex('some')
v2 = validators.PythonRegex('some')
assert 'some' == v1.pattern == v2.regex.pattern

with pytest.raises(errors.ValidationError):
validator.validate(1)
for v in (v1, v2):
with pytest.raises(errors.ValidationError):
v.validate(1)


def test_validation_2():
Expand Down