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

validators: add option for non-ECMA regex validation #103

Open
wants to merge 1 commit 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
52 changes: 30 additions & 22 deletions jsonmodels/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,41 +81,46 @@ class Regex(object):

"""Validator for regular expressions."""

FLAGS = {
ECMA_FLAGS = {
'ignorecase': re.I,
'multiline': re.M,
}

def __init__(self, pattern, **flags):
def __init__(self, pattern, ecma=True, **flags):
"""Init.

Note, that if given pattern is ECMA regex, given flags will be
**completely ignored** and taken from given regex.


:param string pattern: Pattern of regex.
:param boolean ecma: Whether or not use ECMA regex, default True.
:param dict flags: Allowed flags can be found in attribute
`ATTRIBUTES_TO_FLAGS`. Invalid flags will be ignored.
`ECMA_FLAGS`. Invalid flags will be ignored. Will be ignored if not
ECMA regex.

"""
flags = dict(
(key, value) for key, value in flags.items()
if key in self.FLAGS
)

if utilities.is_ecma_regex(pattern):
result = utilities.convert_ecma_regex_to_python(pattern)
self.pattern = result.regex

for key, _ in flags.items():
flags.update(
{key: self.FLAGS[key] in result.flags})
else:
self.pattern = pattern
self.ecma = ecma
self.pattern = pattern
self.flags = []

if ecma:
flags = dict(
(key, value) for key, value in flags.items()
if key in self.ECMA_FLAGS
)

if utilities.is_ecma_regex(pattern):
result = utilities.convert_ecma_regex_to_python(pattern)
self.pattern = result.regex

self.flags = [
self.FLAGS[key] for key, value
in flags.items() if value]
for key, _ in flags.items():
flags.update(
{key: self.ECMA_FLAGS[key] in result.flags})

self.flags = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks compatibility with current code, and contradicts the comment at the head of the function:

Note, that if given pattern is ECMA regex, given flags will be
completely ignored and taken from given regex.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it appears that actually the code comment is incorrect :(

Ignore my comment.

self.ECMA_FLAGS[key] for key, value
in flags.items() if value]

def validate(self, value):
"""Validate value."""
Expand All @@ -137,8 +142,11 @@ def _calculate_flags(self):

def modify_schema(self, field_schema):
"""Modify field schema."""
field_schema['pattern'] = utilities.convert_python_regex_to_ecma(
self.pattern, self.flags)
if self.ecma:
field_schema['pattern'] = utilities.convert_python_regex_to_ecma(
self.pattern, self.flags)
else:
field_schema['pattern'] = self.pattern


class Length(object):
Expand Down
16 changes: 16 additions & 0 deletions tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,22 @@ class Person(models.Base):
person.name = 'Jimmy'


def test_regex_modify_schema():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some missing test cases:

  1. Invalid flags
  2. Flags provided directly in an ECMA262 pattern
  3. Flags passed with **flags

regex = "regex"
schema = {}
validator = validators.Regex(regex)
validator.modify_schema(schema)
assert schema["pattern"] == "/{}/".format(regex)


def test_regex_modify_schema_no_ecma():
regex = "regex"
schema = {}
validator = validators.Regex(regex, ecma=False)
validator.modify_schema(schema)
assert schema["pattern"] == regex


def test_init():
validator = validators.Length(0, 10)
assert 0 == validator.minimum_value
Expand Down