Skip to content

Commit

Permalink
Support for Enum
Browse files Browse the repository at this point in the history
  • Loading branch information
sabariramc committed Feb 7, 2021
1 parent 5ab82f2 commit fcf5304
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 25 deletions.
62 changes: 46 additions & 16 deletions fieldtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ def inner_fu():
return inner_fu


from enum import Enum


class Gender(Enum):
MALE = "male"
FEMALE = "female"
TRANSGENDER = "transgender"


function_arg_definition = {
"pageNo": {"data_type": int, "min_val": 0, "max_val": 10, 'alias': 'page_no', "description": "Test description",
"default": 1}
Expand All @@ -51,6 +60,7 @@ def inner_fu():
, "name": {"data_type": dict, "nested": {
"first_name": {"data_type": str}, "last_name": {"data_type": str}
}}
, "gender": {"data_type": str, "value_list": Gender}
, "location": {"data_type": list
, "nested": {
"address_line_1": {"data_type": str, "required": True}
Expand Down Expand Up @@ -112,15 +122,18 @@ def test_positive_1(self):
name = {
"first_name": "Sabari"
}
gender = "male"
response = not_auto_cast_class_instance.test(
{"pageNo": 10, "start_date": start_date.strftime('%Y-%m-%d')
, "reg_time": reg_time.strftime('%Y-%m-%d %H:%M:%S'),
'request_id': request_uuid,
"id_list": [1, 1, 2, 0],
"location": [{**deepcopy(location_1), 'fad': 'fad'}, deepcopy(location_2)]
{
"pageNo": 10, "start_date": start_date.strftime('%Y-%m-%d')
, "reg_time": reg_time.strftime('%Y-%m-%d %H:%M:%S')
, 'request_id': request_uuid
, "id_list": [1, 1, 2, 0]
, "location": [{**deepcopy(location_1), 'fad': 'fad'}, deepcopy(location_2)]
, "name": deepcopy(name)
, "location_check": True
}
, "gender": gender
}

)
location_2["latitude"] = Decimal(latitude)
Expand All @@ -133,6 +146,7 @@ def test_positive_1(self):
self.assertEqual(response.get('location')[1], location_2)
self.assertEqual(response.get('location')[1], location_2)
self.assertEqual(response.get('name'), name)
self.assertEqual(response.get('gender'), Gender(gender))
self.assertEqual(response.get('location_check'), True)

def test_positive_2(self):
Expand Down Expand Up @@ -439,15 +453,17 @@ def test_positive_1(self):
name = {
"first_name": "Sabari"
}
response = auto_cast_class_instance.test(
{"pageNo": 10, "start_date": start_date.strftime('%Y-%m-%d')
, "reg_time": reg_time.strftime('%Y-%m-%d %H:%M:%S'),
'request_id': request_uuid,
"id_list": [1, 1, 2, 0],
"location": [{**deepcopy(location_1), 'fad': 'fad'}, deepcopy(location_2)]
, "name": deepcopy(name)
, "location_check": "true"
}
gender = "female"
response = auto_cast_class_instance.test({
"pageNo": 10, "start_date": start_date.strftime('%Y-%m-%d')
, "reg_time": reg_time.strftime('%Y-%m-%d %H:%M:%S')
, 'request_id': request_uuid
, "id_list": [1, 1, 2, 0]
, "location": [{**deepcopy(location_1), 'fad': 'fad'}, deepcopy(location_2)]
, "name": deepcopy(name)
, "location_check": True
, "gender": gender
}

)
location_2["latitude"] = Decimal(latitude)
Expand All @@ -460,7 +476,7 @@ def test_positive_1(self):
self.assertEqual(response.get('location')[1], location_2)
self.assertEqual(response.get('location')[1], location_2)
self.assertEqual(response.get('name'), name)
self.assertEqual(response.get('location_check'), True)
self.assertEqual(response.get('gender'), Gender(gender))

def test_positive_2(self):
start_date = date.today()
Expand Down Expand Up @@ -760,6 +776,20 @@ def test_cast_error(self):
self.assertEqual("name", e.exception.field_name)
self.assertEqual("name should be of type <class 'dict'>", e.exception.message)

def test_enum_error(self):
with self.assertRaises(FieldValueError) as e:
auto_cast_class_instance.test({
"request_id": str(uuid4())
, "location": [{"address_line_1": "fad", "pincode": 6544554, "contact_person": {
"first_name": "sabari"
, "phone_number": "8884233317"
}}]
, "gender": "fasdf"
})
self.assertEqual(ErrorCode.FIELD_VALUE_NOT_IN_ALLOWED_LIST, e.exception.error_code)
self.assertEqual("gender", e.exception.field_name)
self.assertEqual("gender should be one of these - ['male', 'female', 'transgender']", e.exception.message)


if __name__ == '__main__':
unittest.main()
28 changes: 20 additions & 8 deletions funcargpreprocessor/funcargpreprocesser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Author : sabariram
Date : 08-Jun-2020
"""

from enum import Enum
from functools import wraps
import re
from copy import deepcopy
Expand Down Expand Up @@ -85,13 +85,13 @@ def parse_value(self, key, value, data_type, nested, **value_constraints):
field_name = f'{key}[{i}]'
try:
item = self.type_cast(item, nested)
temp.append(item)
except Exception:
raise FieldTypeError(field_name, nested)
self.check_constraint(item, field_name, **value_constraints)

temp.append(self.check_constraint(item, field_name, **value_constraints))
value = temp
else:
self.check_constraint(value, key, **value_constraints)
value = self.check_constraint(value, key, **value_constraints)
return value

def type_cast(self, value, data_type):
Expand Down Expand Up @@ -128,7 +128,7 @@ def check_constraint(cls, value, key, min_val=None, max_val=None, value_list=Non
:param key: Key name for passing back in error if any constraint fails
:param min_val: Min range constraint
:param max_val: Max range constraint
:param value_list: Pick list constraint
:param value_list: Pick list constraint or a enum class
:param regex: Regular expression constraint
:param regex_error_message: Alternate error message for regex constraint fails
:param min_len: Minimum length of the field
Expand All @@ -145,9 +145,20 @@ def check_constraint(cls, value, key, min_val=None, max_val=None, value_list=Non
raise FieldValueError(ErrorCode.FIELD_MAX_RANGE_VIOLATED, key,
f"{key} should be lesser than or equal to {max_val}",
{"maxValue": max_val})
if value_list is not None and value not in value_list:
raise FieldValueError(ErrorCode.FIELD_VALUE_NOT_IN_ALLOWED_LIST, key,
f"{key} should be one of these - {value_list}", {"allowedValue": value_list})
if value_list is not None:
if isinstance(value_list, list):
if value not in value_list:
raise FieldValueError(ErrorCode.FIELD_VALUE_NOT_IN_ALLOWED_LIST, key,
f"{key} should be one of these - {value_list}", {"allowedValue": value_list})
elif issubclass(value_list, Enum):
try:
value = value_list(value)
except Exception:
value_list = [x.value for x in value_list]
raise FieldValueError(ErrorCode.FIELD_VALUE_NOT_IN_ALLOWED_LIST, key,
f"{key} should be one of these - {value_list}",
{"allowedValue": value_list})

if hasattr(value, '__len__'):
try:
length = len(value)
Expand All @@ -163,6 +174,7 @@ def check_constraint(cls, value, key, min_val=None, max_val=None, value_list=Non
if regex is not None and re.search(regex, value) is None:
message = regex_error_message if regex_error_message else f"{key} should be of format - {regex}"
raise FieldValueError(ErrorCode.FIELD_REGEX_VALIDATION_FAILED, key, message, {"regex": regex})
return value

@staticmethod
def validate_type_definition(type_definition):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
long_description = fh.read()

setup(name='funcargpreprocessor',
version='0.10.1',
version='0.10.2',
python_requires='>=3.6',
description='Parser for function arguments',
url='https://github.com/sabariramc/funcargpreprocessor',
Expand Down

0 comments on commit fcf5304

Please sign in to comment.