Skip to content

Instantly share code, notes, and snippets.

@anatoly-scherbakov
Created June 10, 2020 11:49
Show Gist options
  • Save anatoly-scherbakov/ff0c832e933b60f2df01e3ba2793ce34 to your computer and use it in GitHub Desktop.
Save anatoly-scherbakov/ff0c832e933b60f2df01e3ba2793ce34 to your computer and use it in GitHub Desktop.
CommaSeparatedList[T]
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)
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'
}
]
@anatoly-scherbakov
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment