Skip to content

PY-PYDA0002 · declarative_field_constraint_candidate

Find field validators that reimplement built-in Pydantic constraints.

This is a deterministic rule for python. Read its implementation.

Inspect imported Pydantic field_validator methods and the directly declared fields they target. Recognize exact string normalization with strip, lower, or upper, rejecting length comparisons, and rejecting numeric bound comparisons. Map those fragments to StringConstraints or Field metadata. Report only directly typed fields and literal comparisons whose replacement preserves the observed boundary.

Each finding names the validator, its fields, and the precise declarative metadata already provided by Pydantic. Several fragments in one validator produce one combined finding. The value is the number of recognized declarative constraints across every field validator.

Domain checks, context-dependent validation, external lookups, cross-field invariants, unknown type aliases, wildcard validators, and Python regular-expression semantics are not inferred. Keep any irreducible logic in an Annotated functional validator or a field validator after moving the recognized constraints into the type.

Bad

A field validator returning `value.strip()` and raising when `len(value) < 1` is reported as
`StringConstraints(strip_whitespace=True)` plus `StringConstraints(min_length=1)`.
Good

type NonEmptyText = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)] makes validation reusable, visible in the annotation, and represented in generated schema. A validator checking a repository or another field remains ordinary custom logic.

  • Cites “Pydantic documentation”, validators, reusable annotated pattern. Open reference
  • Cites “Pydantic documentation”, types, StringConstraints. Open reference
  • Cites “Pydantic documentation”, fields, numeric and collection constraints. Open reference