Skip to main content

Async-first nested storage with dot-path access and atomic writes — supports JSON, TOML, YAML, and TOON

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
YAML YAML .yaml Human-friendly configs
TOON TOON .toon LLM input — compact, token-efficient

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())

YAML

import asyncio
from nestio import YAML

async def main():
    cfg = YAML("data/config.yaml")

    await cfg.set("server.host", "localhost")
    await cfg.set("server.port", 8080)
    await cfg.set("tags", ["web", "api"])

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

    await cfg.append("tags", "async")
    await cfg.update("server", {"timeout": 30})
    await cfg.delete("server.port")

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, YAML, and TOON all share the same interface.

JSON(path) / TOML(path) / YAML(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")
cfg   = YAML("path/to/file.yaml")
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.2.0.tar.gz (9.4 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.2.0-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for nestio-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ba647821987381e46154a5e06df3f001b2c0985f1568bcab393819c1998ec24c
MD5 b3e0ad6c665056bcb1242934da3505af
BLAKE2b-256 7083214a6d7dd711cd6ffd01d48c8d6906e5f436405d21269c7f80e99418da22

See more details on using hashes here.

File details

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

File metadata

  • Download URL: nestio-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8ebcae2961d64cebf25188e25abb5b7bb0224abb9b203113f06f02972d31fe48
MD5 f308aeb92e7b7e2fde4abd4bb82ddaef
BLAKE2b-256 7e98354cbe8fecc8a287ab98676c94b4267acfb6e162938f9010c4534887274b

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