Skip to main content

# kat-transform

Kittie's attempt to declaratively transform Python objects into serializable dictionaries. Minimal, composable, Pydantic-free. Just fields, dataclasses, and a pinch of magic.

Features

  • Declarative schema definition
  • Field-level transformation
  • Nested schemas
  • Dependency-injected getters via FunDI
  • No runtime overhead, no metaclasses, no opinionated data modeling
  • Multiple getters(with fallback: "created_at" -> "created")
  • Custom field metadata and schema metadata

Basic Usage:

from dataclasses import dataclass
from datetime import datetime

from kat_transform import schema, field, transform

user_schema = schema(
    "User",
    field(str, "username"),
    field(int, "id")
)

@dataclass
class User:
    username: str,
    id: int

user = User("Kuyugama", -1)

raw = user_schema.get(user)
transformed = transform(raw)

assert transformed == {"username": "Kuyugama", "id": -1}

print(transformed)

Deep dive

Transform on the Fly

from dataclasses import dataclass
from datetime import datetime

from kat_transform import schema, field, transform

user_schema = schema(
    "User",
    field(str, "username", transform=lambda x: x.lower()),
    field(int, "created", transform=lambda x: int(x.timestamp()), getter=("created_at", "created")),
    field(int, "id")
)

@dataclass
class User:
    username: str,
    created_at: datetime
    id: int

user = User("Kuyugama", datetime(day=17, month=3, year=2026), -1)

raw = user_schema.get(user)
transformed = transform(raw)

assert transformed == {"username": "kuyugama", "created": 1773612000, "id": -1}

print(transformed)

DI-based getters (aka fields from the void)

from dataclasses import dataclass
from datetime import datetime

from kat_transform import schema, field, resolve_fields, transform

error_schema = schema(
    "Error",
    field(str, "message"),
    field(str, "category"),
    field(str, "code"),
    field(str, "cat", transform=lambda x: f"https://http.cat/{x}", getter=lambda response: response["status_code"])
)

@dataclass
class Error:
    message: str
    category: str
    code: str

error = Error("User not found", "users", "not-found")

raw = error_schema.get(error)

resolved = resolve_fields({"response": {"status_code": 404}}, raw)

transformed = transform(resolved)

assert transformed == {"message": "User not found", "category": "users", "code": "not-found", "cat": "https://http.cat/404"}

print(transformed)

resolve_fields uses FunDI dependency injection under the hood. All getter functions should be valid FunDI dependencies.

Nested schemas? Awww, gotcha!

from dataclasses import dataclass
from datetime import datetime

from kat_transform import schema, field, resolve_fields, transform

user_schema = schema(
    "User",
    field(str, "username", transform=lambda x: x.lower()),
    field(int, "id"),
)

content_schema = schema(
    "Content",
    field(user_schema, "owner"),
    field(str, "title", transform=lambda x: x.title()),
)


@dataclass
class User:
    username: str
    id: int


@dataclass
class Content:
  owner: User
  title: str


user = User("Kuyugama", 1)

content = Content(user, "Clever flower")

raw = content_schema.get(content)

transformed = transform(raw)

assert transformed == {"owner": {"username": "kuyugama", "id": 1}, "title": "Clever Flower"}

print(transformed)

Metadata

Release files for kat-transform 0.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kat-transform 0.0.6
File Size Uploaded Provenance
kat_transform-0.0.6.tar.gz 25.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for kat-transform 0.0.6
File Interpreter ABI Platform
kat_transform-0.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 46.1 kB

Release files / kat_transform-0.0.6.tar.gz

Download URL kat_transform-0.0.6.tar.gz
Size 25.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5d75267fcabab4af2ad435ee4a2459e05dd8a9f09991ab242f14f2d5b5c560bf
BLAKE2b-256 checksum
How to use checksums
b49cc30dbfc531772c17864e38a6caa36d41f644d7b19e47a5104c60aa29cddf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.7.14

Release files / kat_transform-0.0.6-py3-none-any.whl

Download URL kat_transform-0.0.6-py3-none-any.whl
Size 20.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78db373a0d4f60e6021f397aff6347216c63a4e8b347015c1baf8e8d286c1fb3
BLAKE2b-256 checksum
How to use checksums
bbe516a2a1bb8df4e8bd575d163be5685641a615e6597514d947d6b045000c82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.7.14

Security for kat-transform 0.0.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page