kevy 5.1.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.
Files changed (49) hide show
  1. kevy-5.1.0/PKG-INFO +119 -0
  2. kevy-5.1.0/README.md +94 -0
  3. kevy-5.1.0/kevy/__init__.py +148 -0
  4. kevy-5.1.0/kevy/_client.py +381 -0
  5. kevy-5.1.0/kevy/_client_async.py +358 -0
  6. kevy-5.1.0/kevy/_client_async_remote.py +231 -0
  7. kevy-5.1.0/kevy/_client_remote.py +288 -0
  8. kevy-5.1.0/kevy/_cluster.py +249 -0
  9. kevy-5.1.0/kevy/_decode.py +172 -0
  10. kevy-5.1.0/kevy/_embedded.py +350 -0
  11. kevy-5.1.0/kevy/_enums.py +70 -0
  12. kevy-5.1.0/kevy/_errors.py +159 -0
  13. kevy-5.1.0/kevy/_ops.py +340 -0
  14. kevy-5.1.0/kevy/_parse.py +127 -0
  15. kevy-5.1.0/kevy/_pipeline.py +41 -0
  16. kevy-5.1.0/kevy/_reply.py +337 -0
  17. kevy-5.1.0/kevy/_resp_conn.py +136 -0
  18. kevy-5.1.0/kevy/_resp_conn_async.py +127 -0
  19. kevy-5.1.0/kevy/_subscriber.py +314 -0
  20. kevy-5.1.0/kevy/_subscriber_async.py +152 -0
  21. kevy-5.1.0/kevy/_transaction.py +235 -0
  22. kevy-5.1.0/kevy/_transaction_async.py +134 -0
  23. kevy-5.1.0/kevy/_types.py +121 -0
  24. kevy-5.1.0/kevy/_url.py +182 -0
  25. kevy-5.1.0/kevy.egg-info/PKG-INFO +119 -0
  26. kevy-5.1.0/kevy.egg-info/SOURCES.txt +47 -0
  27. kevy-5.1.0/kevy.egg-info/dependency_links.txt +1 -0
  28. kevy-5.1.0/kevy.egg-info/requires.txt +5 -0
  29. kevy-5.1.0/kevy.egg-info/top_level.txt +1 -0
  30. kevy-5.1.0/pyproject.toml +50 -0
  31. kevy-5.1.0/setup.cfg +4 -0
  32. kevy-5.1.0/tests/test_async.py +108 -0
  33. kevy-5.1.0/tests/test_blocking.py +71 -0
  34. kevy-5.1.0/tests/test_cluster.py +48 -0
  35. kevy-5.1.0/tests/test_collections.py +66 -0
  36. kevy-5.1.0/tests/test_core.py +96 -0
  37. kevy-5.1.0/tests/test_crc16.py +20 -0
  38. kevy-5.1.0/tests/test_embedded.py +69 -0
  39. kevy-5.1.0/tests/test_errors.py +84 -0
  40. kevy-5.1.0/tests/test_feed.py +51 -0
  41. kevy-5.1.0/tests/test_hashttl.py +47 -0
  42. kevy-5.1.0/tests/test_index.py +72 -0
  43. kevy-5.1.0/tests/test_pipeline.py +58 -0
  44. kevy-5.1.0/tests/test_pubsub.py +73 -0
  45. kevy-5.1.0/tests/test_reconnect.py +30 -0
  46. kevy-5.1.0/tests/test_reply.py +62 -0
  47. kevy-5.1.0/tests/test_transaction.py +79 -0
  48. kevy-5.1.0/tests/test_url.py +65 -0
  49. kevy-5.1.0/tests/test_zalgebra.py +53 -0
