Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6648562

Browse files
authored
Merge pull request#61 from Ge0rg3/dev/steichman/optional_list_enum
Fix issue where Optional[List[Enum]] didn't work, among other nested generic types
2 parents47f81d2 +2db7883 commit6648562

File tree

10 files changed

+2346
-432
lines changed

10 files changed

+2346
-432
lines changed

‎README.md‎

Lines changed: 47 additions & 45 deletions
Large diffs are not rendered by default.

‎flask_parameter_validation/parameter_types/parameter.py‎

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def __init__(
3434
alias=None,# str: alias for parameter name
3535
json_schema=None,# dict: JSON Schema to check received dicts or lists against
3636
blank_none=None,# bool: Whether blank strings should be converted to None when validating a type of Optional[str]
37+
list_disable_query_csv=None,# bool: Whether query strings should be split by `,` when validating a type of list
3738
):
3839
self.default=default
3940
self.min_list_length=min_list_length
@@ -51,6 +52,8 @@ def __init__(
5152
self.alias=alias
5253
self.json_schema=json_schema
5354
self.blank_none=blank_none
55+
self.list_disable_query_csv=list_disable_query_csv
56+
5457

5558
deffunc_helper(self,v):
5659
func_result=self.func(v)
@@ -158,53 +161,63 @@ def validate(self, value):
158161

159162
returnTrue
160163

161-
defconvert(self,value,allowed_types):
164+
defconvert(self,value,allowed_types,current_error=None):
162165
"""Some parameter types require manual type conversion (see Query)"""
163166
blank_none=self.blank_none
164167
ifblank_noneisNone:# Default blank_none to False if not provided or set in app config
165168
blank_none=Falseif"FPV_BLANK_NONE"notinflask.current_app.configelseflask.current_app.config["FPV_BLANK_NONE"]
166169

170+
error=None
167171
# Datetime conversion
168172
ifNoneinallowed_typesandvalueisNone:
169173
returnvalue
174+
iftype(value)inallowed_typesandtype(value)isnotstrandtype(value)isnotint:# Return values that have already been converted by a subclass, but not str or int, as that would be premature
175+
returnvalue
176+
ifdateinallowed_types:
177+
try:
178+
returndate.fromisoformat(str(value))
179+
exceptValueError:
180+
error=ValueError("date format does not match ISO 8601")
181+
iftimeinallowed_types:
182+
try:
183+
returntime.fromisoformat(str(value))
184+
exceptValueError:
185+
error=ValueError("time format does not match ISO 8601")
170186
ifdatetimeinallowed_types:
171187
ifself.datetime_formatisNone:
172188
try:
173-
returnparser.parse(str(value))
174-
exceptparser._parser.ParserError:
175-
pass
189+
returndatetime.fromisoformat(str(value))
190+
exceptValueError:
191+
error=ValueError("datetime format does not match ISO 8601")
176192
else:
177193
try:
178194
returndatetime.strptime(str(value),self.datetime_format)
179195
exceptValueError:
180-
raiseValueError(
181-
f"datetime format does not match:{self.datetime_format}"
182-
)
183-
pass
184-
eliftimeinallowed_types:
185-
try:
186-
returntime.fromisoformat(str(value))
187-
exceptValueError:
188-
raiseValueError("time format does not match ISO 8601")
189-
elifdateinallowed_types:
190-
try:
191-
returndate.fromisoformat(str(value))
192-
exceptValueError:
193-
raiseValueError("date format does not match ISO 8601")
194-
elifblank_noneandtype(None)inallowed_typesandstrinallowed_typesandtype(value)isstrandlen(value)==0:
196+
error=ValueError(f"datetime format does not match:{self.datetime_format}")
197+
ifblank_noneandtype(None)inallowed_typesandstrinallowed_typesandtype(value)isstrandlen(value)==0:
195198
returnNone
196-
elifany(isclass(allowed_type)and (issubclass(allowed_type,str)orissubclass(allowed_type,int)andissubclass(allowed_type,Enum))forallowed_typeinallowed_types):
199+
ifany(isclass(allowed_type)and (issubclass(allowed_type,str)orissubclass(allowed_type,int)andissubclass(allowed_type,Enum))forallowed_typeinallowed_types):
197200
forallowed_typeinallowed_types:
198201
ifissubclass(allowed_type,Enum):
199-
ifissubclass(allowed_types[0],int):
200-
value=int(value)
201-
returning=allowed_types[0](value)
202-
returnreturning
203-
elifuuid.UUIDinallowed_types:
202+
try:
203+
ifissubclass(allowed_type,int):
204+
value=int(value)
205+
returning=allowed_type(value)
206+
returnreturning
207+
exceptValueErrorase:
208+
error=e
209+
ifuuid.UUIDinallowed_types:
204210
try:
205211
iftype(value)==uuid.UUID:# Handle default of type UUID
206212
returnvalue
207-
returnuuid.UUID(value)
213+
try:
214+
returnuuid.UUID(value)
215+
exceptValueErrorase:
216+
error=e
208217
exceptAttributeError:
209-
raiseValueError("UUID format is incorrect")
210-
returnvalue
218+
error=ValueError("UUID format is incorrect")
219+
ifstrinallowed_types:
220+
returnvalue
221+
iferrorandtype(value)isstr:
222+
raiseerror
223+
returnvalue

‎flask_parameter_validation/parameter_types/query.py‎

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- i.e. sent in GET requests, /?username=myname
44
"""
55
importjson
6+
fromenumimportEnum
67

78
from .parameterimportParameter
89

@@ -13,33 +14,41 @@ class Query(Parameter):
1314
def__init__(self,default=None,**kwargs):
1415
super().__init__(default,**kwargs)
1516

16-
defconvert(self,value,allowed_types):
17+
defconvert(self,value,allowed_types,current_error=None):
1718
"""Convert query parameters to corresponding types."""
19+
original_value=value
20+
error=None
1821
iftype(value)isstr:
19-
# int conversion
22+
# int conversion done before dict to handle potential IntEnum
2023
ifintinallowed_types:
2124
try:
22-
value=int(value)
23-
exceptValueError:
25+
enum_test=super().convert(value,allowed_types,current_error)
26+
ifissubclass(type(enum_test),Enum)andissubclass(type(enum_test),int):
27+
returnenum_test
28+
returnint(value)
29+
exceptValueErrororTypeError:
2430
pass
25-
# float conversion
26-
iffloatinallowed_types:
31+
ifdictinallowed_types:
2732
try:
28-
value=float(value)
33+
returnjson.loads(value)
2934
exceptValueError:
30-
pass
35+
error=ValueError(f"invalid JSON")
36+
# float conversion
37+
iffloatinallowed_types:
38+
ifnot (type(value)isintandstr(value)==original_value):# If we've already converted an int and the conversion is exact, skip float conversion
39+
try:
40+
returnfloat(value)
41+
exceptValueError:
42+
pass
3143
# bool conversion
3244
ifboolinallowed_types:
3345
try:
3446
ifvalue.lower()=="true":
35-
value=True
47+
returnTrue
3648
elifvalue.lower()=="false":
37-
value=False
49+
returnFalse
3850
exceptAttributeError:
3951
pass
40-
ifdictinallowed_types:
41-
try:
42-
value=json.loads(value)
43-
exceptValueError:
44-
raiseValueError(f"invalid JSON")
45-
returnsuper().convert(value,allowed_types)
52+
iftype(value)isnotstr:
53+
error=None
54+
returnsuper().convert(value,allowed_types,current_error=error)

‎flask_parameter_validation/parameter_types/route.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Route Parameters
33
- Sent as part of a path, i.e. /user/<int:id>
44
"""
5+
fromenumimportEnum
6+
57
from .parameterimportParameter
68

79

@@ -11,13 +13,17 @@ class Route(Parameter):
1113
def__init__(self,default=None,**kwargs):
1214
super().__init__(default,**kwargs)
1315

14-
defconvert(self,value,allowed_types):
16+
defconvert(self,value,allowed_types,current_error=None):
1517
"""Convert query parameters to corresponding types."""
1618
iftype(value)isstr:
1719
# int conversion
1820
ifintinallowed_types:
1921
try:
20-
value=int(value)
22+
enum_test=super().convert(value,allowed_types,current_error)
23+
ifissubclass(type(enum_test),Enum)andissubclass(type(enum_test),int):
24+
value=enum_test
25+
else:
26+
value=int(value)
2127
exceptValueError:
2228
pass
2329
# float conversion

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp