model_example.py

script

← Back to skill

Content hash: 9628891e1e44dca2592f721ce46ef3e4a630a438b8e19b9331b0a5e68c2f9833
#!/usr/bin/env python3
"""Demonstrates dataclass + Pydantic modeling with validation and JSON round-tripping.

Covers: @dataclass(slots=True) for internal models, Pydantic BaseModel for I/O
boundaries, and the critical default_factory pattern for mutable defaults.
"""
from __future__ import annotations

import json
from dataclasses import dataclass, field
from typing import Any


# --- Internal model: dataclass with slots ---

@dataclass(slots=True)
class Point:
    x: float
    y: float

    def distance_from_origin(self) -> float:
        return (self.x ** 2 + self.y ** 2) ** 0.5


# --- Boundary model: Pydantic with validation ---

try:
    from pydantic import BaseModel, Field, field_validator
except ImportError:
    print("Install pydantic: pip install pydantic")
    raise


class SkillInput(BaseModel):
    name: str = Field(min_length=1, max_length=100)
    description: str = Field(min_length=10)
    tags: list[str] = Field(default_factory=list)

    @field_validator("tags")
    @classmethod
    def tags_must_be_lowercase(cls, v: list[str]) -> list[str]:
        return [t.lower().strip() for t in v]


# --- Usage: dataclass (no validation, fast) ---

p = Point(3.0, 4.0)
print(f"Point distance: {p.distance_from_origin()}")   # 5.0

# --- Usage: Pydantic (validates, serializes) ---

skill = SkillInput(name="Python Tips", description="Useful Python patterns for agents")
print(f"Model dump: {skill.model_dump()}")

# JSON round-trip
raw_json = skill.model_dump_json()
print(f"JSON: {raw_json}")

reloaded = SkillInput.model_validate_json(raw_json)
print(f"Reloaded: {reloaded.name} — {reloaded.description[:30]}...")


# --- Mutable default pitfall (DON'T DO THIS) ---

@dataclass
class BadConfig:
    items: list[str] = []   # BUG: shared across instances!


# Correct:
@dataclass
class GoodConfig:
    items: list[str] = field(default_factory=list)


c1 = GoodConfig()
c2 = GoodConfig()
c1.items.append("a")
print(f"c1: {c1.items}, c2: {c2.items}")  # ['a'], [] — correct isolation

print("\nAll checks passed.")