kevy-5.1.0/PKG-INFO ADDED
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.4
2
+ Name: kevy
3
+ Version: 5.1.0
4
+ Summary: First-party Python client for kevy — the pure-Rust Redis-compatible engine (embedded + remote, blocking + asyncio).
5
+ Author: GOLIA K.K.
6
+ License-Expression: MIT OR Apache-2.0
7
+ Project-URL: Homepage, https://kevy.golia.jp
8
+ Project-URL: Documentation, https://kevy.golia.jp
9
+ Project-URL: Repository, https://github.com/goliajp/kevy
10
+ Project-URL: Changelog, https://kevy.golia.jp/changelog/
11
+ Project-URL: Issues, https://github.com/goliajp/kevy/issues
12
+ Keywords: kevy,redis,resp,key-value,database,asyncio
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Database
17
+ Classifier: Topic :: Database :: Front-Ends
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ Provides-Extra: test
22
+ Requires-Dist: pytest>=7; extra == "test"
23
+ Requires-Dist: pytest-asyncio>=0.21; extra == "test"
24
+ Requires-Dist: pytest-timeout>=2; extra == "test"
25
+
26
+ # kevy — Python client
27
+
28
+ First-party Python client for **kevy**, the pure-Rust, Redis-compatible
29
+ engine. One package ships **both faces** (contract §1.4): a blocking
30
+ `Client` and an asyncio `AsyncClient` — the same shape as redis-py's
31
+ `redis` + `redis.asyncio`.
32
+
33
+ ```sh
34
+ pip install kevy
35
+ ```
36
+
37
+ ```python
38
+ import kevy
39
+
40
+ # Remote — native RESP2/3 over TCP. Standard library only.
41
+ r = kevy.connect("kevy://127.0.0.1:6379")
42
+ r.set("k", "v")
43
+ assert r.get(b"k") == b"v"
44
+
45
+ # Asyncio — same package, same results.
46
+ ac = await kevy.AsyncClient.connect("kevy://127.0.0.1:6379")
47
+ await ac.set("k", "v")
48
+
49
+ # Embedded (in-process), over the C ABI with ctypes. Needs the engine —
50
+ # see below; this line raises a message naming where to get it otherwise.
51
+ c = kevy.connect("mem://app") # or file:///var/lib/app
52
+ ```
53
+
54
+ ## The embedded engine
55
+
56
+ `mem://` and `file://` run kevy inside your process through
57
+ `libkevy_ffi`, a per-platform native library. A Python wheel does not
58
+ carry it: it would work on the handful of targets we happened to build
59
+ and nowhere else, while the remote client above works everywhere
60
+ CPython does. So the engine comes from the engine's own repository —
61
+
62
+ ```sh
63
+ git clone https://github.com/goliajp/kevy
64
+ cd kevy && cargo build --release -p kevy-ffi # → target/release/
65
+ ```
66
+
67
+ — and is found automatically from a kevy checkout, or by pointing
68
+ `KEVY_FFI_LIB` at the built library. Without it, the first embedded call
69
+ raises an error saying exactly this. Nothing else in the API differs.
70
+
71
+ ## One URL, two transports (§1.1)
72
+
73
+ | Scheme | Backend |
74
+ |---|---|
75
+ | `mem://` | embedded, isolated in-memory store |
76
+ | `mem://<name>` | embedded, shared by name (pub/sub works cross-connect) |
77
+ | `file:///abs/path` | embedded, persistent (snapshot + AOF) |
78
+ | `kevy://` / `redis://` / `tcp://` | remote RESP over TCP |
79
+
80
+ `rediss://` / `kevys://` (TLS) and `redis://user:pass@host` (AUTH) are
81
+ rejected — kevy has neither.
82
+
83
+ ## Embedded door (§5)
84
+
85
+ `kevy.open_mem()` / `kevy.open_persistent(dir)` return a `DB` — the
86
+ in-process store over `libkevy_ffi`, driven by ctypes (no C-extension
87
+ build). Every verb is reachable through `db.cmd(*argv) -> Reply`; `db.get`
88
+ / `db.set` are the scalar fast paths; `db.subscribe(chan)` gives a polled
89
+ (`next()`) + blocking (`wait(ms)`) subscription. The library is located via
90
+ `$KEVY_FFI_LIB` or the repo `target/{release,debug}` build.
91
+
92
+ ## Command families
93
+
94
+ Every family of the contract (§3): core string/generic, hash, list, set,
95
+ sorted set, sorted-set algebra, hash-field TTL, declarative indexes
96
+ (`idx_*`, remote-only) — with any other `IDX.*` subcommand reachable through
97
+ the raw `do(*argv)` / `idx_query_raw` escape hatches — change feed
98
+ (`feed_*`), pub/sub
99
+ (`Subscriber` / `AsyncSubscriber`), transactions (`Transaction`),
100
+ pipelines, blocking pops (`blpop`/`brpop`/`bzpopmin`), and the cluster
101
+ client (`ClusterClient`). Bytes and `str` are both accepted; the wire is
102
+ bytes (§7).
103
+
104
+ ## Errors (§2)
105
+
106
+ Raised as a `KevyError` hierarchy inspectable by type: `StoreError`
107
+ (`WrongTypeError`, `NotIntegerError`, …), `ProtocolError`, `IoError`,
108
+ `UnsupportedError`, `InvalidInputError`, `NotFoundError`, `ReadOnlyError`,
109
+ `TimedOutError`, `ClosedError`.
110
+
111
+ ## Tests
112
+
113
+ ```
114
+ pip install -e '.[test]'
115
+ pytest # embedded + remote (spawns a real kevy server)
116
+ ```
117
+
118
+ Remote tests build and boot `kevy` on a temp port; they skip cleanly if the
119
+ server binary is absent (`cargo build --release -p kevy`).
kevy-5.1.0/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # kevy — Python client
2
+
3
+ First-party Python client for **kevy**, the pure-Rust, Redis-compatible
4
+ engine. One package ships **both faces** (contract §1.4): a blocking
5
+ `Client` and an asyncio `AsyncClient` — the same shape as redis-py's
6
+ `redis` + `redis.asyncio`.
7
+
8
+ ```sh
9
+ pip install kevy
10
+ ```
11
+
12
+ ```python
13
+ import kevy
14
+
15
+ # Remote — native RESP2/3 over TCP. Standard library only.
16
+ r = kevy.connect("kevy://127.0.0.1:6379")
17
+ r.set("k", "v")
18
+ assert r.get(b"k") == b"v"
19
+
20
+ # Asyncio — same package, same results.
21
+ ac = await kevy.AsyncClient.connect("kevy://127.0.0.1:6379")
22
+ await ac.set("k", "v")
23
+
24
+ # Embedded (in-process), over the C ABI with ctypes. Needs the engine —
25
+ # see below; this line raises a message naming where to get it otherwise.
26
+ c = kevy.connect("mem://app") # or file:///var/lib/app
27
+ ```
28
+
29
+ ## The embedded engine
30
+
31
+ `mem://` and `file://` run kevy inside your process through
32
+ `libkevy_ffi`, a per-platform native library. A Python wheel does not
33
+ carry it: it would work on the handful of targets we happened to build
34
+ and nowhere else, while the remote client above works everywhere
35
+ CPython does. So the engine comes from the engine's own repository —
36
+
37
+ ```sh
38
+ git clone https://github.com/goliajp/kevy
39
+ cd kevy && cargo build --release -p kevy-ffi # → target/release/
40
+ ```
41
+
42
+ — and is found automatically from a kevy checkout, or by pointing
43
+ `KEVY_FFI_LIB` at the built library. Without it, the first embedded call
44
+ raises an error saying exactly this. Nothing else in the API differs.
45
+
46
+ ## One URL, two transports (§1.1)
47
+
48
+ | Scheme | Backend |
49
+ |---|---|
50
+ | `mem://` | embedded, isolated in-memory store |
51
+ | `mem://<name>` | embedded, shared by name (pub/sub works cross-connect) |
52
+ | `file:///abs/path` | embedded, persistent (snapshot + AOF) |
53
+ | `kevy://` / `redis://` / `tcp://` | remote RESP over TCP |
54
+
55
+ `rediss://` / `kevys://` (TLS) and `redis://user:pass@host` (AUTH) are
56
+ rejected — kevy has neither.
57
+
58
+ ## Embedded door (§5)
59
+
60
+ `kevy.open_mem()` / `kevy.open_persistent(dir)` return a `DB` — the
61
+ in-process store over `libkevy_ffi`, driven by ctypes (no C-extension
62
+ build). Every verb is reachable through `db.cmd(*argv) -> Reply`; `db.get`
63
+ / `db.set` are the scalar fast paths; `db.subscribe(chan)` gives a polled
64
+ (`next()`) + blocking (`wait(ms)`) subscription. The library is located via
65
+ `$KEVY_FFI_LIB` or the repo `target/{release,debug}` build.
66
+
67
+ ## Command families
68
+
69
+ Every family of the contract (§3): core string/generic, hash, list, set,
70
+ sorted set, sorted-set algebra, hash-field TTL, declarative indexes
71
+ (`idx_*`, remote-only) — with any other `IDX.*` subcommand reachable through
72
+ the raw `do(*argv)` / `idx_query_raw` escape hatches — change feed
73
+ (`feed_*`), pub/sub
74
+ (`Subscriber` / `AsyncSubscriber`), transactions (`Transaction`),
75
+ pipelines, blocking pops (`blpop`/`brpop`/`bzpopmin`), and the cluster
76
+ client (`ClusterClient`). Bytes and `str` are both accepted; the wire is
77
+ bytes (§7).
78
+
79
+ ## Errors (§2)
80
+
81
+ Raised as a `KevyError` hierarchy inspectable by type: `StoreError`
82
+ (`WrongTypeError`, `NotIntegerError`, …), `ProtocolError`, `IoError`,
83
+ `UnsupportedError`, `InvalidInputError`, `NotFoundError`, `ReadOnlyError`,
84
+ `TimedOutError`, `ClosedError`.
85
+
86
+ ## Tests
87
+
88
+ ```
89
+ pip install -e '.[test]'
90
+ pytest # embedded + remote (spawns a real kevy server)
91
+ ```
92
+
93
+ Remote tests build and boot `kevy` on a temp port; they skip cleanly if the
94
+ server binary is absent (`cargo build --release -p kevy`).
@@ -0,0 +1,148 @@
1
+ """kevy — the first-party Python client for the pure-Rust, Redis-compatible
2
+ kevy engine.
3
+
4
+ One package, both faces (contract §1.4): a blocking :class:`Client` and an
5
+ asyncio :class:`AsyncClient`, exactly as redis-py ships ``redis`` +
6
+ ``redis.asyncio``. A single ``connect(url)`` chooses the backend from the URL
7
+ scheme (§1.1): ``mem://`` / ``file://`` open the in-process **embedded**
8
+ engine (a ctypes binding over the C ABI ``libkevy_ffi`` — the new Python
9
+ embedded door, §5); ``kevy://`` / ``redis://`` / ``tcp://`` open a native
10
+ RESP2/3 TCP client. The wire is bytes; every key/value is binary-safe (§7).
11
+
12
+ import kevy
13
+
14
+ c = kevy.connect("mem://app") # embedded, blocking
15
+ c.set("k", "v"); print(c.get(b"k")) # -> b"v"
16
+
17
+ ac = await kevy.AsyncClient.connect("kevy://127.0.0.1:6379")
18
+ await ac.set("k", "v")
19
+
20
+ Errors are raised as a :class:`KevyError` hierarchy inspectable by type (§2).
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from ._client import Client
26
+ from ._client_async import AsyncClient
27
+ from ._cluster import ClusterClient, crc16, key_hash_slot
28
+ from ._embedded import DB, Sub, abi, open_mem, open_persistent, version
29
+ from ._enums import EvictionPolicy, HExpireCond, IdxType, RespVersion, ZAggregate
30
+ from ._errors import (
31
+ ClosedError,
32
+ InvalidInputError,
33
+ IoError,
34
+ KevyError,
35
+ NoSuchKeyError,
36
+ NotFloatError,
37
+ NotFoundError,
38
+ NotIntegerError,
39
+ OutOfMemoryStoreError,
40
+ OutOfRangeError,
41
+ OverflowStoreError,
42
+ ProtocolError,
43
+ ReadOnlyError,
44
+ StoreError,
45
+ StoreErrorKind,
46
+ TimedOutError,
47
+ UnsupportedError,
48
+ WrongTypeError,
49
+ )
50
+ from ._pipeline import PipelineBuf
51
+ from ._reply import Reply, ReplyKind
52
+ from ._subscriber import Subscriber
53
+ from ._subscriber_async import AsyncSubscriber
54
+ from ._transaction import Transaction, TransactionReplies
55
+ from ._transaction_async import AsyncTransaction
56
+ from ._types import (
57
+ FeedBatch,
58
+ FeedFrame,
59
+ IdxInfo,
60
+ IdxPage,
61
+ IdxRow,
62
+ PubsubEvent,
63
+ PubsubKind,
64
+ Ranked,
65
+ ZMember,
66
+ ZPopHit,
67
+ KV,
68
+ )
69
+
70
+ __version__ = "5.1.0"
71
+
72
+
73
+ def connect(url: str) -> Client:
74
+ """Open a blocking :class:`Client` for ``url`` (§1.1). Equivalent to
75
+ :meth:`Client.connect`."""
76
+ return Client.connect(url)
77
+
78
+
79
+ async def aconnect(url: str) -> AsyncClient:
80
+ """Open an asyncio :class:`AsyncClient` for ``url`` (§1.4). Equivalent to
81
+ :meth:`AsyncClient.connect`."""
82
+ return await AsyncClient.connect(url)
83
+
84
+
85
+ __all__ = [
86
+ "__version__",
87
+ "connect",
88
+ "aconnect",
89
+ # clients
90
+ "Client",
91
+ "AsyncClient",
92
+ "ClusterClient",
93
+ "Subscriber",
94
+ "AsyncSubscriber",
95
+ "Transaction",
96
+ "AsyncTransaction",
97
+ "TransactionReplies",
98
+ "PipelineBuf",
99
+ # embedded store
100
+ "DB",
101
+ "Sub",
102
+ "open_mem",
103
+ "open_persistent",
104
+ "abi",
105
+ "version",
106
+ # reply / enums
107
+ "Reply",
108
+ "ReplyKind",
109
+ "ZAggregate",
110
+ "HExpireCond",
111
+ "IdxType",
112
+ "RespVersion",
113
+ "EvictionPolicy",
114
+ # data types
115
+ "ZMember",
116
+ "KV",
117
+ "ZPopHit",
118
+ "IdxRow",
119
+ "IdxPage",
120
+ "IdxInfo",
121
+ "Ranked",
122
+ "FeedFrame",
123
+ "FeedBatch",
124
+ "PubsubEvent",
125
+ "PubsubKind",
126
+ # cluster helpers
127
+ "crc16",
128
+ "key_hash_slot",
129
+ # errors
130
+ "KevyError",
131
+ "StoreError",
132
+ "StoreErrorKind",
133
+ "WrongTypeError",
134
+ "NotIntegerError",
135
+ "OverflowStoreError",
136
+ "OutOfRangeError",
137
+ "NoSuchKeyError",
138
+ "NotFloatError",
139
+ "OutOfMemoryStoreError",
140
+ "IoError",
141
+ "ProtocolError",
142
+ "ReadOnlyError",
143
+ "InvalidInputError",
144
+ "NotFoundError",
145
+ "UnsupportedError",
146
+ "TimedOutError",
147
+ "ClosedError",
148
+ ]