Skip to content

Commit

Permalink
Merge pull request #44 from girardinsamuel/feat/new-rules
Browse files Browse the repository at this point in the history
Add rules: different, uuid, distinct, required_if, required_with
  • Loading branch information
josephmancuso authored Nov 26, 2020
2 parents e5e56c6 + 258dace commit f4da403
Show file tree
Hide file tree
Showing 3 changed files with 361 additions and 3 deletions.
127 changes: 124 additions & 3 deletions src/masonite/validation/Validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,18 @@ class required(BaseValidation):
def passes(self, attribute, key, dictionary):
"""The passing criteria for this rule.
This should return a True boolean value.
The key must exist in the dictionary and return a True boolean value.
The key can use * notation.
Arguments:
attribute {mixed} -- The value found within the dictionary
key {string} -- The key in the dictionary being searched for.
This key may or may not exist in the dictionary.
dictionary {dict} -- The dictionary being searched
Returns:
bool
"""
return attribute or key in dictionary
return self.find(key, dictionary) and attribute

def message(self, key):
"""A message to show when this rule fails
Expand Down Expand Up @@ -1029,6 +1029,122 @@ def negated_message(self, attribute):
return "The {} is a valid {} postal code.".format(attribute, self.locale)


class different(BaseValidation):
"""The field under validation must be different than an other given field."""
def __init__(self, validations, other_field, messages={}, raises={}):
super().__init__(validations, messages=messages, raises=raises)
self.other_field = other_field

def passes(self, attribute, key, dictionary):
other_value = dictionary.get(self.other_field, None)
return attribute != other_value

def message(self, attribute):
return "The {} value must be different than {} value.".format(attribute, self.other_field)

def negated_message(self, attribute):
return "The {} value be the same as {} value.".format(attribute, self.other_field)


class uuid(BaseValidation):
"""The field under validation must be a valid UUID. The UUID version standard
can be precised (1,3,4,5)."""
def __init__(self, validations, version=4, messages={}, raises={}):
super().__init__(validations, messages=messages, raises=raises)
self.version = version
self.uuid_type = "UUID"
if version:
self.uuid_type = "UUID {0}".format(self.version)

def passes(self, attribute, key, dictionary):
from uuid import UUID
try:
uuid_value = UUID(str(attribute))
return uuid_value.version == int(self.version)
except ValueError:
return False

def message(self, attribute):
return "The {} value must be a valid {}.".format(attribute, self.uuid_type)

def negated_message(self, attribute):
return "The {} value must not be a valid {}.".format(attribute, self.uuid_type)


class required_if(BaseValidation):
"""The field under validation must be present and not empty only
if an other field has a given value."""
def __init__(self, validations, other_field, value, messages={}, raises={}):
super().__init__(validations, messages=messages, raises=raises)
self.other_field = other_field
self.value = value

def passes(self, attribute, key, dictionary):
if dictionary.get(self.other_field, None) == self.value:
return required.passes(self, attribute, key, dictionary)

return True

def message(self, attribute):
return "The {} is required because {}={}.".format(attribute, self.other_field, self.value)

def negated_message(self, attribute):
return "The {} is not required because {}={} or {} is not present.".format(
attribute, self.other_field, self.value, self.other_field
)


class required_with(BaseValidation):
"""The field under validation must be present and not empty only
if any of the other specified fields are present."""

def __init__(self, validations, other_fields, messages={}, raises={}):
super().__init__(validations, messages=messages, raises=raises)
if not isinstance(other_fields, list):
if "," in other_fields:
self.other_fields = other_fields.split(",")
else:
self.other_fields = [other_fields]
else:
self.other_fields = other_fields

def passes(self, attribute, key, dictionary):
for field in self.other_fields:
if field in dictionary:
return required.passes(self, attribute, key, dictionary)
else:
return True

def message(self, attribute):
fields = ",".join(self.other_fields)
return "The {} is required because {} is present.".format(
attribute,
"one in {}".format(fields) if len(self.other_fields) > 1 else self.other_fields[0],
)

def negated_message(self, attribute):
return "The {} is not required because {} {} is not present.".format(
attribute,
"none of" if len(self.other_fields) > 1 else "",
",".join(self.other_fields)
)


class distinct(BaseValidation):
"""When working with list, the field under validation must not have any
duplicate values."""

def passes(self, attribute, key, dictionary):
# check if list contains duplicates
return len(set(attribute)) == len(attribute)

def message(self, attribute):
return "The {} field has duplicate values.".format(attribute)

def negated_message(self, attribute):
return "The {} field has only different values.".format(attribute)


def flatten(iterable):

flat_list = []
Expand Down Expand Up @@ -1139,6 +1255,8 @@ def __init__(self):
contains,
date,
does_not,
different,
distinct,
equals,
email,
exists,
Expand All @@ -1163,10 +1281,13 @@ def __init__(self):
postal_code,
regex,
required,
required_if,
required_with,
string,
strong,
timezone,
truthy,
uuid,
video,
when,
)
Expand Down
5 changes: 5 additions & 0 deletions src/masonite/validation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
confirmed,
contains,
date,
different,
distinct,
does_not,
email,
equals,
Expand All @@ -34,10 +36,13 @@
postal_code,
regex,
required,
required_if,
required_with,
string,
strong,
timezone,
truthy,
uuid,
video,
when,
)
Loading

0 comments on commit f4da403

Please sign in to comment.