shelfdb 1.1.1__tar.gz → 2.0.0.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. shelfdb-2.0.0.dev0/PKG-INFO +120 -0
  2. shelfdb-2.0.0.dev0/README.md +98 -0
  3. shelfdb-2.0.0.dev0/pyproject.toml +46 -0
  4. {shelfdb-1.1.1 → shelfdb-2.0.0.dev0/src}/shelfdb/__init__.py +2 -0
  5. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/__init__.py +1 -0
  6. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/SKILL.md +90 -0
  7. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/agents/openai.yaml +4 -0
  8. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/api-reference.md +74 -0
  9. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/embedded-mode.md +155 -0
  10. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/getting-started.md +118 -0
  11. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/index.md +93 -0
  12. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/protocol.md +136 -0
  13. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/query-model.md +188 -0
  14. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/security.md +37 -0
  15. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/server-mode.md +181 -0
  16. shelfdb-2.0.0.dev0/src/shelfdb/ai_skill/shelfdb-usage/references/docs/transactions.md +120 -0
  17. shelfdb-2.0.0.dev0/src/shelfdb/cli.py +122 -0
  18. shelfdb-2.0.0.dev0/src/shelfdb/client/__init__.py +38 -0
  19. shelfdb-2.0.0.dev0/src/shelfdb/client/_impl.py +409 -0
  20. shelfdb-2.0.0.dev0/src/shelfdb/log.py +36 -0
  21. shelfdb-2.0.0.dev0/src/shelfdb/protocol/__init__.py +27 -0
  22. shelfdb-2.0.0.dev0/src/shelfdb/protocol/codec.py +32 -0
  23. shelfdb-2.0.0.dev0/src/shelfdb/protocol/payload.py +129 -0
  24. shelfdb-2.0.0.dev0/src/shelfdb/protocol/query.py +22 -0
  25. shelfdb-2.0.0.dev0/src/shelfdb/protocol/schema.py +70 -0
  26. shelfdb-2.0.0.dev0/src/shelfdb/server/__init__.py +10 -0
  27. shelfdb-2.0.0.dev0/src/shelfdb/server/rpc.py +35 -0
  28. shelfdb-2.0.0.dev0/src/shelfdb/server/runtime.py +144 -0
  29. shelfdb-2.0.0.dev0/src/shelfdb/shelf/__init__.py +18 -0
  30. shelfdb-2.0.0.dev0/src/shelfdb/shelf/core.py +349 -0
  31. shelfdb-2.0.0.dev0/src/shelfdb/shelf/normalize.py +26 -0
  32. shelfdb-2.0.0.dev0/src/shelfdb/shelf/query.py +76 -0
  33. shelfdb-2.0.0.dev0/src/shelfdb/shelf/storage/__init__.py +1 -0
  34. shelfdb-2.0.0.dev0/src/shelfdb/shelf/storage/lmdb.py +150 -0
  35. shelfdb-2.0.0.dev0/src/shelfdb/util/__init__.py +1 -0
  36. shelfdb-2.0.0.dev0/src/shelfdb/util/transport.py +31 -0
  37. shelfdb-2.0.0.dev0/src/shelfdb/util/validation.py +45 -0
  38. shelfdb-1.1.1/MANIFEST.in +0 -2
  39. shelfdb-1.1.1/PKG-INFO +0 -85
  40. shelfdb-1.1.1/README.md +0 -70
  41. shelfdb-1.1.1/pyproject.toml +0 -6
  42. shelfdb-1.1.1/setup.cfg +0 -32
  43. shelfdb-1.1.1/shelfdb/server.py +0 -189
  44. shelfdb-1.1.1/shelfdb/shelf.py +0 -282
  45. shelfdb-1.1.1/shelfdb/test_server.py +0 -132
  46. shelfdb-1.1.1/shelfdb/test_shelf.py +0 -249
  47. shelfdb-1.1.1/shelfdb.egg-info/PKG-INFO +0 -85
  48. shelfdb-1.1.1/shelfdb.egg-info/SOURCES.txt +0 -16
  49. shelfdb-1.1.1/shelfdb.egg-info/dependency_links.txt +0 -1
  50. shelfdb-1.1.1/shelfdb.egg-info/entry_points.txt +0 -2
  51. shelfdb-1.1.1/shelfdb.egg-info/requires.txt +0 -4
  52. shelfdb-1.1.1/shelfdb.egg-info/top_level.txt +0 -1
  53. {shelfdb-1.1.1 → shelfdb-2.0.0.dev0}/LICENSE +0 -0
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: shelfdb
3
+ Version: 2.0.0.dev0
4
+ Summary: A tiny documents database for Python
5
+ Keywords: dict,json,database
6
+ Author: Nitipit Nontasuwan
7
+ Author-email: Nitipit Nontasuwan <nitipit@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Dist: cyclopts>=4.10.2
14
+ Requires-Dist: dictify>=4.0.0,<4.1
15
+ Requires-Dist: dill>=0.4.0,<0.5
16
+ Requires-Dist: lmdb>=1.7.3,<2
17
+ Requires-Dist: msgpack>=1.1.2,<2
18
+ Requires-Dist: structlog>=25.1.0,<26
19
+ Requires-Dist: uvloop>=0.22.0,<0.23 ; sys_platform == 'linux'
20
+ Requires-Python: >=3.12
21
+ Description-Content-Type: text/markdown
22
+
23
+ # ShelfDB
24
+
25
+ ShelfDB is a tiny document database for Python that stores JSON-like dictionaries in LMDB.
26
+
27
+ Docs: build and browse the MkDocs site from `docs-src/`.
28
+
29
+ ## Install
30
+
31
+ ```shell
32
+ pip install shelfdb
33
+ ```
34
+
35
+ ## Develop
36
+
37
+ ```shell
38
+ uv sync --dev
39
+ uv run pytest
40
+ uv build
41
+ ```
42
+
43
+ ## Local API
44
+
45
+ Local queries are lazy. Build a query chain and call `.run()` to execute it.
46
+
47
+ ```python
48
+ from datetime import datetime
49
+
50
+ import shelfdb
51
+
52
+ db = shelfdb.open("db")
53
+
54
+ db.shelf("note").put(
55
+ "note-1",
56
+ {
57
+ "title": "Shelf DB",
58
+ "content": "Simple note",
59
+ "created_at": datetime.utcnow().isoformat(),
60
+ },
61
+ ).run()
62
+
63
+ notes = (
64
+ db.shelf("note")
65
+ .filter(lambda item: item[1]["title"] == "Shelf DB")
66
+ .run()
67
+ )
68
+
69
+ print(sorted(notes, key=lambda item: item[1]["created_at"]))
70
+ ```
71
+
72
+ `run()` returns a one-shot iterator for local multi-item queries. Each item has the server-style
73
+ shape `["key", data]`, so use `item[0]` for the key and `item[1]` for the stored document.
74
+
75
+ ## Server
76
+
77
+ Start the asyncio server:
78
+
79
+ ```shell
80
+ shelfdb
81
+ ```
82
+
83
+ Or choose an explicit transport:
84
+
85
+ ```shell
86
+ shelfdb --url tcp://127.0.0.1:17000
87
+ shelfdb --url unix:///tmp/shelfdb.sock
88
+ ```
89
+
90
+ Control server logging with stdlib-integrated structlog:
91
+
92
+ ```shell
93
+ shelfdb --log-level info
94
+ shelfdb --log-level debug
95
+ ```
96
+
97
+ If you use the Python client directly, call `shelfdb.log.configure_logging(...)` first to
98
+ see client-side debug logs as well.
99
+
100
+ ## Network Client
101
+
102
+ RPC queries are also lazy and execute on `.run()`.
103
+
104
+ ```python
105
+ import shelfdb
106
+
107
+
108
+ def main():
109
+ db = shelfdb.connect("tcp://127.0.0.1:17000")
110
+ note = db.shelf("note").key("note-1").first().run()
111
+ print(note)
112
+
113
+
114
+ main()
115
+ ```
116
+
117
+ ## Security
118
+
119
+ The RPC protocol uses Python object deserialization and can transport Python callables.
120
+ Only use the server with trusted local clients.
@@ -0,0 +1,98 @@
1
+ # ShelfDB
2
+
3
+ ShelfDB is a tiny document database for Python that stores JSON-like dictionaries in LMDB.
4
+
5
+ Docs: build and browse the MkDocs site from `docs-src/`.
6
+
7
+ ## Install
8
+
9
+ ```shell
10
+ pip install shelfdb
11
+ ```
12
+
13
+ ## Develop
14
+
15
+ ```shell
16
+ uv sync --dev
17
+ uv run pytest
18
+ uv build
19
+ ```
20
+
21
+ ## Local API
22
+
23
+ Local queries are lazy. Build a query chain and call `.run()` to execute it.
24
+
25
+ ```python
26
+ from datetime import datetime
27
+
28
+ import shelfdb
29
+
30
+ db = shelfdb.open("db")
31
+
32
+ db.shelf("note").put(
33
+ "note-1",
34
+ {
35
+ "title": "Shelf DB",
36
+ "content": "Simple note",
37
+ "created_at": datetime.utcnow().isoformat(),
38
+ },
39
+ ).run()
40
+
41
+ notes = (
42
+ db.shelf("note")
43
+ .filter(lambda item: item[1]["title"] == "Shelf DB")
44
+ .run()
45
+ )
46
+
47
+ print(sorted(notes, key=lambda item: item[1]["created_at"]))
48
+ ```
49
+
50
+ `run()` returns a one-shot iterator for local multi-item queries. Each item has the server-style
51
+ shape `["key", data]`, so use `item[0]` for the key and `item[1]` for the stored document.
52
+
53
+ ## Server
54
+
55
+ Start the asyncio server:
56
+
57
+ ```shell
58
+ shelfdb
59
+ ```
60
+
61
+ Or choose an explicit transport:
62
+
63
+ ```shell
64
+ shelfdb --url tcp://127.0.0.1:17000
65
+ shelfdb --url unix:///tmp/shelfdb.sock
66
+ ```
67
+
68
+ Control server logging with stdlib-integrated structlog:
69
+
70
+ ```shell
71
+ shelfdb --log-level info
72
+ shelfdb --log-level debug
73
+ ```
74
+
75
+ If you use the Python client directly, call `shelfdb.log.configure_logging(...)` first to
76
+ see client-side debug logs as well.
77
+
78
+ ## Network Client
79
+
80
+ RPC queries are also lazy and execute on `.run()`.
81
+
82
+ ```python
83
+ import shelfdb
84
+
85
+
86
+ def main():
87
+ db = shelfdb.connect("tcp://127.0.0.1:17000")
88
+ note = db.shelf("note").key("note-1").first().run()
89
+ print(note)
90
+
91
+
92
+ main()
93
+ ```
94
+
95
+ ## Security
96
+
97
+ The RPC protocol uses Python object deserialization and can transport Python callables.
98
+ Only use the server with trusted local clients.
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.3,<0.12"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "shelfdb"
7
+ version = "2.0.0.dev0"
8
+ description = "A tiny documents database for Python"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "Nitipit Nontasuwan", email = "nitipit@gmail.com" },
15
+ ]
16
+ keywords = ["dict", "json", "database"]
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3.12",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ ]
22
+ dependencies = [
23
+ "cyclopts>=4.10.2",
24
+ "dictify>=4.0.0,<4.1",
25
+ "dill>=0.4.0,<0.5",
26
+ "lmdb>=1.7.3,<2",
27
+ "msgpack>=1.1.2,<2",
28
+ "structlog>=25.1.0,<26",
29
+ "uvloop>=0.22.0,<0.23; platform_system == 'Linux'",
30
+ ]
31
+
32
+ [project.scripts]
33
+ shelfdb = "shelfdb.cli:main"
34
+
35
+ [dependency-groups]
36
+ dev = [
37
+ "dictify>=4.0.0,<4.1",
38
+ "mkdocs>=1.6.1,<2",
39
+ "mkdocs-shadcn>=0.10.4,<0.11",
40
+ "mkdocstrings[python]>=0.29.0,<0.30",
41
+ "pytest>=8.4.2,<9",
42
+ ]
43
+
44
+ [tool.uv.build-backend]
45
+ module-name = "shelfdb"
46
+ module-root = "src"
@@ -1,3 +1,5 @@
1
+ from .client import connect as connect
2
+ from .client import connect_async as connect_async
1
3
  from .shelf import DB
