Created
June 10, 2020 11:49
-
-
Save anatoly-scherbakov/ff0c832e933b60f2df01e3ba2793ce34 to your computer and use it in GitHub Desktop.
CommaSeparatedList[T]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Generic, TypeVar | |
from pydantic import ValidationError | |
from pydantic.fields import ModelField | |
T = TypeVar('T') | |
class CommaSeparatedList(Generic[T]): | |
"""Parse and validate a list of comma separated values.""" | |
def __init__(self, value: T): | |
self.value = value | |
@classmethod | |
def __get_validators__(cls): | |
yield cls.validate | |
@classmethod | |
def validate(cls, v, field: ModelField): | |
if not isinstance(v, str): | |
raise TypeError('Expected a string.') | |
if not field.sub_fields: | |
# Generic parameters were not provided so we don't try to validate | |
# them and just return the value as is | |
return v | |
value_type = field.sub_fields[0] | |
sub_values = v.split(',') | |
pairs = [ | |
value_type.validate( | |
sub_value, | |
{}, | |
loc=str(i), | |
) for i, sub_value in enumerate(sub_values) | |
] | |
valid_values, errors = zip(*pairs) | |
errors = list(filter(bool, errors)) | |
if errors: | |
raise ValidationError(errors, cls) | |
return list(valid_values) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from pydantic import BaseModel, ValidationError | |
from crudantic.types import CommaSeparatedList | |
class StrListModel(BaseModel): | |
lst: CommaSeparatedList[str] | |
class IntListModel(BaseModel): | |
lst: CommaSeparatedList[int] | |
def test_comma_separated_string_list(): | |
m = StrListModel(lst='a,b,c') | |
assert m.lst == ['a', 'b', 'c'] | |
def test_comma_separated_int_list(): | |
m = IntListModel(lst='12,34,567') | |
assert m.lst == [12, 34, 567] | |
def test_comma_separated_int_list_error(): | |
try: | |
IntListModel(lst='12,34,abc') | |
except ValidationError as err: | |
assert err.errors() == [ | |
{ | |
'loc': ('lst', '2'), | |
'msg': 'value is not a valid integer', | |
'type': 'type_error.integer' | |
} | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The tests explain what this code does. However, the models using it do not work with FastAPI, and I currently do not have the time to debug or dive deeper into the issue. The intent was to support query strings like
?company_id__in=1,2,54
.