Open1
pydantic v2 memo

- tagged union
tagged_union.py
from typing import Literal, NewType
from decimal import Decimal
from pydantic import BaseModel, TypeAdapter
class UnitQuantity(BaseModel):
kind: Literal["unit"]
quantity: int
class KilogramQuantity(BaseModel):
kind: Literal["kilogram"]
quantity: Decimal
type OrderQuantity = UnitQuantity | KilogramQuantity
CheckNumber = NewType("CheckNumber", int)
CardNumber = NewType("CardNumber", str)
"""単純型"""
if __name__ == "__main__":
examples = [
{"kind": "unit", "quantity": 10},
{"kind": "kilogram", "quantity": "2.5"},
]
adapter = TypeAdapter(OrderQuantity)
for data in examples:
oq = adapter.validate_python(data)
print(f"Parsed {data} to {oq} (type : {type(oq)})")
examples = [
UnitQuantity(kind="unit", quantity=10),
UnitQuantity(kind="unit", quantity=20),
UnitQuantity(kind="unit", quantity=333),
KilogramQuantity(kind="kilogram", quantity=Decimal("4.5")),
KilogramQuantity(kind="kilogram", quantity=Decimal("2.5")),
]
for data in examples:
match data:
case UnitQuantity(kind="unit", quantity=quantity):
print(f"Unit quantity: {quantity}")
case KilogramQuantity(kind="kilogram", quantity=quantity):
print(f"Kilogram quantity: {quantity}")
case _:
raise ValueError(
f"Unknown quantity type {data.kind}, {type(data) = }, {data = }"
)
simple_types = [
CheckNumber(12345678901234567890),
CardNumber("1234567890123456"),
]
for data in simple_types:
print(f"Simple type: {data} (type : {type(data)})")
uv run python --version
# >>> Python 3.13.2
uv run python tagged_union.py
# >>> Parsed {'kind': 'unit', 'quantity': 10} to kind='unit' quantity=10 (type : <class '__main__.UnitQuantity'>)
# >>> Parsed {'kind': 'kilogram', 'quantity': '2.5'} to kind='kilogram' quantity=Decimal('2.5') (type : <class '__main__.KilogramQuantity'>)