+31
languages/python/ecosystem/pydantic.md
+31
languages/python/ecosystem/pydantic.md
···
53
53
54
54
from [pdsx/_internal/config.py](https://github.com/zzstoatzz/pdsx/blob/main/src/pdsx/_internal/config.py)
55
55
56
+
## annotated types for reusable validation
57
+
58
+
when multiple schemas share the same validation logic, bind it to the type itself instead of repeating `@field_validator` on each schema:
59
+
60
+
```python
61
+
from datetime import timedelta
62
+
from typing import Annotated
63
+
from pydantic import AfterValidator, BaseModel
64
+
65
+
def _validate_non_negative_timedelta(v: timedelta) -> timedelta:
66
+
if v < timedelta(seconds=0):
67
+
raise ValueError("timedelta must be non-negative")
68
+
return v
69
+
70
+
NonNegativeTimedelta = Annotated[
71
+
timedelta,
72
+
AfterValidator(_validate_non_negative_timedelta)
73
+
]
74
+
75
+
class RunDeployment(BaseModel):
76
+
schedule_after: NonNegativeTimedelta
77
+
```
78
+
79
+
benefits:
80
+
- write validation once
81
+
- field types become swappable interfaces
82
+
- types are self-documenting
83
+
84
+
from [coping with python's type system](https://blog.zzstoatzz.io/coping-with-python-type-system/)
85
+
56
86
## when to use what
57
87
58
88
pydantic models are heavier than they look - they do a lot of work on instantiation. for internal data you control, python's `dataclasses` are simpler:
···
77
107
78
108
sources:
79
109
- [how to use pydantic-settings](https://blog.zzstoatzz.io/how-to-use-pydantic-settings/)
110
+
- [coping with python's type system](https://blog.zzstoatzz.io/coping-with-python-type-system/)