cuttledb 0.6.0__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.
- cuttledb-0.6.0/PKG-INFO +110 -0
- cuttledb-0.6.0/README.md +82 -0
- cuttledb-0.6.0/cuttledb/__init__.py +1351 -0
- cuttledb-0.6.0/cuttledb/cluster.py +223 -0
- cuttledb-0.6.0/cuttledb/replicate.py +239 -0
- cuttledb-0.6.0/cuttledb.egg-info/PKG-INFO +110 -0
- cuttledb-0.6.0/cuttledb.egg-info/SOURCES.txt +32 -0
- cuttledb-0.6.0/cuttledb.egg-info/dependency_links.txt +1 -0
- cuttledb-0.6.0/cuttledb.egg-info/requires.txt +3 -0
- cuttledb-0.6.0/cuttledb.egg-info/top_level.txt +1 -0
- cuttledb-0.6.0/pyproject.toml +46 -0
- cuttledb-0.6.0/setup.cfg +4 -0
- cuttledb-0.6.0/tests/test_audit_log.py +140 -0
- cuttledb-0.6.0/tests/test_cluster.py +116 -0
- cuttledb-0.6.0/tests/test_constraints.py +187 -0
- cuttledb-0.6.0/tests/test_datetime.py +171 -0
- cuttledb-0.6.0/tests/test_exec_kernel.py +1219 -0
- cuttledb-0.6.0/tests/test_groupby.py +148 -0
- cuttledb-0.6.0/tests/test_hnsw_wire.py +587 -0
- cuttledb-0.6.0/tests/test_http_health.py +123 -0
- cuttledb-0.6.0/tests/test_join.py +149 -0
- cuttledb-0.6.0/tests/test_matmul_wire.py +199 -0
- cuttledb-0.6.0/tests/test_max_conn.py +123 -0
- cuttledb-0.6.0/tests/test_metrics.py +148 -0
- cuttledb-0.6.0/tests/test_multi_token.py +136 -0
- cuttledb-0.6.0/tests/test_security_edge.py +200 -0
- cuttledb-0.6.0/tests/test_slow_log_file.py +193 -0
- cuttledb-0.6.0/tests/test_smoke.py +1000 -0
- cuttledb-0.6.0/tests/test_stress.py +655 -0
- cuttledb-0.6.0/tests/test_tls.py +209 -0
- cuttledb-0.6.0/tests/test_update_row.py +95 -0
- cuttledb-0.6.0/tests/test_v0517_audit.py +369 -0
- cuttledb-0.6.0/tests/test_wal.py +265 -0
- cuttledb-0.6.0/tests/test_wal_mid_tx.py +129 -0
cuttledb-0.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cuttledb
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: CuttleDB Python client — embedded realtime database with vector search, WAL durability, and event streaming. One self-contained binary.
|
|
5
|
+
Author: CuttleDB contributors
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/mikedconcepcion/CuttleDB
|
|
8
|
+
Project-URL: Source, https://github.com/mikedconcepcion/CuttleDB
|
|
9
|
+
Project-URL: Issues, https://github.com/mikedconcepcion/CuttleDB/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/mikedconcepcion/CuttleDB/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: database,local-first,vector-search,embeddings,knn,hnsw,bm25,full-text,real-time,change-feed,wasm,embedded,agents,rag,redis,sqlite
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Database :: Database Engines/Servers
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
28
|
+
|
|
29
|
+
# cuttledb — Python client for CuttleDB
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install cuttledb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from cuttledb import CuttleDB, ColType
|
|
37
|
+
|
|
38
|
+
with CuttleDB.connect("127.0.0.1", 7780) as db:
|
|
39
|
+
hid = db.open()
|
|
40
|
+
tid = db.create(hid, "memory", [
|
|
41
|
+
("text", ColType.STRING),
|
|
42
|
+
("embedding", ColType.VEC, 768),
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
db.insert(hid, tid, ["hello world", [0.1] * 768])
|
|
46
|
+
|
|
47
|
+
hits = db.knn(hid, tid, col=1, k=5, query=[0.1] * 768)
|
|
48
|
+
for row_id, score in hits:
|
|
49
|
+
print(score, db.get(hid, tid, row_id))
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
See the full feature set and use cases in the
|
|
53
|
+
[CuttleDB project README](https://github.com/mikedconcepcion/CuttleDB#readme).
|
|
54
|
+
|
|
55
|
+
## API surface
|
|
56
|
+
|
|
57
|
+
| Method | Returns | Notes |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `CuttleDB.connect(host, port)` | `CuttleDB` | classmethod, returns connected client; use as context manager |
|
|
60
|
+
| `db.open()` | `int` | new handle id |
|
|
61
|
+
| `db.create(hid, name, [(col, type), …])` | `int` | new table id |
|
|
62
|
+
| `db.insert(hid, tid, values)` | `int` | new row id |
|
|
63
|
+
| `db.insert_batch(hid, tid, rows)` | `list[int]` | pipelined; bulk-load 1000 rows in <40ms |
|
|
64
|
+
| `db.get(hid, tid, row_id)` | `list[str]` | values returned as strings (no type coercion) |
|
|
65
|
+
| `db.count(hid, tid)` | `int` | O(1) |
|
|
66
|
+
| `db.sum / .min / .max(hid, tid, col)` | `float` | SUM O(1); MIN/MAX SIMD |
|
|
67
|
+
| `db.fcount_gt(hid, tid, col, threshold)` | `int` | SIMD predicate scan |
|
|
68
|
+
| `db.select_gt(hid, tid, col, threshold)` | `list[list[str]]` | all matching rows |
|
|
69
|
+
| `db.knn(hid, tid, col, k, query)` | `list[(row_id, score)]` | cosine, sorted desc |
|
|
70
|
+
| `db.delete(hid, tid, row_id)` | `bool` | swap-with-last |
|
|
71
|
+
| `db.save(hid, path)` / `db.load(path)` | `str` / `int` | binary snapshot |
|
|
72
|
+
| `db.sub(hid, tid)` / `db.unsub(hid, tid)` | `str` | register/cancel push subscription |
|
|
73
|
+
| `db.poll_events(timeout)` | `list[Event]` | drain pending push events |
|
|
74
|
+
| `with db.stream_events() as events: …` | iterator | generator-style event loop |
|
|
75
|
+
| `db.log(hid, tid, since=0)` | `(cursor, events)` | per-table change ring buffer |
|
|
76
|
+
| `db.ping() / db.hello() / db.info() / db.stats(...)` | `str` / `dict` | server meta |
|
|
77
|
+
|
|
78
|
+
All methods raise `CuttleDBError` on `-ERR …` responses or protocol violations.
|
|
79
|
+
|
|
80
|
+
## Concurrency model
|
|
81
|
+
|
|
82
|
+
`CuttleDB` is **thread-compatible but not thread-safe** — calls serialize
|
|
83
|
+
through an internal lock, so multiple threads on one connection won't
|
|
84
|
+
corrupt the wire protocol, but they will not run in parallel either. For
|
|
85
|
+
parallel workloads, open one connection per worker. The server is
|
|
86
|
+
multi-client (thread-per-connection) so this scales.
|
|
87
|
+
|
|
88
|
+
## Subscriptions without a background thread
|
|
89
|
+
|
|
90
|
+
The Python SDK is intentionally single-threaded. For real-time push:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
db.sub(hid, tid)
|
|
94
|
+
|
|
95
|
+
# blocking loop with a poll interval
|
|
96
|
+
while True:
|
|
97
|
+
for evt in db.poll_events(timeout=1.0):
|
|
98
|
+
handle(evt)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Or the generator form:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
with db.stream_events(poll_interval=0.1) as events:
|
|
105
|
+
for evt in events:
|
|
106
|
+
handle(evt)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
If you need true background push (callbacks fired from a reader thread),
|
|
110
|
+
wrap `poll_events` in your own thread — it's three lines.
|
cuttledb-0.6.0/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# cuttledb — Python client for CuttleDB
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
pip install cuttledb
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from cuttledb import CuttleDB, ColType
|
|
9
|
+
|
|
10
|
+
with CuttleDB.connect("127.0.0.1", 7780) as db:
|
|
11
|
+
hid = db.open()
|
|
12
|
+
tid = db.create(hid, "memory", [
|
|
13
|
+
("text", ColType.STRING),
|
|
14
|
+
("embedding", ColType.VEC, 768),
|
|
15
|
+
])
|
|
16
|
+
|
|
17
|
+
db.insert(hid, tid, ["hello world", [0.1] * 768])
|
|
18
|
+
|
|
19
|
+
hits = db.knn(hid, tid, col=1, k=5, query=[0.1] * 768)
|
|
20
|
+
for row_id, score in hits:
|
|
21
|
+
print(score, db.get(hid, tid, row_id))
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
See the full feature set and use cases in the
|
|
25
|
+
[CuttleDB project README](https://github.com/mikedconcepcion/CuttleDB#readme).
|
|
26
|
+
|
|
27
|
+
## API surface
|
|
28
|
+
|
|
29
|
+
| Method | Returns | Notes |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `CuttleDB.connect(host, port)` | `CuttleDB` | classmethod, returns connected client; use as context manager |
|
|
32
|
+
| `db.open()` | `int` | new handle id |
|
|
33
|
+
| `db.create(hid, name, [(col, type), …])` | `int` | new table id |
|
|
34
|
+
| `db.insert(hid, tid, values)` | `int` | new row id |
|
|
35
|
+
| `db.insert_batch(hid, tid, rows)` | `list[int]` | pipelined; bulk-load 1000 rows in <40ms |
|
|
36
|
+
| `db.get(hid, tid, row_id)` | `list[str]` | values returned as strings (no type coercion) |
|
|
37
|
+
| `db.count(hid, tid)` | `int` | O(1) |
|
|
38
|
+
| `db.sum / .min / .max(hid, tid, col)` | `float` | SUM O(1); MIN/MAX SIMD |
|
|
39
|
+
| `db.fcount_gt(hid, tid, col, threshold)` | `int` | SIMD predicate scan |
|
|
40
|
+
| `db.select_gt(hid, tid, col, threshold)` | `list[list[str]]` | all matching rows |
|
|
41
|
+
| `db.knn(hid, tid, col, k, query)` | `list[(row_id, score)]` | cosine, sorted desc |
|
|
42
|
+
| `db.delete(hid, tid, row_id)` | `bool` | swap-with-last |
|
|
43
|
+
| `db.save(hid, path)` / `db.load(path)` | `str` / `int` | binary snapshot |
|
|
44
|
+
| `db.sub(hid, tid)` / `db.unsub(hid, tid)` | `str` | register/cancel push subscription |
|
|
45
|
+
| `db.poll_events(timeout)` | `list[Event]` | drain pending push events |
|
|
46
|
+
| `with db.stream_events() as events: …` | iterator | generator-style event loop |
|
|
47
|
+
| `db.log(hid, tid, since=0)` | `(cursor, events)` | per-table change ring buffer |
|
|
48
|
+
| `db.ping() / db.hello() / db.info() / db.stats(...)` | `str` / `dict` | server meta |
|
|
49
|
+
|
|
50
|
+
All methods raise `CuttleDBError` on `-ERR …` responses or protocol violations.
|
|
51
|
+
|
|
52
|
+
## Concurrency model
|
|
53
|
+
|
|
54
|
+
`CuttleDB` is **thread-compatible but not thread-safe** — calls serialize
|
|
55
|
+
through an internal lock, so multiple threads on one connection won't
|
|
56
|
+
corrupt the wire protocol, but they will not run in parallel either. For
|
|
57
|
+
parallel workloads, open one connection per worker. The server is
|
|
58
|
+
multi-client (thread-per-connection) so this scales.
|
|
59
|
+
|
|
60
|
+
## Subscriptions without a background thread
|
|
61
|
+
|
|
62
|
+
The Python SDK is intentionally single-threaded. For real-time push:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
db.sub(hid, tid)
|
|
66
|
+
|
|
67
|
+
# blocking loop with a poll interval
|
|
68
|
+
while True:
|
|
69
|
+
for evt in db.poll_events(timeout=1.0):
|
|
70
|
+
handle(evt)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Or the generator form:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
with db.stream_events(poll_interval=0.1) as events:
|
|
77
|
+
for evt in events:
|
|
78
|
+
handle(evt)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If you need true background push (callbacks fired from a reader thread),
|
|
82
|
+
wrap `poll_events` in your own thread — it's three lines.
|