2
4
 
3
5
 
@@ -0,0 +1 @@
1
+ """ShelfDB bundled AI skills."""
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: shelfdb-usage
3
+ description: "ShelfDB developer workflow for running the local server and querying it from sync or async Python clients. Use when Codex needs to write or debug ShelfDB server-mode code, client queries, transactions, logging, or examples that call `shelfdb.connect`, `connect_async`, `.run()`, or `tx.commit()`."
4
+ ---
5
+
6
+ # ShelfDB usage
7
+
8
+ Prefer the simplest mode that fits the task.
9
+
10
+ ## Reference docs
11
+
12
+ - Read `references/docs/` for mirrored ShelfDB documentation when you need the full narrative docs.
13
+ - Prefer the most specific page for the task: `server-mode.md`, `query-model.md`, `transactions.md`, and `security.md` are the usual first reads.
14
+
15
+ ## Choose the mode
16
+
17
+ - Use embedded mode with `shelfdb.open(...)` when the process can access the LMDB directory directly.
18
+ - Use server mode only when a separate process or multi-client access is required.
19
+
20
+ ## Start the server
21
+
22
+ - Run `shelfdb` for the default TCP server on `127.0.0.1:17000` with the `db/` directory.
23
+ - Use `shelfdb --url tcp://HOST:PORT` or `shelfdb --url unix:///path/to/socket.sock` when an explicit transport is needed.
24
+ - Keep the server on loopback or a Unix socket. Treat the RPC layer as trusted-local only.
25
+
26
+ ## Connect from Python
27
+
28
+ - Use `shelfdb.connect(url)` in sync code.
29
+ - Use `await shelfdb.connect_async(url)` in async code.
30
+ - Await only `connect_async(...)`, `query.run()` in async code, and `tx.commit()`.
31
+
32
+ ## Build queries lazily
33
+
34
+ - Chain query methods and execute only with `.run()`.
35
+ - Reuse the same query object when you need to run the same pipeline again.
36
+ - Use the same query style in embedded and remote code.
37
+
38
+ Available operations:
39
+
40
+ - Read: `key`, `key_range`, `keys_in`, `filter`, `slice`, `first`, `count`
41
+ - Write: `put`, `put_many`, `update`, `replace`, `edit`, `delete`
42
+
43
+ ## Handle results correctly
44
+
45
+ - Local multi-item `.run()` returns a one-shot iterator of `['key', data]` items; wrap it in `list(...)` if you need reuse.
46
+ - Remote results are normalized into plain Python values.
47
+ - `first()` returns one item or `None`.
48
+ - `put_many()` returns `None`.
49
+
50
+ ## Respect batch and transaction behavior
51
+
52
+ - Pass iterables to `put_many()` and `keys_in()`, but assume the client materializes them before send.
53
+ - `keys_in()` keeps the requested key order and may repeat keys.
54
+ - Use `client.transaction(write=True)` for remote batches; queue queries with `.run()` and send them with `tx.commit()`.
55
+ - Use `db.transaction(write=True)` for embedded atomic writes; inside a local transaction, use `tx.shelf(...)`, not `db.shelf(...)`.
56
+
57
+ ## Safety checks
58
+
59
+ - Keep callable `filter()` and `edit()` functions simple and trusted; the protocol uses `dill`.
60
+ - Configure debug logs with `shelfdb.log.configure_logging("debug")` when diagnosing client or server behavior.
61
+ - Do not expose the server to untrusted networks.
62
+
63
+ ## Minimal patterns
64
+
65
+ ```python
66
+ import shelfdb
67
+
68
+ client = shelfdb.connect("tcp://127.0.0.1:17000")
69
+ note = client.shelf("note").key("note-1").first().run()
70
+ ```
71
+
72
+ ```python
73
+ import asyncio
74
+ import shelfdb
75
+
76
+
77
+ async def main():
78
+ client = await shelfdb.connect_async("unix:///tmp/shelfdb.sock")
79
+ rows = await client.shelf("note").keys_in(["note-1", "note-2"]).run()
80
+ print(rows)
81
+
82
+
83
+ asyncio.run(main())
84
+ ```
85
+
86
+ ```python
87
+ tx = client.transaction(write=True)
88
+ tx.shelf("note").put("note-1", {"title": "ShelfDB"}).run()
89
+ tx.commit()
90
+ ```
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "ShelfDB Usage"
3
+ short_description: "ShelfDB server/client usage guide"
4
+ default_prompt: "Use $shelfdb-usage to help with ShelfDB server startup, client queries, and remote transactions."
@@ -0,0 +1,74 @@
1
+ # API Reference
2
+
3
+ This page is the generated reference for the public Python modules.
4
+
5
+ Use the narrative pages first if you are learning ShelfDB. Come back here when you want exact
6
+ signatures, annotations, class members, or module-level details.
7
+
8
+ ## Protocol
9
+
10
+ Start with the [Protocol](protocol.md) page for the conceptual overview and module guide.
11
+
12
+ The sections below show the public `shelfdb.protocol` package surface and the protocol submodules.
13
+
14
+ ::: shelfdb.protocol
15
+
16
+ ### `shelfdb.protocol.schema`
17
+
18
+ Typed protocol shapes and schema models.
19
+
20
+ ::: shelfdb.protocol.schema
21
+
22
+ ### `shelfdb.protocol.query`
23
+
24
+ Serialized query-step builders.
25
+
26
+ ::: shelfdb.protocol.query
27
+
28
+ ### `shelfdb.protocol.payload`
29
+
30
+ Request and response payload helpers.
31
+
32
+ ::: shelfdb.protocol.payload
33
+
34
+ ### `shelfdb.protocol.codec`
35
+
36
+ Byte-level request and response codecs.
37
+
38
+ ::: shelfdb.protocol.codec
39
+
40
+ ## Package
41
+
42
+ Top-level package exports such as `open()`, `connect()`, and `connect_async()`.
43
+
44
+ ::: shelfdb
45
+
46
+ ## Local database
47
+
48
+ Local database, query, and result classes.
49
+
50
+ ::: shelfdb.shelf
51
+
52
+ ## Client
53
+
54
+ Sync and async remote client types.
55
+
56
+ ::: shelfdb.client
57
+
58
+ ## Server
59
+
60
+ Programmatic server type for running ShelfDB over TCP or a Unix socket.
61
+
62
+ ::: shelfdb.server
63
+
64
+ ## CLI
65
+
66
+ CLI entry points and server configuration helpers.
67
+
68
+ ::: shelfdb.cli
69
+
70
+ ## Logging
71
+
72
+ Logging helpers for configuring ShelfDB debug output.
73
+
74
+ ::: shelfdb.log
@@ -0,0 +1,155 @@
1
+ # Embedded Mode
2
+
3
+ Use `shelfdb.open()` when you want ShelfDB as an embedded database inside your Python process.
4
+
5
+ This is the default way to use the project: your Python process talks directly to LMDB and no
6
+ separate server is required.
7
+
8
+ ## Open a database
9
+
10
+ ```python
11
+ import shelfdb
12
+
13
+ db = shelfdb.open("db")
14
+ ```
15
+
16
+ `db` is a `shelfdb.DB` object.
17
+
18
+ ## Choose a shelf
19
+
20
+ A shelf is a named collection of keyed documents.
21
+
22
+ ```python
23
+ notes = db.shelf("note")
24
+ users = db.shelf("user")
25
+ ```
26
+
27
+ Each shelf name is independent, so you can organize documents by purpose.
28
+
29
+ ## Read data
30
+
31
+ Read everything in a shelf:
32
+
33
+ ```python
34
+ all_notes = db.shelf("note").run()
35
+ print(list(all_notes))
36
+ ```
37
+
38
+ Read one item by key:
39
+
40
+ ```python
41
+ note = db.shelf("note").key("note-1").first().run()
42
+ ```
43
+
44
+ Filter matching items:
45
+
46
+ ```python
47
+ matching = list(db.shelf("note").filter(lambda item: item[1]["title"] == "updated").run())
48
+ ```
49
+
50
+ Range and slice:
51
+
52
+ ```python
53
+ selected = list(
54
+ db.shelf("note")
55
+ .key_range("note-1", "note-5")
56
+ .slice(0, 5)
57
+ .run()
58
+ )
59
+ ```
60
+
61
+ Fetch exact keys:
62
+
63
+ ```python
64
+ picked = list(db.shelf("note").keys_in(["note-1", "note-3"]).run())
65
+ ```
66
+
67
+ If you need custom ordering, sort the returned Python values yourself after `.run()`.
68
+
69
+ Count matches:
70
+
71
+ ```python
72
+ count = db.shelf("note").count().run()
73
+ ```
74
+
75
+ ## Write data
76
+
77
+ Insert or replace one document:
78
+
79
+ ```python
80
+ db.shelf("note").put("note-1", {"title": "hello"}).run()
81
+ db.shelf("note").put("note-1", {"title": "updated"}).run()
82
+ ```
83
+
84
+ Write many documents:
85
+
86
+ ```python
87
+ db.shelf("note").put_many(
88
+ [
89
+ ("note-1", {"title": "hello"}),
90
+ ("note-2", {"title": "world"}),
91
+ ]
92
+ ).run()
93
+ ```
94
+
95
+ Merge fields into existing documents:
96
+
97
+ ```python
98
+ db.shelf("note").key("note-1").update({"views": 1}).run()
99
+ ```
100
+
101
+ Replace a full document:
102
+
103
+ ```python
104
+ db.shelf("note").key("note-1").replace({"title": "replaced"}).run()
105
+ ```
106
+
107
+ Transform with a function:
108
+
109
+ ```python
110
+ db.shelf("note").key("note-1").edit(
111
+ lambda item: {"title": item[1]["title"], "status": "published"}
112
+ ).run()
113
+ ```
114
+
115
+ Delete matching items:
116
+
117
+ ```python
118
+ db.shelf("note").key("note-1").delete().run()
119
+ ```
120
+
121
+ `update()`, `replace()`, and `edit()` require an existing selection. If nothing matches, they
122
+ raise an error instead of silently creating a new document. All write queries run atomically by
123
+ default, even outside `db.transaction(write=True)`; use an explicit write transaction when you
124
+ need multiple queries to commit together. `delete()` is safe on a missing key and returns an
125
+ empty result. `put_many()` writes multiple documents and returns `None`.
126
+
127
+ Embedded multi-item `run()` results are one-shot iterators.
128
+
129
+ ## Result types
130
+
131
+ Embedded execution uses these main types:
132
+
133
+ - `shelfdb.DB` for the database
134
+ - `shelfdb.shelf.ShelfQuery` for lazy embedded query builders
135
+ - one-shot iterators from `run()` for executed selections
136
+
137
+ Each yielded item uses the server-style shape `["key", {"title": "example"}]`.
138
+
139
+ ## Close the database
140
+
141
+ When you are done with the embedded database:
142
+
143
+ ```python
144
+ db.close()
145
+ ```
146
+
147
+ ## Transactions
148
+
149
+ For consistent reads and atomic writes, use `with db.transaction(...) as tx:` and create
150
+ transaction-scoped queries with `tx.shelf(...)`.
151
+
152
+ Inside the block, embedded `.run()` calls execute immediately. Remote client transactions queue
153
+ their steps until `tx.commit()`.
154
+
155
+ See [Transactions](transactions.md) for the full behavior and examples.