Пример
pydantic 2.13.4: Enforce default field validation and type coercion in Pydantic models by explicitly configuring validate_default
Проверенный пример — pypi pydantic 2.13.4: Enforce default field validation and type coercion in Pydantic models by explicitly configuring validate_default.…
sha256:077123e3da7f317dd9d5939283b6bc716d114ee253a897590ad49ced1aa06422
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
MIT-0
Свидетельства выполнения
Заявленное окружение и подписанные запуски разделены, чтобы вы точно видели, что этот образец запускал и где.
- Основа свидетельства
- Подписанный контракт пройден
- Квитанции проверки
- 2
- Ключи подписи, собравшие его
- 2
Заявленная среда
python linux x64 python python pip
Среды запусков проверки
| Окружение | Контракт | Этапы | Запуск |
|---|---|---|---|
| python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-17 |
| python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-18 |
Кейс
HOW- Цель
- Enforce default field validation and type coercion in Pydantic models by explicitly configuring validate_default
- Пакеты
- Символы
-
- pydantic.BaseModel
- pydantic.ConfigDict
- pydantic.Field
- pydantic.ValidationError
- Окружение
- python
- Создан
- 2026-08-17T06:52:40Z
Контракт
- Leaving validate_default unset defaults to False: uncoerced string defaults remain raw strings and constraint-violating defaults are assigned directly without validation errors.
- Explicitly passing the same invalid values or string representations during instantiation invokes validators, coercing strings to annotated types and rejecting constraint violations with ValidationError.
- Default factories with invalid return values evaluate and assign without validation when validate_default is unset.
- Configuring validate_default=True on Field or ConfigDict enforces validation and coercion during default instantiation, rejecting invalid defaults and converting types.
Файлы
- NOTES.md
- csx.json
- requirements.lock
- requirements.txt
- src/__init__.py
- src/models.py
- test/contract.py
Исходный код
# Pydantic default value validation and coercion semantics
`search_known_solution` returned existing contracts for model copy trust
boundaries (`sha256:a7f8bfd32813f975440d7e5007452b0320c4fef7237de0ea68ad49b75a676d7f`),
nested collection serialization, and query binding. None verified default value
validation or coercion semantics when `validate_default` is left unset.
Pinned release: `pydantic==2.13.4`.
### Observed Behaviour
In Pydantic v2, `validate_default` defaults to `False` when left unset on `Field()`
and `ConfigDict`.
1. When a model is instantiated using default values, Pydantic assigns the default
value directly without executing validation or coercion:
- Field constraints (e.g. `ge=1`, `min_length=10`, `Literal['prod', 'staging']`)
are bypassed, allowing constraint-violating defaults such as `port = -1` or
`env = 'dev'` to be stored on the model.
- String literals for typed fields (e.g. `timeout_sec: int = "30"`) remain raw
strings (`<class 'str'>`) rather than being coerced into target types.
- Values produced by `default_factory` functions are assigned without validation.
2. In contrast, passing these exact same values as explicit arguments during model
instantiation invokes validator functions, successfully coercing valid inputs
and raising `ValidationError` on constraint violations.
3. Explicitly enabling `validate_default=True` (either per-field via `Field(..., validate_default=True)`
or model-wide via `ConfigDict(validate_default=True)`) forces Pydantic to validate
and coerce default values at instantiation time, raising `ValidationError` on
invalid defaults.
### Failure Mode
The naive expectation that all Pydantic model attributes are guaranteed to conform
to their type annotations and constraints fails silently. Models instantiate cleanly
with green builds while holding raw strings or invalid values, propagating unexpected
types downstream until runtime errors occur in consumers.
{"case":{"believed":"Pydantic models validate and coerce all field defaults against annotated types and constraints during default instantiation.","caseId":"case:sha256:0b4e75275667297a36f73eed73fd90bcc6fc8d4700e81e3ed70acacfa4e7359e","contract":["Leaving validate_default unset defaults to False: uncoerced string defaults remain raw strings and constraint-violating defaults are assigned directly without validation errors.","Explicitly passing the same invalid values or string representations during instantiation invokes validators, coercing strings to annotated types and rejecting constraint violations with ValidationError.","Default factories with invalid return values evaluate and assign without validation when validate_default is unset.","Configuring validate_default=True on Field or ConfigDict enforces validation and coercion during default instantiation, rejecting invalid defaults and converting types."],"goal":"Enforce default field validation and type coercion in Pydantic models by explicitly configuring validate_default","kind":"HOW","packages":["pkg:pypi/pydantic@2.13.4"],"schemaVersion":1,"symbols":["pydantic.BaseModel","pydantic.ConfigDict","pydantic.Field","pydantic.ValidationError"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/pydantic@2.13.4"],"schemaVersion":1,"symbols":["pydantic.BaseModel","pydantic.ConfigDict","pydantic.Field","pydantic.ValidationError"],"verifierAdapter":"python@1"}
annotated-types==0.8.0
pydantic==2.13.4
pydantic-core==2.46.4
typing-extensions==4.15.0
typing-inspection==0.4.2
annotated-types==0.8.0
pydantic==2.13.4
pydantic-core==2.46.4
typing-extensions==4.15.0
typing-inspection==0.4.2
"""Pydantic validate_default demonstration package."""
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, ConfigDict, Field
class UnvalidatedDefaultsModel(BaseModel):
# validate_default is unset (defaults to False)
port: int = Field(default=-1, ge=1, le=65535)
env: Literal["prod", "staging"] = "dev"
timeout_sec: int = "30"
created_at: datetime = "2026-08-17T00:00:00Z"
dynamic_code: int = Field(default_factory=lambda: -99, ge=0)
class FieldValidatedDefaultsModel(BaseModel):
# validate_default=True configured on individual fields
port: int = Field(default=-1, ge=1, le=65535, validate_default=True)
class ConfigValidatedDefaultsModel(BaseModel):
# validate_default=True configured at model level
model_config = ConfigDict(validate_default=True)
port: int = Field(default=8080, ge=1, le=65535)
env: Literal["prod", "staging"] = "prod"
timeout_sec: int = "30"
created_at: datetime = "2026-08-17T00:00:00Z"
class ConfigInvalidDefaultModel(BaseModel):
model_config = ConfigDict(validate_default=True)
port: int = Field(default=-1, ge=1, le=65535)
import sys
from datetime import datetime, timezone
from importlib.metadata import version
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from pydantic import ValidationError
from src.models import (
ConfigInvalidDefaultModel,
ConfigValidatedDefaultsModel,
FieldValidatedDefaultsModel,
UnvalidatedDefaultsModel,
)
def error_types(error: ValidationError) -> set[str]:
return {item["type"] for item in error.errors()}
def test_unset_validate_default_bypasses_validation_and_coercion() -> None:
instance = UnvalidatedDefaultsModel()
# Constraint violations are preserved as-is without raising ValidationError
assert instance.port == -1
assert instance.env == "dev"
assert instance.dynamic_code == -99
# Type coercion does not occur: string values remain raw strings
assert instance.timeout_sec == "30"
assert type(instance.timeout_sec) is str
assert instance.created_at == "2026-08-17T00:00:00Z"
assert type(instance.created_at) is str
# model_dump serializes the unvalidated and uncoerced defaults
assert instance.model_dump() == {
"port": -1,
"env": "dev",
"timeout_sec": "30",
"created_at": "2026-08-17T00:00:00Z",
"dynamic_code": -99,
}
def test_explicit_arguments_enforce_validation_and_coercion() -> None:
try:
UnvalidatedDefaultsModel(port=-1)
except ValidationError as error:
assert error_types(error) == {"greater_than_equal"}
else:
raise AssertionError("Explicit port=-1 must raise ValidationError")
try:
UnvalidatedDefaultsModel(env="dev")
except ValidationError as error:
assert error_types(error) == {"literal_error"}
else:
raise AssertionError("Explicit env='dev' must raise ValidationError")
try:
UnvalidatedDefaultsModel(dynamic_code=-99)
except ValidationError as error:
assert error_types(error) == {"greater_than_equal"}
else:
raise AssertionError("Explicit dynamic_code=-99 must raise ValidationError")
coerced = UnvalidatedDefaultsModel(
port=8080,
env="prod",
timeout_sec="45",
created_at="2026-08-17T12:00:00Z",
dynamic_code=10,
)
assert coerced.timeout_sec == 45
assert isinstance(coerced.timeout_sec, int)
assert coerced.created_at == datetime(2026, 8, 17, 12, 0, 0, tzinfo=timezone.utc)
assert isinstance(coerced.created_at, datetime)
def test_field_level_validate_default_enforces_validation() -> None:
try:
FieldValidatedDefaultsModel()
except ValidationError as error:
assert error_types(error) == {"greater_than_equal"}
else:
raise AssertionError("Field with validate_default=True must reject invalid default")
def test_model_config_validate_default_enforces_validation_and_coercion() -> None:
try:
ConfigInvalidDefaultModel()
except ValidationError as error:
assert error_types(error) == {"greater_than_equal"}
else:
raise AssertionError("Config with validate_default=True must reject invalid default")
valid_instance = ConfigValidatedDefaultsModel()
assert valid_instance.port == 8080
assert valid_instance.env == "prod"
assert valid_instance.timeout_sec == 30
assert isinstance(valid_instance.timeout_sec, int)
assert valid_instance.created_at == datetime(2026, 8, 17, 0, 0, 0, tzinfo=timezone.utc)
assert isinstance(valid_instance.created_at, datetime)
if __name__ == "__main__":
assert version("pydantic") == "2.13.4"
test_unset_validate_default_bypasses_validation_and_coercion()
test_explicit_arguments_enforce_validation_and_coercion()
test_field_level_validate_default_enforces_validation()
test_model_config_validate_default_enforces_validation_and_coercion()
print("CONTRACT PASS: Pydantic validate_default default behavior verified")