onlyworlds (Python)
OnlyWorlds is an open standard for worldbuilding data: 22 element types (characters, locations, events, laws and the rest) that any tool can read and write. This is a Python client for its API, and a reader and writer for OnlyWorlds world folders (a world as a folder of JSON files). Python 3.12+, no runtime dependencies.
Install
pip install onlyworlds
The newest unreleased code: pip install git+https://github.com/OnlyWorlds/python-sdk.
First run
Moppetopia is a public demo world. Its read-only key, 0000000001, needs no account:
from onlyworlds import Client
client = Client("0000000001")
print(client.get_world()["name"])
for c in client.list_page("character", filter={"name__icontains": "fluffington"})["data"]:
print(" ", c["name"])
Moppetopia
Admiral Fluffington
Your own world
Create a world at onlyworlds.com; its keys are on the world's page. A new key is shown once, so copy it then.
- An
ow_r_key reads, with no PIN:Client("ow_r_…"). - An
ow_w_key reads and writes. Writes also send a PIN:Client("ow_w_…", "…"). - For code that writes, give it its own agent seat, a key for one tool or script. The seat's key and its
ow_s_secret (passed as the PIN) work in one world, and you can remove them without touching your account PIN.
Elements are plain dicts:
writer = Client("ow_w_…", "ow_s_…")
peak = writer.create("location", {"name": "Dragon Peak"})
writer.patch("location", peak["id"], {"supertype": "Mountain"})
for character in client.iter_elements("character", expand=["species"]):
print(character["name"])
World folders
A world folder is one JSON file per element, in the world folder format. Atlas, the OnlyWorlds editor, reads and writes the same format.
from onlyworlds import export_world, read_folder
export_world("moppetopia", api_key="0000000001")
folder = read_folder("moppetopia")
print(folder.world["name"], len(folder.elements), "elements")
write_folder(root, world, elements) writes a folder from a world dict and a dict of element lists by type. Reading never changes a file, and a file without an id is skipped and left alone.
To send a folder's edits back, keep a copy exported before you edited, then push the difference:
from onlyworlds import push
result = push("moppetopia-before", "moppetopia", api_key="ow_w_…", pin="ow_s_…", log_path="push.jsonl")
push sends only the fields that changed, retries what the server asks it to retry, checks that what came back is what it sent, and logs every write, so running it again skips what already landed. dry_run=True shows the plan without sending it.
Errors
A failed call raises ApiError with the API's code, param (the field that failed) and doc_url, and flags for the cases you handle differently: is_validation_error, is_auth_error, is_not_author, is_owner_only, is_id_conflict, is_resync_required, is_busy.
The change feed
walk = client.walk_changes(saved_cursor) # None for everything
for op in walk:
... # op["op"] is "upsert" or "delete"
saved_cursor = walk.cursor # opaque: keep it, don't parse it
Schema
The 22 element types and each field's kind are generated from the published schema distribution; onlyworlds.SCHEMA_VERSION and onlyworlds.SCHEMA_DIST_TAG say which one. The package's own version doesn't track the schema's.
Not yet: typed element models, the account routes, a snapshot writer.
Develop
uv sync
uv run pytest -q
uv run ruff check . && uv run mypy --strict src
uv run python codegen/generate_schema.py --check
Three groups of tests run only when asked:
OW_CONFORMANCE_FIXTURE=<path>: the folder-format conformance fixture from the Atlas repo.OW_OPENAPI=https://www.onlyworlds.com/api/v2/openapi.json(or a saved copy): checks the client's routes, parameters and fields against the API's own OpenAPI document.OW_LIVE=1: read-only calls against the demo world.
License
MIT. See LICENSE.
Metadata
Release files for onlyworlds 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| onlyworlds-0.1.0.tar.gz | 128.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| onlyworlds-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 162.4 kB
Release files / onlyworlds-0.1.0.tar.gz
| Download URL | onlyworlds-0.1.0.tar.gz |
|---|---|
| Size | 128.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6b2ec7d26fdddd8e5db9875fb4fe5296a3424dfbeffa9b9c16e473fc813ab4da
|
|
BLAKE2b-256 checksum How to use checksums |
eee190ed17f973ef9cc68c1ffff2f8dceb5fa39c3c118d089f816262fa5afe63
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / onlyworlds-0.1.0-py3-none-any.whl
| Download URL | onlyworlds-0.1.0-py3-none-any.whl |
|---|---|
| Size | 34.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a0d30ba160f195ba4e8201a40edebd352639db4b829c6af27a106a122182fc12
|
|
BLAKE2b-256 checksum How to use checksums |
0d39931b09b7e8539a222813ce77ef2d100c8ef00bc6889420069b18a84059df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|