Support Pydantic validators in Annotated fields
- Dominant language
- Rust
- Stars
- 7k
- Forks
- 516
- PR merge metrics
- No merged PRs in 30d
Description
Pydantic has support for `validators` ([docs](https://pydantic.dev/docs/validation/latest/concepts/validators)) which allow transforming an input value before storing it in the model. It seems like the `@field_validator` decorator pattern should be supported (see prior issues like https://github.com/facebook/pyrefly/issues/589), but the `Annotated[T, *V]` pattern is not.
As a very simple example:
```py
from typing import Annotated, Any
from pydantic import BaseModel, BeforeValidator
def ensure_str(v: Any) -> str:
return str(v)
class MyModel(BaseModel):
field: Annotated[str, BeforeValidator(ensure_str)]
MyModel(field=5) # You can pass in other things here, but Pyrefly doesn't allow it
```
The example above can take in any value, convert it to a string, and store it as such in the model field. Pyrefly, however, only looks at the `str` argument of the `Annotated` type, and completely ignores the validators that come after. It only allows assigning a `str` to this field, even though I should be able to pass in whatever I want.
If validators are supplied, Pyrefly should let you assign whichever value the first validator allows. In my example above this would be `Any`, but that doesn't have to be the case. Ideally, this would respect `model_config.validate_assignment` to correctly typecheck on assignment _after_ `__init__` as well.
Similarly, it would make sense to have a check for the _output_ value of the validator to be compatible with the supposed type of the field, meaning that `-> str` is assignable to `Annotated[str, ...]`.
It could go further and check that chained validators are compatible with _eachother_, but that might be out of scope for this issue as it seems quite complicated.
## Why not just use the decorator pattern?
This allows extracting the validators out to a custom type that you can attach to fields, rather than having to write a validator function for every single field every single time. For large models that have a lot of fields that need pre-processing, this saves a lot of effort.
Contributor guide
Assessment
This issue has not been assessed yet.