skills/bossjones/pydantic/SKILL.md
Data validation and settings management using Python type annotations with Pydantic v2
npx skillsauth add aiskillstore/marketplace pydanticInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pydantic is a data validation library that uses Python type annotations to define data schemas, offering fast and extensible validation with automatic type coercion.
from pydantic import BaseModel
from datetime import datetime
from typing import Optional
class User(BaseModel):
id: int
name: str
email: str
signup_ts: Optional[datetime] = None
is_active: bool = True
# Automatic type coercion
user = User(
id='123', # String → int
name='John Doe',
email='[email protected]',
signup_ts='2017-06-01 12:22' # String → datetime
)
# From dict
user = User.model_validate({'id': 1, 'name': 'Alice', 'email': '[email protected]'})
# From JSON
user = User.model_validate_json('{"id": 1, "name": "Alice", "email": "[email protected]"}')
# Serialization
print(user.model_dump()) # Python dict
print(user.model_dump_json()) # JSON string
from pydantic import BaseModel, Field, EmailStr, HttpUrl
from typing import Annotated
class Product(BaseModel):
product_id: int = Field(alias='id', ge=1, description='Unique product identifier')
name: str = Field(min_length=1, max_length=200)
price: float = Field(gt=0, le=1000000)
email: EmailStr
website: HttpUrl
tags: list[str] = Field(default_factory=list, max_length=10)
internal_code: str = Field(exclude=True, default='N/A')
class User(BaseModel):
username: Annotated[str, Field(min_length=3, pattern=r'^[a-zA-Z0-9_]+$')]
age: int = Field(ge=0, le=150)
from pydantic import BaseModel, ConfigDict
class StrictModel(BaseModel):
model_config = ConfigDict(
strict=True, # No type coercion
frozen=True, # Immutable instances
validate_assignment=True, # Validate on attribute assignment
extra='forbid', # Reject extra fields
str_strip_whitespace=True,
populate_by_name=True, # Accept both alias and field name
use_enum_values=True, # Serialize enums as values
)
id: int
name: str
from pydantic import BaseModel, model_validator, field_validator, ValidationError
from typing import Any
class DateRange(BaseModel):
start_date: str
end_date: str
@field_validator('start_date', 'end_date')
@classmethod
def validate_date_format(cls, v: str) -> str:
# Custom validation logic
if not v:
raise ValueError('Date cannot be empty')
return v
@model_validator(mode='after')
def check_dates_order(self) -> 'DateRange':
# Cross-field validation
if self.start_date > self.end_date:
raise ValueError('start_date must be before end_date')
return self
# Using the model
try:
date_range = DateRange(start_date='2024-01-01', end_date='2024-01-31')
except ValidationError as e:
for error in e.errors():
print(f"{error['loc']}: {error['msg']}")
from pydantic import BaseModel, Field, SecretStr
from datetime import datetime
class User(BaseModel):
id: int
username: str
password: SecretStr
created_at: datetime
internal_data: dict = Field(exclude=True, default_factory=dict)
# Serialization options
user = User(
id=1,
username='john',
password='secret',
created_at=datetime.now()
)
# Basic serialization
print(user.model_dump()) # Python dict
print(user.model_dump_json()) # JSON string
# Excluding fields
print(user.model_dump(exclude={'password'}))
print(user.model_dump(exclude={'username', 'created_at'}))
# Include only specific fields
print(user.model_dump(include={'id', 'username'}))
# JSON-compatible serialization
print(user.model_dump(mode='json')) # datetime → string
print(user.model_dump(by_alias=True)) # Use field aliases
from typing import Annotated, Any
from pydantic import BaseModel, field_serializer, PlainSerializer
class Model(BaseModel):
number: int
created_at: datetime
@field_serializer('number')
def serialize_number(self, value: int) -> str:
return f"{value:,}" # Format with commas
# Using Annotated with PlainSerializer
custom_field: Annotated[
float,
PlainSerializer(lambda x: round(x, 2), return_type=float)
]
from pydantic import BaseModel
from typing import Optional, List
class Address(BaseModel):
street: str
city: str
country: str = 'USA'
zip_code: str
class User(BaseModel):
id: int
name: str
addresses: List[Address]
primary_address: Optional[Address] = None
# Usage
user = User(
id=1,
name='John Doe',
addresses=[
{'street': '123 Main St', 'city': 'New York', 'zip_code': '10001'},
{'street': '456 Oak Ave', 'city': 'Boston', 'zip_code': '02101'}
],
primary_address={'street': '123 Main St', 'city': 'New York', 'zip_code': '10001'}
)
from enum import Enum, IntEnum
from pydantic import BaseModel
class Status(str, Enum):
PENDING = 'pending'
ACTIVE = 'active'
COMPLETED = 'completed'
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
class Task(BaseModel):
title: str
status: Status = Status.PENDING
priority: Priority = Priority.MEDIUM
model_config = ConfigDict(use_enum_values=True)
# Can use enum values or names
task1 = Task(title='Task 1', status='active', priority=3)
task2 = Task(title='Task 2', status=Status.ACTIVE, priority=Priority.HIGH)
from pydantic import TypeAdapter
from typing import List, Optional
# Validate individual types without full models
int_adapter = TypeAdapter(int)
print(int_adapter.validate_python('123')) # 123
list_adapter = TypeAdapter(List[int])
print(list_adapter.validate_python(['1', '2', '3'])) # [1, 2, 3]
# Generate JSON schemas
print(int_adapter.json_schema())
print(list_adapter.json_schema())
from pydantic import BaseModel, ValidationError
from typing import Union
class EmailValidator(BaseModel):
email: str
@field_validator('email')
@classmethod
def validate_email(cls, v: str) -> str:
if '@' not in v:
raise ValueError('Invalid email format')
return v.lower()
# Validation error handling
try:
user = User(id='invalid', name='', email='test')
except ValidationError as e:
print(f"Errors: {e.error_count()}")
for error in e.errors():
print(f" {error['loc']}: {error['msg']} ({error['type']})")
uv add pydanticuv add pydantic[email] for EmailStruv add pydantic[url] for HttpUrluv add pydantic[typing-extensions] for extended type supportconint(gt=0) over int for positive numbersConfigDict to set global model behavior@field_validatormodel_dump() parameters to control output formatdevelopment
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.