Skip to content

Canadian-Light-Source/kv-dict

Repository files navigation

CI

kv-dict

KV backed dictionary, similar to RedisJSONDict

Install Package

  • pip: pip install kv-dict
  • uv: uv add kv-dict
    • add --optional FEATURE to add as an optional dependency
  • pixi: pixi add --pypi kv-dict
    • add --feature FEATURE to add as an optional dependency

Development

This project uses uv for managing project dependencies. Installation instructions may be found here.

git clone https://github.com/Canadian-Light-Source/kv-dict.git
cd kv-dict
uv sync --all-extras

Remote Mapping + In-Memory Backend Example

Run a basic RemoteKVMapping flow backed by InMemoryAsyncBackend:

uv run python examples/remote_mapping_in_memory_example.py

Remote Mapping + Redis/Dragonfly Backend Example

Run a basic RemoteKVMapping flow backed by a Redis-compatible server:

uv run python examples/remote_mapping_redis_example.py

Note

In the devcontainer compose setup, the Redis-compatible service hostname is redis.

Remote Mapping + PostgreSQL Backend Example

Run a basic RemoteKVMapping flow backed by PostgreSQL:

uv run python examples/remote_mapping_postgres_example.py

Note

In the devcontainer compose setup, PostgreSQL is available on the internal hostname/port postgres:5432.

Remote Mapping + NATS JetStream KV Backend Example

Run a basic RemoteKVMapping flow backed by NATS JetStream KV:

uv run python examples/remote_mapping_nats_example.py

Important

This example uses create_bucket=False (production-style). Ensure the kv_dict bucket already exists.

Note

In the devcontainer compose setup, NATS is also available to host-side tools at nats://127.0.0.1:14222.

Watch the changes in the NATS KV with the CLI client:

nats -s localhost:14222 kv watch kv_dict
Create the kv_dict bucket locally (for testing)

Run this once before executing the NATS example:

uv run python - <<'PY'
import asyncio
import nats


async def main() -> None:
  nc = await nats.connect(servers=["nats://nats:4222"])
  try:
    js = nc.jetstream()
    try:
      await js.key_value("kv_dict")
      print("Bucket already exists: kv_dict")
    except Exception:
      await js.create_key_value(bucket="kv_dict")
      print("Created bucket: kv_dict")
  finally:
    await nc.close()


asyncio.run(main())
PY

Differences from Python dict

RemoteKVMapping is intentionally dict-like, but not a byte-for-byte replacement of the built-in dict behavior.

Key behavioral differences

  • Iteration order is sorted by key, not insertion order.
  • Values are persisted through backend round-trips, so operations are not purely in-memory.
  • Nested dict and list mutations are write-through.
  • Mutable non-dict/non-list values are not automatically write-through.

Missing / non-parity APIs

  • fromkeys() is not implemented.

Practical guidance

Warning

RemoteKVMapping is backend-backed, not purely in-memory. Avoid relying on insertion-order behavior and reassignment-free updates for mutable non-list, non-dict nested values.

  • Treat this mapping as a backend-backed structure, not an in-memory object.
  • For nested non-dict updates, reassign the modified value to persist changes.
  • If strict insertion-order semantics are required, do not rely on iteration order from RemoteKVMapping.

Dict parity roadmap

  • Implement copy() semantics for backend-backed snapshots.
  • Implement in-place dict union operator (|=).
  • Implement dict union operator (|).
  • Implement fromkeys() with explicit persistence semantics.
  • Add write-through wrappers for list operations.
  • Add write-through wrappers for additional mutable container types (if required).
  • Decide and document stable ordering strategy (sorted vs insertion-order).
  • Add dedicated parity tests against a reference dict behavior matrix.

About

KV backed dictionary, similar to RedisJSONDict

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors