Skip to main content

Experimental Pydantic Support

Pyrefly includes experimental support for Pydantic, a popular Python library for data validation and parsing. This feature aims to provide improved static type checking and IDE integration for Pydantic models.

Note: This support is experimental and actively evolving. The design may change based on feedback and development.

Feedback

We welcome your feedback and suggestions. Please share your thoughts and ideas here.


What is Pydantic?

Pydantic is a Python library designed for data validation and parsing using Python type annotations. While it shares similarities with dataclasses in creating structured data containers, Pydantic additionally provides extensive runtime data validation.


Validation Modes

Pydantic supports two validation modes for Pydantic models:

  • Lax (Default): Values are automatically converted when possible. For example, the string "123" will be interpreted as an integer.
  • Strict: Coercion is disabled, and only exactly matching types are accepted.

Pyrefly reads your model config to determine the validation mode, so it can strike a balance between providing useful typing and IDE support while maintaining Pydantic's flexibility.


How Pyrefly Supports Pydantic

  • Understands Pydantic constructs like BaseModel, Field, ConfigDict, and model-level config options.
  • Performs static analysis that mirrors Pydantic’s runtime validation logic, minimizing false positives in your IDE.
  • Provides immediate feedback (e.g. red squiggles or type errors) when the code would fail under Pydantic's actual behavior.
  • Does not require a plugin or manual config — support is builtin and automatic.

Comparison to Existing Tools

Mypy’s Pydantic plugin has five configuration options to control how strict the checking is — for example, whether coercion is allowed or extra fields are permitted. Pyrefly works differently. It doesn't rely on external config. Instead, it inspects your code directly — things like strict=True or extra='forbid' and strikes a balance between Pydantic's flexibility and Pyrefly's type checking.


How to Use

You don’t need to enable or configure anything to use Pyrefly’s Pydantic support.

Just:

  1. Install pydantic (preferably v2).
  2. Write your Pydantic models as usual.
  3. Run Pyrefly on your code.

Pyrefly will recognize Pydantic constructs like BaseModel, Field, and model_config, and provide appropriate type checking automatically.


Examples

Immutable fields with ConfigDict

from pydantic import BaseModel, ConfigDict

# Marking a model as frozen (immutable)
class Model(BaseModel):
model_config = ConfigDict(frozen=True)
x: int = 42
m = Model()
m.x = 10 # Error: Cannot set field `x` because the model is frozen

Strict vs Non-Strict Field Validation

from pydantic import BaseModel, Field

# Non-strict mode: runtime coercion allowed
class User(BaseModel):
name: str
age: int

# This passes at runtime and in Pyrefly.
y = User(name="Alice", age="30")

# Strict mode: enforce exact types, no coercion
class User2(BaseModel):
name: str
age: int = Field(strict=True)

# This triggers type errors in Pyrefly and red squiggles in the IDE,
# and will also fail at runtime due to type mismatch.
z = User2(name="Alice", age="30")

Handling Extra Fields in Pydantic Models

By default, Pydantic models allow extra fields (fields not defined in the model) to be passed during initialization. This behavior is consistent with Pyrefly’s support, which follows the default extra='allow' behavior.

from pydantic import BaseModel

# Extra fields allowed by default
class ModelAllow(BaseModel):
x: int

# This works fine: extra field `y` is allowed and ignored
ModelAllow(x=1, y=2)

# Explicitly forbid extra fields by setting `extra='forbid'`
class ModelForbid(BaseModel, extra="forbid"):
x: int

# This will raise a type error because of unexpected field `y`, which is consistent with runtime behavior.
ModelForbid(x=1, y=2)