Python is dynamically typed, and PEP484 Type Hints is not enforced during run time
Pydantic is the most widely used data validation library for Python.
pydantic.functional_validators let you do validation without base_model (e.g a function)
TypeAdapter instead of BaseModelfield_serializer you can do custom serialization{'country': 'France',
'description': 'Ripe in color and aromas, this chunky wine delivers heavy '
'baked-berry and raisin aromas in front of a jammy, extracted '
'palate. Raisin and cooked berry flavors finish plump, with '
'earthy notes.',
'id': 45100,
'points': 85,
'price': 10.0,
'province': 'Maule Valley',
'taster_name': 'Michael Schachner',
'taster_twitter_handle': '@wineschach',
'title': 'Balduzzi 2012 Reserva Merlot (Maule Valley)',
'variety': 'Merlot',
'vineyard': 'The Vineyard',
'winery': 'Balduzzi'}
id field always exists (this will be the primary key), and is an integerpoints field is an integerprice field is a floatcountry field always has a non-null value β if itβs set as null or the country key doesnβt exist in the raw data, it must be set to Unknown. This is because the use case we defined will involve querying on country downstreamprovince, region_1 and region_2 if they have the value null in the raw data β these fields will not be queried on and we do not want to unnecessarily store null values downstream| v1 | v2 |
|---|---|
root_validator |
@model_validator/@field_validator |
wine = Wine(**sample_data) |
wine = Wine(**sample_data) |
pprint(wine.dict(exclude_none=True, by_alias=True)) |
pprint(wine.model_dump(exclude_none=True, by_alias=True)) |
| v2 | v2-optimized |
|---|---|
class Wine(BaseModel) |
class Wine(TypedDict) |
wine = Wine(**sample_data) |
wines = WinesTypeAdapter.validate_python([sample_data]) |
All tests on Windows11, with WSL2:Ubuntu-22.04
129971 records
| v1 | v2 | v2-optimized | |
|---|---|---|---|
| All cases | 45.380 | 6.944 | 3.582 |
| Average pr run | 9.076 | 1.389 | 0.716 |
| Times speed up (v1) | 1 | 6.534 | 12.678 |
mypy integrationExplanation of why TypedDict work with a field_validator, but violates PEP589
See the different examples in demo/v2/good_mypy.py and demo/v2/bad_mypy.py