facebook / facebook/pyrefly

Support Pydantic validators in Annotated fields

Open
#4,256 2 comments 0 reactions 1 assignee Claimed by @asukaminato0721 View on GitHub
help wanted pydantic stale typechecking
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.