サンプル
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. python…
sha256:077123e3da7f317dd9d5939283b6bc716d114ee253a897590ad49ced1aa06422
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
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")