Skip to main content

Transform python data using declarative schemas

Project description

# 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)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kat_transform-0.0.6.tar.gz (25.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kat_transform-0.0.6-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

Details for the file kat_transform-0.0.6.tar.gz.

File metadata

  • Download URL: kat_transform-0.0.6.tar.gz
  • Upload date:
  • Size: 25.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.7.14

File hashes

Hashes for kat_transform-0.0.6.tar.gz
Algorithm Hash digest
SHA256 5d75267fcabab4af2ad435ee4a2459e05dd8a9f09991ab242f14f2d5b5c560bf
MD5 b590fbf49c8e9f6a2d395d1373049423
BLAKE2b-256 b49cc30dbfc531772c17864e38a6caa36d41f644d7b19e47a5104c60aa29cddf

See more details on using hashes here.

File details

Details for the file kat_transform-0.0.6-py3-none-any.whl.

File metadata

File hashes

Hashes for kat_transform-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 78db373a0d4f60e6021f397aff6347216c63a4e8b347015c1baf8e8d286c1fb3
MD5 466c3ade7af8b893fa7b3da071b81b2e
BLAKE2b-256 bbe516a2a1bb8df4e8bd575d163be5685641a615e6597514d947d6b045000c82

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page