
Cuddles the Cat
"If it fits, I sits."
castfit helps you convert things like command-line arguments (e.g., from docopt) and simple API responses into something more typed with low overhead.
# modern (recommended)
uv add castfit
# classic
python -m pip install castfitAlternatively, you can just download the single file and name it castfit.py.
# Example: CLI-like args
from typing import Optional
from pathlib import Path
from castfit import castfit
class Args:
host: str
port: int
timeout: Optional[float]
log: Path
data = {
"host": "localhost",
"port": "8080",
# "timeout": "5.0" # key can be missing
"log": "app.log",
}
config = castfit(Args, data)
assert config.host == "localhost"
assert config.port == 8080
assert config.timeout is None
assert config.log == Path("app.log")
# if timeout was present:
data = {"host": "localhost", "port": "8080", "timeout": "5.0", "log": "app.log"}
config = castfit(Args, data)
assert config.host == "localhost"
assert config.port == 8080
assert config.timeout == 5.0
assert config.log == Path("app.log")# Example: nested types
from dataclasses import dataclass
from typing import Literal
from castfit import castfit
@dataclass
class Pet:
name: str
type: Literal["cat", "dog", "other"]
age: int
@dataclass
class Owner:
name: str
pets: list[Pet]
owner_data = {
"name": "Alice",
"pets": [
{"name": "Cuddles", "type": "cat", "age": "4"},
{"name": "Buddy", "type": "dog", "age": "2.5"}, # age will be cast to int(2)
],
}
owner = castfit(Owner, owner_data)
assert owner.name == "Alice"
assert len(owner.pets) == 2
assert isinstance(owner.pets[0], Pet)
assert owner.pets[0].name == "Cuddles"
assert owner.pets[0].type == "cat"
assert owner.pets[0].age == 4
assert owner.pets[1].name == "Buddy"
assert owner.pets[1].age == 2 # Cast from "2.5" to int# Example: adding a custom converter
from dataclasses import dataclass
import castfit
@dataclass
class LatLon:
lat: float
lon: float
@castfit.casts
def str_to_latlon(s: str) -> LatLon:
lat, lon = map(float, s.split(","))
return LatLon(lat, lon)
assert castfit.to_type("40.7,-74.0", LatLon) == LatLon(40.7, -74.0)