Skip to main content

Async-first nested JSON/TOML storage with dot-path access and atomic writes

Project description

nestio

Async-first nested storage with dot-path access and atomic writes.

nestio lets you read and write deeply nested data files using simple dot-path keys — no manual file handling, no race conditions, no boilerplate. Supports multiple file formats, with more on the way.


Installation

pip install nestio

Supported Formats

Format Class File ext Best for
JSON Json .json General purpose, APIs, configs
TOML Toml .toml Configuration files
TOON Toon .toon LLM input — compact, token-efficient
YAML Yaml .yaml (coming soon)

Quickstart

JSON

import asyncio
from nestio import Json

async def main():
    db = Json("data/config.json")

    await db.set("user.name", "Alice")
    await db.set("user.settings.theme", "dark")
    await db.set("user.scores", [])

    name = await db.get("user.name")            # "Alice"
    theme = await db.get("user.settings.theme") # "dark"

    await db.append("user.scores", 42)
    await db.update("user.settings", {"language": "en"})
    await db.delete("user.settings.theme")

asyncio.run(main())

TOML

import asyncio
from nestio import Toml

async def main():
    cfg = Toml("data/config.toml")

    await cfg.set("server.host", "localhost")
    await cfg.set("server.port", 8080)

    host = await cfg.get("server.host") # "localhost"

    await cfg.update("server", {"port": 9090, "debug": True})
    await cfg.delete("server.host")

asyncio.run(main())

TOON

TOON (Token-Oriented Object Notation) is a compact, human-readable format designed for LLM input. It uses YAML-style indentation for nested objects and CSV-style rows for uniform arrays — achieving up to 40% fewer tokens than JSON while maintaining full round-trip fidelity.

import asyncio
from nestio import Toon

async def main():
    store = Toon("data/context.toon")

    await store.set("context.task", "Our favorite hikes")
    await store.set("context.location", "Boulder")
    await store.set("friends", ["ana", "luis", "sam"])

    task = await store.get("context.task") # "Our favorite hikes"

    await store.append("logs", "started")
    await store.update("context", {"season": "spring_2025"})
    await store.delete("context.location")

asyncio.run(main())

A .toon file produced by nestio looks like this:

context:
  task: Our favorite hikes
  season: spring_2025
friends[3]: ana,luis,sam
hikes[3]{id,name,distanceKm,wasSunny}:
  1,Blue Lake Trail,7.5,true
  2,Ridge Overlook,9.2,false
  3,Wildflower Loop,5.1,true

API

All methods are async and must be awaited. Json, Toml, and Toon all share the same interface.

Json(path) / Toml(path) / Toon(path)

Creates a storage instance pointing to a file. The file and any parent directories are created automatically on first write.

db    = Json("path/to/file.json")
cfg   = Toml("path/to/file.toml")
store = Toon("path/to/file.toon")

get(path, default=None)

Returns the value at the given dot-path, or default if it doesn't exist.

value = await db.get("server.host", default="localhost")

set(path, value)

Sets the value at the given dot-path. Creates intermediate dicts as needed.

await db.set("server.port", 8080)

delete(path)

Removes the key at the given dot-path. Does nothing if the key doesn't exist.

await db.delete("server.port")

append(path, value)

Appends a value to a list at the given dot-path. Creates the list if it doesn't exist yet.

await db.append("logs", {"level": "info", "msg": "started"})

update(path, new_data)

Deep-merges a dict into the value at the given dot-path. Nested keys are merged recursively — existing keys not in new_data are preserved.

await db.update("config", {"retries": 3, "timeout": 30})

How it works

  • Dot-path access — keys like "a.b.c" resolve through nested dicts automatically.
  • Atomic writes — every save writes to a temp file first, then uses os.replace() to swap it in. Your file is never left in a half-written state.
  • Per-key locking — concurrent writes to the same path are serialized with asyncio.Lock, while independent paths can write in parallel. Locks are cleaned up automatically after a TTL.

Requirements


License

MIT © MrBaconHat

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

nestio-0.1.1.tar.gz (6.3 kB view details)

Uploaded Source

Built Distribution

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

nestio-0.1.1-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

File details

Details for the file nestio-0.1.1.tar.gz.

File metadata

  • Download URL: nestio-0.1.1.tar.gz
  • Upload date:
  • Size: 6.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for nestio-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7e2a448f30c80d731d9fa0be09273ec6a274c534471da86c2377eb8ab60811f0
MD5 1c5174df57b358c83d29ffc6f80306d1
BLAKE2b-256 89d99154a31a070e6412fad271cf8dcd47bb9ac633c817d3c55f49691f5373de

See more details on using hashes here.

File details

Details for the file nestio-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: nestio-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 7.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for nestio-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a5c0c320c469f32a1c8b91a12808733cc5e0785cde6f1f57e0d5acf5b6c89dfb
MD5 2c85f89e88d25c9c42abb5591c432588
BLAKE2b-256 d3c33e47fa47158e653cadf694ab570aa24cfafa60aa83a74bdb7109cc3cf469

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