Skip to main content

A typed Python framework for modeling and generating API clients.

Project description

Klarient

Klarient is a typed Python framework for building small, readable REST API wrappers.

The goal is to let an API wrapper look like the API domain instead of a pile of raw HTTP calls. Resources model the URI tree, request objects model inputs, and response objects model typed results while preserving HTTP metadata.

Klarient is early pre-alpha software. The design is usable, but the public API may still change as more real APIs are modeled.

Install

pip install klarient

Install a transport extra for the HTTP library you want to use:

pip install "klarient[requests]"
pip install "klarient[httpx]"
pip install "klarient[aiohttp]"

Basic Shape

A Klarient wrapper usually has four parts:

  • a client class
  • resource classes that mirror the REST URI tree
  • request objects for typed query or body data
  • response objects for typed access to API responses
from enum import StrEnum

from klarient import (
    JSONBodyRequest,
    RequestField,
    RequestsTransport,
    ResourcePath,
    ResponseDict,
    SyncClient,
    SyncResource,
)


class TaskStatus(StrEnum):
    OPEN = "open"
    DONE = "done"


class TaskCreate(JSONBodyRequest):
    def __init__(
        self,
        *,
        title: str | None = None,
        status: TaskStatus | None = None,
    ) -> None:
        super().__init__(title=title, status=status)

    title = RequestField[str]()
    status = RequestField[TaskStatus]()


class Task(ResponseDict):
    @property
    def id(self) -> int:
        return int(self["id"])

    @property
    def title(self) -> str:
        return str(self["title"])

    @property
    def status(self) -> TaskStatus:
        return TaskStatus(str(self["status"]))


class TaskResponse(ResponseDict):
    @property
    def data(self) -> Task:
        return Task(self["data"], response=self.http_response)


class TaskResource(SyncResource[SyncClient]):
    def retrieve(self) -> TaskResponse:
        return self._executor.get(TaskResponse)


class TasksResource(SyncResource[SyncClient]):
    def __getitem__(self, task_id: int | str) -> TaskResource:
        return TaskResource(self, segment=ResourcePath.segment(task_id))

    def create(self, options: TaskCreate) -> TaskResponse:
        return self._executor.post(TaskResponse, options)


class TasksClient(SyncClient):
    def __init__(self, *, base_url: str) -> None:
        super().__init__(
            base_url=base_url,
            transport=RequestsTransport(),
        )
        self.tasks = TasksResource(self, segment="api/tasks")

Usage:

client = TasksClient(base_url="https://api.example.test")

created = client.tasks.create(
    TaskCreate(title="Write docs", status=TaskStatus.OPEN)
)

print(created.data.id)
print(created.data.title)
print(created.data.status)

task = client.tasks[created.data.id].retrieve()
print(task.data.status)

Request Modeling

Use typed request objects instead of passing dictionaries through your public wrapper API.

from klarient import QueryFieldSpec, QueryRequest, QuerySerialization


class TaskQuery(QueryRequest):
    def __init__(
        self,
        *,
        status: list[TaskStatus] | None = None,
        page: int | None = None,
    ) -> None:
        super().__init__(status=status, page=page)

    status = RequestField[list[TaskStatus]](
        query=QueryFieldSpec(serialization=QuerySerialization.REPEAT)
    )
    page = RequestField[int]()

That repeated field is encoded as repeated query values such as:

?status=open&status=done

Response Modeling

Response models keep the original HTTP response available:

response = client.tasks[123].retrieve()

print(response.data.title)
print(response.status)
print(response.http_response.headers)
print(response.native_response)

Use ResponseDict for JSON objects, ResponseList for JSON arrays, and derive from ResponseBase when a response owns a different representation such as text, XML, or bytes.

Project Status

Klarient is currently focused on the core framework:

  • transport-independent HTTP primitives
  • sync and async clients
  • typed REST resources
  • typed request field helpers
  • typed response models
  • reusable pagination strategies
  • pluggable transport adapters for requests, httpx, and aiohttp

Examples and broader documentation will live outside the core package while the framework stabilizes.

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

klarient-0.1.0.tar.gz (44.2 kB view details)

Uploaded Source

Built Distribution

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

klarient-0.1.0-py3-none-any.whl (59.5 kB view details)

Uploaded Python 3

File details

Details for the file klarient-0.1.0.tar.gz.

File metadata

  • Download URL: klarient-0.1.0.tar.gz
  • Upload date:
  • Size: 44.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for klarient-0.1.0.tar.gz
Algorithm Hash digest
SHA256 20216c0bec1c0de3e87338390d185cc5a8c62616900e31b7131c82299fc02a55
MD5 1d10bed10c7ce5619aaafc1d4e5fc64f
BLAKE2b-256 1bbde44b94ba6c74286c0f7c765824df9a73e79354fd4a006a89f9201fee21c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for klarient-0.1.0.tar.gz:

Publisher: python-publish.yml on ludvikjerabek/klarient

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file klarient-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: klarient-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 59.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for klarient-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f1b1360139c2ec5099af24c3661da27986d7ae85f79507257fd07f79d8b14ab8
MD5 0553e8807eef6cb434ac38999a834803
BLAKE2b-256 2a63a302b7481abe00b7dd5cac031e2b9b9a8fd510a2631d8c2e4c903abf8c0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for klarient-0.1.0-py3-none-any.whl:

Publisher: python-publish.yml on ludvikjerabek/klarient

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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