Skip to main content

weltenfw — v0.4.1

WeltenHub Client Framework — typed REST client, Pydantic v2 schemas, and a pluggable storage-backend pattern for the WeltenHub Story Universe API.

CI PyPI Python License: MIT

Installation

pip install iil-weltenfw                  # core (httpx + pydantic)
pip install iil-weltenfw[django]          # + Django AppConfig + DjangoCache

Quick Start — Low-Level Client

from weltenfw import WeltenClient

with WeltenClient(
    base_url="https://weltenforger.com/api/v1",
    token="your-token",
) as client:
    world = client.worlds.create(WorldCreateInput(
        name="Aldoria", setting_era="medieval",
    ))
    chars = client.characters.list(world=str(world.id))
    locs  = client.locations.list(world=str(world.id))
    stories = client.stories.list(world=str(world.id))
    scenes  = client.scenes.list(story=str(stories.results[0].id))

Async

async with WeltenClient(base_url=..., token=...) as client:
    world = await client.worlds.aget(world_id)
    locs  = await client.locations.alist(world=world_id)

Django Integration

# settings.py
INSTALLED_APPS  = [..., "weltenfw.django"]
WELTENHUB_URL   = "https://weltenforger.com/api/v1"
WELTENHUB_TOKEN = env("WELTENHUB_TOKEN")

# services.py
from weltenfw.django import get_client
client = get_client()   # lazy singleton, one per worker

Storage Backend Pattern (ADR-117)

weltenfw ships WeltenhubBackend — a higher-level write/read facade on top of WeltenClient. Consumer apps (bfagent, travel-beat, …) use this to keep Weltenhub as the single source of truth without duplicating data.

Two Scenarios — same API

from weltenfw.backends import WeltenhubBackend

backend = WeltenhubBackend(
    base_url="https://weltenforger.com/api/v1",
    token=token,   # user token (A) or service token (B)
)

Scenario A — user has Weltenhub account: token = user.weltenhub_token → data visible in Weltenhub UI immediately.

Scenario B — user not yet linked: token = WELTENHUB_API_KEY (service token) → data stored, UUID returned, UI locked until user links their account. No duplication; consumer stores only UUID.


Backend API Reference

Worlds

Method Signature Returns
create_world (name, description, setting_era, **kw) WorldResult
get_world (world_id) WorldResult
list_worlds (search, page) WorldPage
update_world (world_id, **fields) WorldResult
result = backend.create_world(name="Aldoria", description="Kingdom of runes")
result.id       # Weltenhub UUID
result.ok       # True on success
result.error    # str | None
result.backend  # "weltenhub"

Characters

Method Signature Returns
create_character (world_id, name, personality, backstory, is_protagonist, **kw) CharacterResult
get_character (character_id) CharacterResult
list_characters (world_id, page) CharacterPage
chars = backend.list_characters(world_id="<uuid>")
for c in chars.results:
    print(c.name, c.role_name)

Locations

Method Signature Returns
create_location (world_id, name, description, parent_id, **kw) LocationResult
list_locations (world_id, page, page_size) LocationPage
locs = backend.list_locations(world_id="<uuid>")
for loc in locs.results:
    print(loc.name, loc.location_type_name, loc.full_path)

new_loc = backend.create_location(
    world_id="<uuid>", name="Eisenhain",
    description="A fortress city in the northern mountains.",
)

Stories

Method Signature Returns
create_story (world_id, title, synopsis, **kw) StoryResult
list_stories (world_id, page, page_size) StoryPage
stories = backend.list_stories(world_id="<uuid>")
for s in stories.results:
    print(s.title, s.status)

story = backend.create_story(world_id="<uuid>", title="Der Ruf der Runen")

Scenes

Method Signature Returns
create_scene (story_id, title, summary, order, **kw) SceneResult
list_scenes (story_id, page, page_size) ScenePage
scenes = backend.list_scenes(story_id="<uuid>")
for s in scenes.results:
    print(s.title, s.location_name, s.order)

Result Types

All result types are frozen dataclasses with an .ok property:

Type Key fields
WorldResult id, name, description, setting_era, genre_name
CharacterResult id, name, world_id, role_name, description, personality
LocationResult id, name, world_id, parent_id, location_type_name, description, full_path
SceneResult id, title, story_id, summary, location_name, order
StoryResult id, title, world_id, genre_name, status, synopsis

All *Page types have .results: list[*Result] and .count: int.


User Provisioning (S2S, idempotent)

token = WeltenhubBackend.provision_user(
    username="bf_hugo",
    email="hugo@example.com",
    base_url="https://weltenforger.com/api/v1",
    service_token=WELTENHUB_API_KEY,
)
# Returns per-user token (Scenario A) or None on failure

LocalWorldBackend (tests / offline)

from weltenfw.backends.local import LocalWorldBackend

backend = LocalWorldBackend()
result = backend.create_world(name="Test")
# result.id = "" — caller manages local DB
# result.backend = "local"

Custom Backend (Protocol)

Implement AbstractWorldBackend without inheriting — structural subtyping:

from weltenfw.backends.base import AbstractWorldBackend, WorldResult

class MyBackend:
    def create_world(self, name: str, **kw) -> WorldResult: ...
    def get_world(self, world_id: str) -> WorldResult: ...
    def list_worlds(self, search: str = "", page: int = 1): ...
    def update_world(self, world_id: str, **fields): ...
    def create_character(self, world_id, name, **kw): ...
    def get_character(self, character_id): ...
    def list_characters(self, world_id, page=1): ...
    def list_locations(self, world_id, page=1, page_size=100): ...
    def create_location(self, world_id, name, **kw): ...
    def list_stories(self, world_id, page=1, page_size=100): ...
    def create_story(self, world_id, title, **kw): ...
    def list_scenes(self, story_id, page=1, page_size=100): ...
    def create_scene(self, story_id, title, **kw): ...

Architecture

  • 1 Client = 1 Token = 1 Tenant — no global singleton; multi-tenant callers instantiate one client per token.
  • Pydantic v2 — all API responses validated into typed, frozen schemas.
  • Separate Input schemas*CreateInput (POST) / *UpdateInput (PATCH).
  • Lookup cache — pluggable CacheBackend (NullCache → MemoryCache → DjangoCache).
  • Storage Backend Pattern — Weltenhub-DB is SSoT; consumer apps store UUID only.

Changelog

See CHANGELOG.md.

Links

Download files

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

Source Distribution

iil_weltenfw-0.5.0.tar.gz (40.0 kB view details)

Uploaded Source

Built Distribution

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

iil_weltenfw-0.5.0-py3-none-any.whl (38.3 kB view details)

Uploaded Python 3

File details

Details for the file iil_weltenfw-0.5.0.tar.gz.

File metadata

  • Download URL: iil_weltenfw-0.5.0.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for iil_weltenfw-0.5.0.tar.gz
Algorithm Hash digest
SHA256 70e5b9c5da93046043289d03e074720863b51518844c3b6cc82acd475413d8c1
MD5 1c7cc128f99c47cfc196b4c37e08ecac
BLAKE2b-256 8b57900634a5e56ee2dd964998e85450ad649361f5ac4d46243c17a2c9d4f294

See more details on using hashes here.

Provenance

The following attestation bundles were made for iil_weltenfw-0.5.0.tar.gz:

Publisher: publish.yml on achimdehnert/weltenfw

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

File details

Details for the file iil_weltenfw-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: iil_weltenfw-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 38.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for iil_weltenfw-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc87759daecb7fc3ff7c10fb51705b8c22abf7b6f8376e92585d38ed5ce56226
MD5 e0ecff6bd5ba34e6becac3a9f1c43771
BLAKE2b-256 40009d1073164a8a02d9a5f689e2b5c35c1eefe2a654a151f5d9d9a63859d4e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for iil_weltenfw-0.5.0-py3-none-any.whl:

Publisher: publish.yml on achimdehnert/weltenfw

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

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.0

2 files

0.1.0

2 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