Skip to content

Commit ddf4ab4

Browse files
Merge pull request #71 from gridsmartercities/numerical_validators
Adding numerical validators
2 parents 0f680bf + 7b293ae commit ddf4ab4

File tree

3 files changed

+195
-1
lines changed

3 files changed

+195
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ Currently, the package offers 3 validators:
4545
* [__Mandatory__](https://github.com/gridsmartercities/aws-lambda-decorators/blob/master/aws_lambda_decorators/validators.py#L5-L16): Checks if a parameter has a value.
4646
* [__RegexValidator__](https://github.com/gridsmartercities/aws-lambda-decorators/blob/master/aws_lambda_decorators/validators.py#L19-L38): Checks a parameter against a regular expression.
4747
* [__SchemaValidator__](https://github.com/gridsmartercities/aws-lambda-decorators/blob/master/aws_lambda_decorators/validators.py#L41-L63): Checks if an object adheres to the schema. Uses [schema](https://github.com/keleshev/schema) library.
48+
* [__Minimum__](https://github.com/gridsmartercities/aws-lambda-decorators/blob/master/aws_lambda_decorators/validators.py#L66-L91): Checks if an optional numerical value is greater than a minimum value.
49+
* [__Maximum__](https://github.com/gridsmartercities/aws-lambda-decorators/blob/master/aws_lambda_decorators/validators.py#L94-L119): Checks if an optional numerical value is less than a maximum value.
4850

4951
### [Decoders](https://github.com/gridsmartercities/aws-lambda-decorators/blob/master/aws_lambda_decorators/decoders.py)
5052

aws_lambda_decorators/validators.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,59 @@ def validate(self, value=None):
6161
return self._schema.validate(value) == value
6262
except SchemaError:
6363
return False
64+
65+
66+
class Minimum: # noqa: pylint - too-few-public-methods
67+
"""Validation rule to check if a value is greater than a minimum value."""
68+
69+
def __init__(self, minimum: (float, int)):
70+
"""
71+
Set the minimum value.
72+
73+
Args:
74+
minimum (float, int): The minimum value.
75+
"""
76+
self._minimum = minimum
77+
78+
def validate(self, value=None):
79+
"""
80+
Check if the value is greater than the minimum.
81+
82+
Args:
83+
value (float, int): Value to be validated.
84+
"""
85+
if value is None:
86+
return True
87+
88+
if isinstance(value, (float, int)):
89+
return self._minimum <= value
90+
91+
return False
92+
93+
94+
class Maximum: # noqa: pylint - too-few-public-methods
95+
"""Validation rule to check if a value is less than a maximum value."""
96+
97+
def __init__(self, maximum: (float, int)):
98+
"""
99+
Set the maximum value.
100+
101+
Args:
102+
maximum (float, int): The maximum value.
103+
"""
104+
self._maximum = maximum
105+
106+
def validate(self, value=None):
107+
"""
108+
Check if the value is less than the maximum.
109+
110+
Args:
111+
value (float, int): Value to be validated.
112+
"""
113+
if value is None:
114+
return True
115+
116+
if isinstance(value, (float, int)):
117+
return self._maximum >= value
118+
119+
return False

tests/test_decorators.py

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from aws_lambda_decorators.classes import ExceptionHandler, Parameter, SSMParameter, ValidatedParameter
88
from aws_lambda_decorators.decorators import extract, extract_from_event, extract_from_context, handle_exceptions, \
99
log, response_body_as_json, extract_from_ssm, validate, handle_all_exceptions, cors
10-
from aws_lambda_decorators.validators import Mandatory, RegexValidator, SchemaValidator
10+
from aws_lambda_decorators.validators import Mandatory, RegexValidator, SchemaValidator, Minimum, Maximum
1111

1212
TEST_JWT = "eyJraWQiOiJEQlwvK0lGMVptekNWOGNmRE1XVUxBRlBwQnVObW5CU2NcL2RoZ3pnTVhcL2NzPSIsImFsZyI6IlJTMjU2In0." \
1313
"eyJzdWIiOiJhYWRkMWUwZS01ODA3LTQ3NjMtYjFlOC01ODIzYmY2MzFiYjYiLCJhdWQiOiIycjdtMW1mdWFiODg3ZmZvdG9iNWFjcX" \
@@ -712,3 +712,139 @@ def handler(event, context, a=None): # noqa
712712
}
713713
}
714714
self.assertEqual(expected, response)
715+
716+
def test_extract_parameter_with_minimum(self):
717+
event = {
718+
"value": 20
719+
}
720+
721+
@extract([Parameter("/value", "event", validators=[Minimum(10.0)])])
722+
def handler(event, value=None): # noqa: pylint - unused-argument
723+
return {}
724+
725+
response = handler(event)
726+
self.assertEqual({}, response)
727+
728+
def test_error_extracting_parameter_with_minimum(self):
729+
event = {
730+
"value": 5
731+
}
732+
733+
@extract([Parameter("/value", "event", validators=[Minimum(10.0)])])
734+
def handler(event, value=None): # noqa: pylint - unused-argument
735+
return {}
736+
737+
response = handler(event)
738+
self.assertEqual(response["statusCode"], 400)
739+
self.assertEqual('{"message": "Error extracting parameters"}', response["body"])
740+
741+
def test_error_extracting_non_numeric_parameter_with_minimum(self):
742+
event = {
743+
"value": "20"
744+
}
745+
746+
@extract([Parameter("/value", "event", validators=[Minimum(10.0)])])
747+
def handler(event, value=None): # noqa: pylint - unused-argument
748+
return {}
749+
750+
response = handler(event)
751+
self.assertEqual(response["statusCode"], 400)
752+
self.assertEqual('{"message": "Error extracting parameters"}', response["body"])
753+
754+
def test_extract_optional_null_parameter_with_minimum(self):
755+
event = {
756+
}
757+
758+
@extract([Parameter("/value", "event", validators=[Minimum(10.0)])])
759+
def handler(event, value=None): # noqa: pylint - unused-argument
760+
return {}
761+
762+
response = handler(event)
763+
self.assertEqual({}, response)
764+
765+
def test_extract_mandatory_parameter_with_minimum(self):
766+
event = {
767+
"value": 20
768+
}
769+
770+
@extract([Parameter("/value", "event", validators=[Minimum(10.0), Mandatory()])])
771+
def handler(event, value=None): # noqa: pylint - unused-argument
772+
return {}
773+
774+
response = handler(event)
775+
self.assertEqual({}, response)
776+
777+
def test_extract_parameter_with_maximum(self):
778+
event = {
779+
"value": 20
780+
}
781+
782+
@extract([Parameter("/value", "event", validators=[Maximum(100.0)])])
783+
def handler(event, value=None): # noqa: pylint - unused-argument
784+
return {}
785+
786+
response = handler(event)
787+
self.assertEqual({}, response)
788+
789+
def test_error_extracting_parameter_with_maximum(self):
790+
event = {
791+
"value": 105
792+
}
793+
794+
@extract([Parameter("/value", "event", validators=[Maximum(100.0)])])
795+
def handler(event, value=None): # noqa: pylint - unused-argument
796+
return {}
797+
798+
response = handler(event)
799+
self.assertEqual(response["statusCode"], 400)
800+
self.assertEqual(
801+
'{"message": "Error extracting parameters"}', response["body"])
802+
803+
def test_error_extracting_non_numeric_parameter_with_maximum(self):
804+
event = {
805+
"value": "20"
806+
}
807+
808+
@extract([Parameter("/value", "event", validators=[Maximum(100.0)])])
809+
def handler(event, value=None): # noqa: pylint - unused-argument
810+
return {}
811+
812+
response = handler(event)
813+
self.assertEqual(response["statusCode"], 400)
814+
self.assertEqual(
815+
'{"message": "Error extracting parameters"}', response["body"])
816+
817+
def test_extract_optional_null_parameter_with_maximum(self):
818+
event = {
819+
}
820+
821+
@extract([Parameter("/value", "event", validators=[Maximum(10.0)])])
822+
def handler(event, value=None): # noqa: pylint - unused-argument
823+
return {}
824+
825+
response = handler(event)
826+
self.assertEqual({}, response)
827+
828+
def test_extract_mandatory_parameter_with_maximum(self):
829+
event = {
830+
"value": 20
831+
}
832+
833+
@extract([Parameter("/value", "event", validators=[Maximum(100.0), Mandatory()])])
834+
def handler(event, value=None): # noqa: pylint - unused-argument
835+
return {}
836+
837+
response = handler(event)
838+
self.assertEqual({}, response)
839+
840+
def test_extract_mandatory_parameter_with_range(self):
841+
event = {
842+
"value": 20
843+
}
844+
845+
@extract([Parameter("/value", "event", validators=[Minimum(10.0), Maximum(100.0), Mandatory()])])
846+
def handler(event, value=None): # noqa: pylint - unused-argument
847+
return {}
848+
849+
response = handler(event)
850+
self.assertEqual({}, response)

0 commit comments

Comments
 (0)