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 BaseModel
field_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 downstreamv1 | 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