Skip to main content

wiltech-labs-rest

The response-building core for Wiltech FastAPI apps: the typed _data / _metadata / _metaLinks / _messages envelope, HATEOAS-style links, field metadata and UTC date formatting, as described in docs/PYTHON_APP_CONVENTIONS.md.

It's the server side of @wiltech-labs/ngx-api-client, which reads these envelopes in the Angular apps.

Depends only on pydantic (no FastAPI import), so it's usable from any layer.

Install

Published on PyPI. In the consuming app:

uv add wiltech-labs-rest            # adds "wiltech-labs-rest>=x.y.z" to pyproject.toml + uv.lock

Upgrade later with uv lock --upgrade-package wiltech-labs-rest && uv sync. Docker builds and Cloudflare Workers (pywrangler) download it from PyPI like any other dependency — it's pure Python, depending only on pydantic.

Usage

# todos/schemas.py
from datetime import datetime

from pydantic import BaseModel, field_serializer

from wiltech_labs_rest import ApiResponse, FieldMetadata, LinkedResource, format_utc_datetime


class TodoDTO(LinkedResource):
    id: str
    title: str
    state: TodoState
    created_date: datetime

    @field_serializer("created_date")
    def serialize_created_date(self, value: datetime) -> str:
        return format_utc_datetime(value)


class TodoMetadata(BaseModel):
    id: FieldMetadata
    title: FieldMetadata
    state: FieldMetadata


TodoResponse = ApiResponse[TodoDTO, TodoMetadata]
TodoListResponse = ApiResponse[list[TodoDTO], TodoMetadata]
# todos/todo_service.py
from wiltech_labs_rest import API_PREFIX, FieldMetadata, Link, choice_field


class TodoService:
    @staticmethod
    def build_links(todo_id: str) -> dict[str, Link]:
        url = f"{API_PREFIX}/todos/{todo_id}"
        return {
            LINK_SELF: Link(href=url),
            LINK_UPDATE_TODO: Link(href=url, method="PUT"),
        }

    def build_metadata(self, todo: TodoDTO) -> TodoMetadata:
        return TodoMetadata(
            id=FieldMetadata(readOnly=True, hidden=True),
            title=FieldMetadata(mandatory=True),
            state=choice_field(TodoState),   # every enum member as {id, value}
        )

    def build_response(self, todo: TodoDTO) -> TodoResponse:
        return TodoResponse.of(TODO_DATA_NAME, todo, self.build_metadata(todo))
{
  "_data": { "todo": { "id": "…", "title": "…", "links": { "self": { "href": "/api/todos/…", "method": "GET" } } } },
  "_metadata": { "id": { "readOnly": true, "hidden": true }, "state": { "mandatory": true, "values": [ … ] } },
  "_metaLinks": {},
  "_messages": []
}

Public API

Everything is imported from wiltech_labs_rest:

Name What it is
ApiResponse[DataT, MetadataT] The envelope. Build with ApiResponse.of(data_name, data, metadata, meta_links=None, messages=None).
API_PREFIX "/api" — the prefix every router is mounted under; use it when building hrefs.
Link {href, method="GET"}
LinkedResource DTO base class adding links: dict[str, Link]
FieldMetadata readOnly / hidden / mandatory / values, plus limits maxLength (text), maxItems (lists), min / max / default (numbers); unset flags are left out of the JSON
NoMetadata _metadata for a response with no field rules; serializes as {}
EmbeddedRef {id, value} — an option in values, or an embedded reference
choice_field(enum) Mandatory FieldMetadata whose values are every member of the enum
Message, MessageType One _messages entry: INFO / WARNING / ERROR / SUCCESS
format_utc_datetime(value) datetime or ISO string → YYYY-MM-DDTHH:MM:SSZ
UtcDateTime, as_utc(value) Field type for database row models: parses stored dates and makes them timezone-aware UTC (naive = UTC), so they compare safely

Development

From the repo root:

uv sync
uv run --package wiltech-labs-rest pytest packages/rest

Publishing

Released to TestPyPI (rehearsal) and PyPI (what apps install from). They're separate sites with separate accounts and API tokens. Account setup, checking a TestPyPI release and fixing errors are covered in docs/PUBLISHING.md.

cd packages/rest

# 1. Test, bump, build
uv run pytest
uv version --bump patch                 # or minor / major; skip for the first 0.1.0
rm -rf ../../dist && uv build           # -> ../../dist/

# 2. TestPyPI (optional rehearsal), using a token from test.pypi.org
read -rsp "TestPyPI token: " UV_PUBLISH_TOKEN && export UV_PUBLISH_TOKEN && echo
uv publish --index testpypi ../../dist/*
unset UV_PUBLISH_TOKEN

# 3. PyPI (the real thing), using a token from pypi.org
read -rsp "PyPI token: " UV_PUBLISH_TOKEN && export UV_PUBLISH_TOKEN && echo
uv publish ../../dist/*
unset UV_PUBLISH_TOKEN

# 4. Commit and tag
git commit -am "wiltech-labs-rest <version>"
git tag rest-v<version> && git push && git push --tags

A version number can only be uploaded once to each site. To retry after a fix, bump the version and rebuild.

Metadata

Release files for wiltech-labs-rest 1.0.0

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

Source distribution (sdist)

Source distribution for wiltech-labs-rest 1.0.0
File Size Uploaded
wiltech_labs_rest-1.0.0.tar.gz 8.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wiltech-labs-rest 1.0.0
File Interpreter ABI Platform
wiltech_labs_rest-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.4 kB

Release files / wiltech_labs_rest-1.0.0.tar.gz

Download URL wiltech_labs_rest-1.0.0.tar.gz
Size 8.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e1c8475b935496ce89608ae074503c29168b3040d38b003c4bb7fd1d99eaced8
BLAKE2b-256 checksum
How to use checksums
0384b043db06978d94463a2d380386683a815ea0416bd3369bc330096ace1c1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / wiltech_labs_rest-1.0.0-py3-none-any.whl

Download URL wiltech_labs_rest-1.0.0-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ace3351f0243bcf848584168645082fe1c709f665e5729381d437bfb499c40cd
BLAKE2b-256 checksum
How to use checksums
d9530ae2fa7bceb297a6e27f9bcf28708be3411d9c2d8fa8a492c32bfe6f8816
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

1.0.1

2 release files

This release

1.0.0 This release

2 release files

0.1.0

2 release files

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