I'm using the Typing module and Pydantic to define a custom type which is a union. How can I tell which part of the Union is satisfied by a particular value after initializing the class?
For example, in:
from datetime import datetime
from typing import Union, Literal, Tuple, List
from pydantic import BaseModel, UUID4, ValidationError
class ExportDataRequest(BaseModel):
customers: Union[Literal["all"], List[UUID4], UUID4, List[int], int]
daterange: Union[Tuple[datetime, datetime], int]
data = {
"customers": "all",
'daterange': ("2024-01-01", "2024-03-01")
}
try:
model = ExportDataRequest(**data)
print(type(model.customers))
# str
except ValidationError as e:
print(e.errors())
The type from the Union
satisfied by the input to customers
above is the Literal["all"]
piece.
If I ask for the type
of model.customers
as in the above snippet, python will respond with str
.
Is there a way to determine that it is the Literal["all"]
from my class definition?
For anyone who sees this, I solved it with Pydantic's TypeAdapter
: https://docs.pydantic.dev/latest/concepts/type_adapter/
Adding the below to the code from the question above:
from pydantic import TypeAdapter
def handle_type(model):
types_to_check = [
(Literal["all"], "all"),
(List[UUID4], "uuid_list"),
(List[int], "int_list"),
(int, "int"),
(UUID4, "uuid"),
]
for type_to_check, result in types_to_check:
try:
TypeAdapter(type_to_check).validate_python(model.customers)
return result
except ValidationError:
pass
return None