Skip to content

Commit c77e9f4

Browse files
authored
Merge pull request #20 from LeanderCS/16
16 | Add functionality to filter and validate in a custom order
2 parents 3aa255e + 9db1a22 commit c77e9f4

File tree

4 files changed

+67
-7
lines changed

4 files changed

+67
-7
lines changed

CHAGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
All notable changes to this project will be documented in this file.
44

55

6+
# [0.0.8] - 2025-01-16
7+
8+
## Added
9+
10+
- New functionality to define steps for a field to have more control over the
11+
order of the validation and filtering process.
12+
13+
614
# [0.0.7.1] - 2025-01-16
715

816
## Changed

flask_inputfilter/InputFilter.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ def add(
4444
or field None, although it is required .
4545
:param filters: The filters to apply to the field value.
4646
:param validators: The validators to apply to the field value.
47-
:param steps:
47+
:param steps: Allows to apply multiple filters and validators
48+
in a specific order.
4849
:param external_api: Configuration for an external API call.
4950
"""
5051

@@ -89,12 +90,14 @@ def __applyFilters(self, field_name: str, value: Any) -> Any:
8990

9091
field = self.fields.get(field_name)
9192

92-
for filter_ in field["filters"]:
93+
for filter_ in field.get("filters"):
9394
value = filter_.apply(value)
9495

9596
return value
9697

97-
def __validateField(self, field_name: str, field_info, value: Any) -> None:
98+
def __validateField(
99+
self, field_name: str, field_info: Any, value: Any
100+
) -> None:
98101
"""
99102
Validate the field value.
100103
"""
@@ -108,16 +111,38 @@ def __validateField(self, field_name: str, field_info, value: Any) -> None:
108111

109112
field = self.fields.get(field_name)
110113

111-
for validator in field["validators"]:
114+
for validator in field.get("validators"):
112115
validator.validate(value)
113116
except ValidationError:
114117
if field_info.get("fallback") is None:
115118
raise
116119

117120
return field_info.get("fallback")
118121

122+
def __applySteps(
123+
self, field_name: str, field_info: Any, value: Any
124+
) -> Any:
125+
"""
126+
Apply multiple filters and validators in a specific order.
127+
"""
128+
129+
field = self.fields.get(field_name)
130+
131+
try:
132+
for step in field.get("steps"):
133+
if isinstance(step, BaseFilter):
134+
value = step.apply(value)
135+
elif isinstance(step, BaseValidator):
136+
step.validate(value)
137+
except ValidationError:
138+
if field_info.get("fallback") is None:
139+
raise
140+
return field_info.get("fallback")
141+
142+
return value
143+
119144
def __callExternalApi(
120-
self, field_info, validated_data: dict
145+
self, field_info: Any, validated_data: dict
121146
) -> Optional[Any]:
122147
"""
123148
Führt den API-Aufruf durch und gibt den Wert zurück,
@@ -255,6 +280,8 @@ def validateData(
255280
self.__validateField(field_name, field_info, value) or value
256281
)
257282

283+
value = self.__applySteps(field_name, field_info, value)
284+
258285
if field_info.get("external_api"):
259286
value = self.__callExternalApi(field_info, validated_data)
260287

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name="flask_inputfilter",
5-
version="0.0.7.2",
5+
version="0.0.8",
66
author="Leander Cain Slotosch",
77
author_email="[email protected]",
88
description="A library to filter and validate input data in"

test/test_input_filter.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from flask_inputfilter import InputFilter
77
from flask_inputfilter.Condition import BaseCondition
88
from flask_inputfilter.Exception import ValidationError
9-
from flask_inputfilter.Filter import ToUpperFilter
9+
from flask_inputfilter.Filter import ToLowerFilter, ToUpperFilter
1010
from flask_inputfilter.Model import ExternalApiConfig
1111
from flask_inputfilter.Validator import (
1212
InArrayValidator,
@@ -242,6 +242,31 @@ def test_fallback_with_default(self) -> None:
242242
with self.assertRaises(ValidationError):
243243
self.inputFilter.validateData({})
244244

245+
def test_steps(self) -> None:
246+
"""
247+
Test that custom steps works.
248+
"""
249+
250+
self.inputFilter.add(
251+
"name_upper",
252+
steps=[
253+
ToUpperFilter(),
254+
InArrayValidator(["MAURICE"]),
255+
ToLowerFilter(),
256+
],
257+
)
258+
259+
validated_data = self.inputFilter.validateData(
260+
{"name_upper": "Maurice"}
261+
)
262+
self.assertEqual(validated_data["name_upper"], "maurice")
263+
264+
with self.assertRaises(ValidationError):
265+
validated_data = self.inputFilter.validateData(
266+
{"name_upper": "Alice"}
267+
)
268+
self.assertEqual(validated_data["name_upper"], "ALICE")
269+
245270
@patch("requests.request")
246271
def test_external_api(self, mock_request: Mock) -> None:
247272
"""

0 commit comments

Comments
 (0)