moat-kv 0.70.20__py3-none-any.whl → 0.70.23__py3-none-any.whl
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.
- moat/kv/__init__.py +1 -0
- moat/kv/_cfg.yaml +97 -0
- moat/kv/_main.py +6 -9
- moat/kv/client.py +36 -52
- moat/kv/code.py +10 -3
- moat/kv/codec.py +1 -0
- moat/kv/config.py +2 -0
- moat/kv/data.py +8 -7
- moat/kv/errors.py +17 -9
- moat/kv/exceptions.py +1 -7
- moat/kv/model.py +16 -24
- moat/kv/runner.py +39 -36
- moat/kv/server.py +86 -90
- moat/kv/types.py +5 -8
- {moat_kv-0.70.20.dist-info → moat_kv-0.70.23.dist-info}/METADATA +22 -25
- moat_kv-0.70.23.dist-info/RECORD +19 -0
- {moat_kv-0.70.20.dist-info → moat_kv-0.70.23.dist-info}/WHEEL +1 -1
- moat_kv-0.70.23.dist-info/licenses/LICENSE.txt +14 -0
- moat/kv/_config.yaml +0 -98
- moat/kv/actor/__init__.py +0 -97
- moat/kv/actor/deletor.py +0 -137
- moat/kv/auth/__init__.py +0 -446
- moat/kv/auth/_test.py +0 -172
- moat/kv/auth/password.py +0 -232
- moat/kv/auth/root.py +0 -56
- moat/kv/backend/__init__.py +0 -66
- moat/kv/backend/mqtt.py +0 -74
- moat/kv/backend/serf.py +0 -44
- moat/kv/command/__init__.py +0 -1
- moat/kv/command/acl.py +0 -174
- moat/kv/command/auth.py +0 -258
- moat/kv/command/code.py +0 -306
- moat/kv/command/codec.py +0 -190
- moat/kv/command/data.py +0 -274
- moat/kv/command/dump/__init__.py +0 -141
- moat/kv/command/error.py +0 -156
- moat/kv/command/internal.py +0 -257
- moat/kv/command/job.py +0 -438
- moat/kv/command/log.py +0 -52
- moat/kv/command/server.py +0 -115
- moat/kv/command/type.py +0 -203
- moat/kv/mock/__init__.py +0 -97
- moat/kv/mock/mqtt.py +0 -164
- moat/kv/mock/serf.py +0 -253
- moat/kv/mock/tracer.py +0 -65
- moat/kv/obj/__init__.py +0 -636
- moat/kv/obj/command.py +0 -246
- moat_kv-0.70.20.dist-info/LICENSE +0 -3
- moat_kv-0.70.20.dist-info/LICENSE.APACHE2 +0 -202
- moat_kv-0.70.20.dist-info/LICENSE.MIT +0 -20
- moat_kv-0.70.20.dist-info/RECORD +0 -49
- {moat_kv-0.70.20.dist-info → moat_kv-0.70.23.dist-info}/top_level.txt +0 -0
moat/kv/server.py
CHANGED
@@ -5,12 +5,11 @@ import io
|
|
5
5
|
import os
|
6
6
|
import signal
|
7
7
|
import time
|
8
|
-
from pathlib import Path as FPath
|
9
8
|
|
10
9
|
import anyio
|
11
10
|
from anyio.abc import SocketAttribute
|
12
11
|
from asyncscope import scope
|
13
|
-
from moat.util import DelayedRead, DelayedWrite, create_queue,
|
12
|
+
from moat.util import DelayedRead, DelayedWrite, create_queue, ensure_cfg
|
14
13
|
|
15
14
|
try:
|
16
15
|
from contextlib import asynccontextmanager
|
@@ -21,7 +20,7 @@ import logging
|
|
21
20
|
from collections.abc import Mapping
|
22
21
|
from functools import partial
|
23
22
|
from pprint import pformat
|
24
|
-
from typing import Any
|
23
|
+
from typing import Any
|
25
24
|
|
26
25
|
from asyncactor import (
|
27
26
|
Actor,
|
@@ -151,9 +150,7 @@ class StreamCommand:
|
|
151
150
|
self.client.in_stream[self.seq] = self
|
152
151
|
self.qlen = self.client.qlen
|
153
152
|
if self.qlen:
|
154
|
-
self.qr = DelayedRead(
|
155
|
-
self.qlen, get_seq=self._get_seq, send_ack=self._send_ack
|
156
|
-
)
|
153
|
+
self.qr = DelayedRead(self.qlen, get_seq=self._get_seq, send_ack=self._send_ack)
|
157
154
|
self.dw = DelayedWrite(self.qlen)
|
158
155
|
else:
|
159
156
|
self.qr = create_queue(1)
|
@@ -227,9 +224,7 @@ class StreamCommand:
|
|
227
224
|
await self.send(**res)
|
228
225
|
except Exception as exc:
|
229
226
|
if not isinstance(exc, CancelledError):
|
230
|
-
self.client.logger.exception(
|
231
|
-
"ERS%d %r", self.client._client_nr, self.msg
|
232
|
-
)
|
227
|
+
self.client.logger.exception("ERS%d %r", self.client._client_nr, self.msg)
|
233
228
|
await self.send(error=repr(exc))
|
234
229
|
finally:
|
235
230
|
with anyio.move_on_after(2, shield=True):
|
@@ -547,7 +542,11 @@ class SCmd_watch(StreamCommand):
|
|
547
542
|
client = self.client
|
548
543
|
conv = client.conv
|
549
544
|
entry, acl = client.root.follow_acl(
|
550
|
-
msg.path,
|
545
|
+
msg.path,
|
546
|
+
acl=client.acl,
|
547
|
+
acl_key="x",
|
548
|
+
create=True,
|
549
|
+
nulls_ok=client.nulls_ok,
|
551
550
|
)
|
552
551
|
nchain = msg.get("nchain", 0)
|
553
552
|
max_depth = msg.get("max_depth", -1)
|
@@ -602,7 +601,9 @@ class SCmd_watch(StreamCommand):
|
|
602
601
|
a = a.step(p)
|
603
602
|
else:
|
604
603
|
res = m.entry.serialize(
|
605
|
-
chop_path=client._chop_path,
|
604
|
+
chop_path=client._chop_path,
|
605
|
+
nchain=nchain,
|
606
|
+
conv=conv,
|
606
607
|
)
|
607
608
|
shorter(res)
|
608
609
|
if not a.allows("r"):
|
@@ -661,7 +662,7 @@ class ServerClient:
|
|
661
662
|
tg = None
|
662
663
|
qlen = 0
|
663
664
|
|
664
|
-
def __init__(self, server:
|
665
|
+
def __init__(self, server: Server, stream: Stream):
|
665
666
|
self.server = server
|
666
667
|
self.root = server.root
|
667
668
|
self.metaroot = self.root.follow(Path(None), create=True, nulls_ok=True)
|
@@ -707,9 +708,7 @@ class ServerClient:
|
|
707
708
|
with anyio.CancelScope() as s:
|
708
709
|
self.tasks[seq] = s
|
709
710
|
if "chain" in msg:
|
710
|
-
msg.chain = NodeEvent.deserialize(
|
711
|
-
msg.chain, cache=self.server.node_cache
|
712
|
-
)
|
711
|
+
msg.chain = NodeEvent.deserialize(msg.chain, cache=self.server.node_cache)
|
713
712
|
|
714
713
|
fn = None
|
715
714
|
if msg.get("state", "") != "start":
|
@@ -848,7 +847,11 @@ class ServerClient:
|
|
848
847
|
acl2 = root.follow(Path(None, "acl", acl2), create=False, nulls_ok=True)
|
849
848
|
acl2 = ACLFinder(acl2)
|
850
849
|
_entry, acl = root.follow_acl(
|
851
|
-
msg.path,
|
850
|
+
msg.path,
|
851
|
+
acl=acl2,
|
852
|
+
acl_key=mode,
|
853
|
+
nulls_ok=False,
|
854
|
+
create=None,
|
852
855
|
)
|
853
856
|
if not ok:
|
854
857
|
acl.block("a")
|
@@ -865,7 +868,11 @@ class ServerClient:
|
|
865
868
|
if with_data is None:
|
866
869
|
with_data = msg.get("with_data", False)
|
867
870
|
entry, acl = root.follow_acl(
|
868
|
-
msg.path,
|
871
|
+
msg.path,
|
872
|
+
acl=self.acl,
|
873
|
+
acl_key="e",
|
874
|
+
create=False,
|
875
|
+
nulls_ok=_nulls_ok,
|
869
876
|
)
|
870
877
|
empty = msg.get("empty", False)
|
871
878
|
if with_data:
|
@@ -908,7 +915,9 @@ class ServerClient:
|
|
908
915
|
if "node" in msg and "path" not in msg:
|
909
916
|
n = Node(msg.node, cache=self.server.node_cache, create=False)
|
910
917
|
return n[msg.tick].serialize(
|
911
|
-
chop_path=self._chop_path,
|
918
|
+
chop_path=self._chop_path,
|
919
|
+
nchain=msg.get("nchain", 0),
|
920
|
+
conv=self.conv,
|
912
921
|
)
|
913
922
|
|
914
923
|
if _nulls_ok is None:
|
@@ -917,16 +926,18 @@ class ServerClient:
|
|
917
926
|
root = self.root
|
918
927
|
try:
|
919
928
|
entry, _ = root.follow_acl(
|
920
|
-
msg.path,
|
929
|
+
msg.path,
|
930
|
+
create=False,
|
931
|
+
acl=self.acl,
|
932
|
+
acl_key="r",
|
933
|
+
nulls_ok=_nulls_ok,
|
921
934
|
)
|
922
935
|
except KeyError:
|
923
936
|
entry = {}
|
924
937
|
if msg.get("nchain", 0):
|
925
938
|
entry["chain"] = None
|
926
939
|
else:
|
927
|
-
entry = entry.serialize(
|
928
|
-
chop_path=-1, nchain=msg.get("nchain", 0), conv=self.conv
|
929
|
-
)
|
940
|
+
entry = entry.serialize(chop_path=-1, nchain=msg.get("nchain", 0), conv=self.conv)
|
930
941
|
return entry
|
931
942
|
|
932
943
|
async def cmd_set_value(self, msg, **kw):
|
@@ -955,9 +966,7 @@ class ServerClient:
|
|
955
966
|
entry, acl = root.follow_acl(msg.path, acl=acl, acl_key="W", nulls_ok=_nulls_ok)
|
956
967
|
if root is self.root and "match" in self.metaroot:
|
957
968
|
try:
|
958
|
-
self.metaroot["match"].check_value(
|
959
|
-
None if value is NotGiven else value, entry
|
960
|
-
)
|
969
|
+
self.metaroot["match"].check_value(None if value is NotGiven else value, entry)
|
961
970
|
except ClientError:
|
962
971
|
raise
|
963
972
|
except Exception as exc:
|
@@ -968,11 +977,7 @@ class ServerClient:
|
|
968
977
|
send_prev = True
|
969
978
|
nchain = msg.get("nchain", 1)
|
970
979
|
|
971
|
-
if (
|
972
|
-
msg.get("idem", False)
|
973
|
-
and type(entry.data) is type(value)
|
974
|
-
and entry.data == value
|
975
|
-
):
|
980
|
+
if msg.get("idem", False) and type(entry.data) is type(value) and entry.data == value:
|
976
981
|
res = attrdict(tock=entry.tock, changed=False)
|
977
982
|
if nchain > 0:
|
978
983
|
res.chain = entry.chain.serialize(nchain=nchain)
|
@@ -980,9 +985,7 @@ class ServerClient:
|
|
980
985
|
|
981
986
|
if "prev" in msg:
|
982
987
|
if entry.data != msg.prev:
|
983
|
-
raise ClientError(
|
984
|
-
f"Data is {entry.data !r} not {msg.prev !r} at {msg.path}"
|
985
|
-
)
|
988
|
+
raise ClientError(f"Data is {entry.data!r} not {msg.prev!r} at {msg.path}")
|
986
989
|
send_prev = False
|
987
990
|
if "chain" in msg:
|
988
991
|
if msg.chain is None:
|
@@ -992,7 +995,7 @@ class ServerClient:
|
|
992
995
|
raise ClientChainError(f"Entry is new at {msg.path}")
|
993
996
|
elif entry.chain != msg.chain:
|
994
997
|
raise ClientChainError(
|
995
|
-
f"Chain is {entry.chain
|
998
|
+
f"Chain is {entry.chain!r} not {msg.chain!r} for {msg.path}",
|
996
999
|
)
|
997
1000
|
send_prev = False
|
998
1001
|
|
@@ -1009,9 +1012,7 @@ class ServerClient:
|
|
1009
1012
|
async with self.server.next_event() as event:
|
1010
1013
|
await entry.set_data(
|
1011
1014
|
event,
|
1012
|
-
NotGiven
|
1013
|
-
if value is NotGiven
|
1014
|
-
else self.conv.dec_value(value, entry=entry),
|
1015
|
+
NotGiven if value is NotGiven else self.conv.dec_value(value, entry=entry),
|
1015
1016
|
server=self.server,
|
1016
1017
|
tock=self.server.tock,
|
1017
1018
|
)
|
@@ -1085,7 +1086,10 @@ class ServerClient:
|
|
1085
1086
|
|
1086
1087
|
try:
|
1087
1088
|
entry, acl = self.root.follow_acl(
|
1088
|
-
msg.path,
|
1089
|
+
msg.path,
|
1090
|
+
acl=self.acl,
|
1091
|
+
acl_key="d",
|
1092
|
+
nulls_ok=self.nulls_ok,
|
1089
1093
|
)
|
1090
1094
|
except KeyError:
|
1091
1095
|
return False
|
@@ -1094,9 +1098,7 @@ class ServerClient:
|
|
1094
1098
|
res = 0
|
1095
1099
|
if entry.data is not None and acl.allows("d"):
|
1096
1100
|
async with self.server.next_event() as event:
|
1097
|
-
evt = await entry.set_data(
|
1098
|
-
event, NotGiven, server=self, tock=self.server.tock
|
1099
|
-
)
|
1101
|
+
evt = await entry.set_data(event, NotGiven, server=self, tock=self.server.tock)
|
1100
1102
|
if nchain:
|
1101
1103
|
r = evt.serialize(
|
1102
1104
|
chop_path=self._chop_path,
|
@@ -1152,9 +1154,7 @@ class ServerClient:
|
|
1152
1154
|
if msg.typ is None:
|
1153
1155
|
val.pop("current", None)
|
1154
1156
|
elif msg.typ not in a or not len(a[msg.typ]["user"].keys()):
|
1155
|
-
raise RuntimeError(
|
1156
|
-
"You didn't configure this method yet:" + repr((msg.typ, vars(a)))
|
1157
|
-
)
|
1157
|
+
raise RuntimeError("You didn't configure this method yet:" + repr((msg.typ, vars(a))))
|
1158
1158
|
else:
|
1159
1159
|
val["current"] = msg.typ
|
1160
1160
|
msg.value = val
|
@@ -1238,13 +1238,13 @@ class ServerClient:
|
|
1238
1238
|
await evt.wait()
|
1239
1239
|
except Exception as exc:
|
1240
1240
|
msg = {"error": str(exc)}
|
1241
|
-
if isinstance(
|
1242
|
-
exc, ClientError
|
1243
|
-
): # pylint doesn't seem to see this, so …:
|
1241
|
+
if isinstance(exc, ClientError): # pylint doesn't seem to see this, so …:
|
1244
1242
|
msg["etype"] = exc.etype # pylint: disable=no-member ### YES IT HAS
|
1245
1243
|
else:
|
1246
1244
|
self.logger.exception(
|
1247
|
-
"ERR %d: Client error on %s",
|
1245
|
+
"ERR %d: Client error on %s",
|
1246
|
+
self._client_nr,
|
1247
|
+
repr(msg),
|
1248
1248
|
)
|
1249
1249
|
if seq is not None:
|
1250
1250
|
msg["seq"] = seq
|
@@ -1357,7 +1357,7 @@ class Server:
|
|
1357
1357
|
name (str): the name of this MoaT-KV server instance.
|
1358
1358
|
It **must** be unique.
|
1359
1359
|
cfg: configuration.
|
1360
|
-
See ``
|
1360
|
+
See ``_cfg.yaml`` for default values.
|
1361
1361
|
Relevant is the ``kv.server`` sub-dict (mostly).
|
1362
1362
|
init (Any):
|
1363
1363
|
The initial content of the root entry. **Do not use this**, except
|
@@ -1381,7 +1381,10 @@ class Server:
|
|
1381
1381
|
|
1382
1382
|
def __init__(self, name: str, cfg: dict = None, init: Any = NotGiven):
|
1383
1383
|
self.root = RootEntry(self, tock=self.tock)
|
1384
|
-
|
1384
|
+
from moat.util import CFG
|
1385
|
+
|
1386
|
+
ensure_cfg("moat.kv")
|
1387
|
+
CFG = CFG["kv"]
|
1385
1388
|
|
1386
1389
|
self.cfg = combine_dict(cfg or {}, CFG, cls=attrdict)
|
1387
1390
|
csr = self.cfg.server["root"]
|
@@ -1390,7 +1393,7 @@ class Server:
|
|
1390
1393
|
|
1391
1394
|
self.paranoid_root = self.root if self.cfg.server.paranoia else None
|
1392
1395
|
|
1393
|
-
self._nodes:
|
1396
|
+
self._nodes: dict[str, Node] = {}
|
1394
1397
|
self.node_drop = set()
|
1395
1398
|
self.node = Node(name, None, cache=self.node_cache)
|
1396
1399
|
|
@@ -1473,9 +1476,7 @@ class Server:
|
|
1473
1476
|
yield n
|
1474
1477
|
except BaseException as exc:
|
1475
1478
|
if n is not None:
|
1476
|
-
self.logger.warning(
|
1477
|
-
"Deletion %s %d due to %r", self.node, n.tick, exc
|
1478
|
-
)
|
1479
|
+
self.logger.warning("Deletion %s %d due to %r", self.node, n.tick, exc)
|
1479
1480
|
self.node.report_deleted(
|
1480
1481
|
RangeSet((nt,)),
|
1481
1482
|
self, # pylint: disable=used-before-assignment
|
@@ -1598,7 +1599,10 @@ class Server:
|
|
1598
1599
|
async def send_nodes():
|
1599
1600
|
nonlocal nodes, n_nodes
|
1600
1601
|
await client._request( # pylint: disable=cell-var-from-loop
|
1601
|
-
"check_deleted",
|
1602
|
+
"check_deleted",
|
1603
|
+
iter=False,
|
1604
|
+
nchain=-1,
|
1605
|
+
nodes=nodes.serialize(),
|
1602
1606
|
)
|
1603
1607
|
nodes.clear()
|
1604
1608
|
n_nodes = 0
|
@@ -1739,9 +1743,7 @@ class Server:
|
|
1739
1743
|
"""
|
1740
1744
|
Process an update message: deserialize it and apply the result.
|
1741
1745
|
"""
|
1742
|
-
msg = UpdateEvent.deserialize(
|
1743
|
-
self.root, msg, cache=self.node_cache, nulls_ok=True
|
1744
|
-
)
|
1746
|
+
msg = UpdateEvent.deserialize(self.root, msg, cache=self.node_cache, nulls_ok=True)
|
1745
1747
|
await msg.entry.apply(msg, server=self, root=self.paranoid_root)
|
1746
1748
|
|
1747
1749
|
async def user_info(self, msg):
|
@@ -1841,7 +1843,7 @@ class Server:
|
|
1841
1843
|
j = i
|
1842
1844
|
while i:
|
1843
1845
|
i -= 1
|
1844
|
-
msg[f"_p{i+1}"] = msg[f"_p{i}"]
|
1846
|
+
msg[f"_p{i + 1}"] = msg[f"_p{i}"]
|
1845
1847
|
if j:
|
1846
1848
|
msg["_p0"] = ""
|
1847
1849
|
|
@@ -1887,8 +1889,8 @@ class Server:
|
|
1887
1889
|
msg["_p0"] = ""
|
1888
1890
|
|
1889
1891
|
i = 0
|
1890
|
-
while f"_p{i+1}" in msg:
|
1891
|
-
msg[f"_p{i}"] = msg[f"_p{i+1}"]
|
1892
|
+
while f"_p{i + 1}" in msg:
|
1893
|
+
msg[f"_p{i}"] = msg[f"_p{i + 1}"]
|
1892
1894
|
i += 1
|
1893
1895
|
del msg[f"_p{i}"]
|
1894
1896
|
return msg
|
@@ -2015,9 +2017,7 @@ class Server:
|
|
2015
2017
|
try:
|
2016
2018
|
# First try to read the host name from the meta-root's
|
2017
2019
|
# "hostmap" entry, if any.
|
2018
|
-
hme = self.root.follow(
|
2019
|
-
Path(None, "hostmap", host), create=False, nulls_ok=True
|
2020
|
-
)
|
2020
|
+
hme = self.root.follow(Path(None, "hostmap", host), create=False, nulls_ok=True)
|
2021
2021
|
if hme.data is NotGiven:
|
2022
2022
|
raise KeyError(host)
|
2023
2023
|
except KeyError:
|
@@ -2123,7 +2123,10 @@ class Server:
|
|
2123
2123
|
async for r in res:
|
2124
2124
|
pl(r)
|
2125
2125
|
r = UpdateEvent.deserialize(
|
2126
|
-
self.root,
|
2126
|
+
self.root,
|
2127
|
+
r,
|
2128
|
+
cache=self.node_cache,
|
2129
|
+
nulls_ok=True,
|
2127
2130
|
)
|
2128
2131
|
await r.entry.apply(r, server=self, root=self.paranoid_root)
|
2129
2132
|
await self.tock_seen(res.end_msg.tock)
|
@@ -2139,7 +2142,10 @@ class Server:
|
|
2139
2142
|
async for r in res:
|
2140
2143
|
pl(r)
|
2141
2144
|
r = UpdateEvent.deserialize(
|
2142
|
-
self.root,
|
2145
|
+
self.root,
|
2146
|
+
r,
|
2147
|
+
cache=self.node_cache,
|
2148
|
+
nulls_ok=True,
|
2143
2149
|
)
|
2144
2150
|
await r.entry.apply(r, server=self, root=self.paranoid_root)
|
2145
2151
|
await self.tock_seen(res.end_msg.tock)
|
@@ -2172,9 +2178,7 @@ class Server:
|
|
2172
2178
|
if len(self.fetch_missing):
|
2173
2179
|
self.fetch_running = False
|
2174
2180
|
for nm in self.fetch_missing:
|
2175
|
-
self.logger.error(
|
2176
|
-
"Sync: missing: %s %s", nm.name, nm.local_missing
|
2177
|
-
)
|
2181
|
+
self.logger.error("Sync: missing: %s %s", nm.name, nm.local_missing)
|
2178
2182
|
await self.spawn(self.do_send_missing)
|
2179
2183
|
if self.force_startup or not len(self.fetch_missing):
|
2180
2184
|
if self.node.tick is None:
|
@@ -2354,9 +2358,7 @@ class Server:
|
|
2354
2358
|
if prio is None:
|
2355
2359
|
await anyio.sleep(clock * (1 + self._actor.random / 3))
|
2356
2360
|
else:
|
2357
|
-
await anyio.sleep(
|
2358
|
-
clock * (1 - (1 / (1 << prio)) / 2 - self._actor.random / 5)
|
2359
|
-
)
|
2361
|
+
await anyio.sleep(clock * (1 - (1 / (1 << prio)) / 2 - self._actor.random / 5))
|
2360
2362
|
|
2361
2363
|
self.logger.debug("SendMissingGo %s %s", prio, self.sending_missing)
|
2362
2364
|
while self.sending_missing:
|
@@ -2431,18 +2433,12 @@ class Server:
|
|
2431
2433
|
await self.tock_seen(m.tock)
|
2432
2434
|
else:
|
2433
2435
|
m.tock = self.tock
|
2434
|
-
m = UpdateEvent.deserialize(
|
2435
|
-
self.root, m, cache=self.node_cache, nulls_ok=True
|
2436
|
-
)
|
2436
|
+
m = UpdateEvent.deserialize(self.root, m, cache=self.node_cache, nulls_ok=True)
|
2437
2437
|
await self.tock_seen(m.tock)
|
2438
|
-
await m.entry.apply(
|
2439
|
-
m, server=self, root=self.paranoid_root, loading=True
|
2440
|
-
)
|
2438
|
+
await m.entry.apply(m, server=self, root=self.paranoid_root, loading=True)
|
2441
2439
|
elif "info" in m:
|
2442
2440
|
await self._process_info(m["info"])
|
2443
|
-
elif
|
2444
|
-
"nodes" in m or "known" in m or "deleted" in m or "tock" in m
|
2445
|
-
): # XXX LEGACY
|
2441
|
+
elif "nodes" in m or "known" in m or "deleted" in m or "tock" in m: # XXX LEGACY
|
2446
2442
|
await self._process_info(m)
|
2447
2443
|
else:
|
2448
2444
|
self.logger.warning("Unknown message in stream: %s", repr(m))
|
@@ -2560,7 +2556,11 @@ class Server:
|
|
2560
2556
|
cnt += 1
|
2561
2557
|
|
2562
2558
|
async def _saver(
|
2563
|
-
self,
|
2559
|
+
self,
|
2560
|
+
path: str = None,
|
2561
|
+
stream=None,
|
2562
|
+
done: ValueEvent = None,
|
2563
|
+
save_state=False,
|
2564
2564
|
):
|
2565
2565
|
with anyio.CancelScope() as s:
|
2566
2566
|
sd = anyio.Event()
|
@@ -2574,7 +2574,7 @@ class Server:
|
|
2574
2574
|
done_val=s,
|
2575
2575
|
save_state=save_state,
|
2576
2576
|
)
|
2577
|
-
except
|
2577
|
+
except OSError as err:
|
2578
2578
|
if done is None:
|
2579
2579
|
raise
|
2580
2580
|
done.set_error(err)
|
@@ -2582,9 +2582,7 @@ class Server:
|
|
2582
2582
|
with anyio.CancelScope(shield=True):
|
2583
2583
|
sd.set()
|
2584
2584
|
|
2585
|
-
async def run_saver(
|
2586
|
-
self, path: str = None, stream=None, save_state=False, wait: bool = True
|
2587
|
-
):
|
2585
|
+
async def run_saver(self, path: str = None, stream=None, save_state=False, wait: bool = True):
|
2588
2586
|
"""
|
2589
2587
|
Start a task that continually saves to disk.
|
2590
2588
|
|
@@ -2611,7 +2609,7 @@ class Server:
|
|
2611
2609
|
stream=stream,
|
2612
2610
|
save_state=save_state,
|
2613
2611
|
done=done,
|
2614
|
-
)
|
2612
|
+
),
|
2615
2613
|
)
|
2616
2614
|
if wait:
|
2617
2615
|
res = await done.get()
|
@@ -2732,9 +2730,7 @@ class Server:
|
|
2732
2730
|
assert self.node.tick is None
|
2733
2731
|
self.node.tick = 0
|
2734
2732
|
async with self.next_event() as event:
|
2735
|
-
await self.root.set_data(
|
2736
|
-
event, self._init, tock=self.tock, server=self
|
2737
|
-
)
|
2733
|
+
await self.root.set_data(event, self._init, tock=self.tock, server=self)
|
2738
2734
|
|
2739
2735
|
await self.spawn(self._sigterm)
|
2740
2736
|
|
moat/kv/types.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import logging
|
2
3
|
import weakref
|
3
4
|
|
@@ -302,13 +303,11 @@ class CodecEntry(Entry):
|
|
302
303
|
r = dec(v)
|
303
304
|
except Exception as exc:
|
304
305
|
raise ValueError(
|
305
|
-
f"failed decoder at {self.path} on {v!r} with {exc!r}"
|
306
|
+
f"failed decoder at {self.path} on {v!r} with {exc!r}",
|
306
307
|
) from exc
|
307
308
|
else:
|
308
309
|
if r != w:
|
309
|
-
raise ValueError(
|
310
|
-
f"Decoding at {self.path}: {v!r} got {r!r}, not {w!r}"
|
311
|
-
)
|
310
|
+
raise ValueError(f"Decoding at {self.path}: {v!r} got {r!r}, not {w!r}")
|
312
311
|
|
313
312
|
if value is not None and value.encode is not None:
|
314
313
|
if not value["out"]:
|
@@ -319,13 +318,11 @@ class CodecEntry(Entry):
|
|
319
318
|
r = enc(v)
|
320
319
|
except Exception as exc:
|
321
320
|
raise ValueError(
|
322
|
-
f"failed encoder at {self.path} on {v!r} with {exc!r}"
|
321
|
+
f"failed encoder at {self.path} on {v!r} with {exc!r}",
|
323
322
|
) from exc
|
324
323
|
else:
|
325
324
|
if r != w:
|
326
|
-
raise ValueError(
|
327
|
-
f"Encoding at {self.path}: {v!r} got {r!r}, not {w!r}"
|
328
|
-
)
|
325
|
+
raise ValueError(f"Encoding at {self.path}: {v!r} got {r!r}, not {w!r}")
|
329
326
|
|
330
327
|
await super().set(value)
|
331
328
|
self._enc = enc
|
@@ -1,15 +1,13 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: moat-kv
|
3
|
-
Version: 0.70.
|
3
|
+
Version: 0.70.23
|
4
4
|
Summary: A distributed no-master key-value store
|
5
5
|
Author-email: Matthias Urlichs <matthias@urlichs.de>
|
6
6
|
Project-URL: homepage, https://m-o-a-t.org
|
7
|
-
Project-URL: repository, https://github.com/M-o-a-T/moat
|
7
|
+
Project-URL: repository, https://github.com/M-o-a-T/moat
|
8
8
|
Keywords: MoaT
|
9
9
|
Classifier: Development Status :: 4 - Beta
|
10
10
|
Classifier: Intended Audience :: Information Technology
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
13
11
|
Classifier: Framework :: AsyncIO
|
14
12
|
Classifier: Framework :: Trio
|
15
13
|
Classifier: Operating System :: POSIX :: Linux
|
@@ -21,28 +19,27 @@ Classifier: Topic :: Home Automation
|
|
21
19
|
Classifier: Topic :: System :: Distributed Computing
|
22
20
|
Requires-Python: >=3.8
|
23
21
|
Description-Content-Type: text/x-rst
|
24
|
-
License-File: LICENSE
|
25
|
-
|
26
|
-
|
27
|
-
Requires-Dist:
|
28
|
-
Requires-Dist:
|
29
|
-
Requires-Dist:
|
30
|
-
Requires-Dist:
|
31
|
-
Requires-Dist:
|
32
|
-
Requires-Dist:
|
33
|
-
Requires-Dist:
|
34
|
-
Requires-Dist:
|
35
|
-
Requires-Dist:
|
36
|
-
Requires-Dist: moat-
|
37
|
-
Requires-Dist: moat-util (~=0.35.0)
|
22
|
+
License-File: LICENSE.txt
|
23
|
+
Requires-Dist: asyncclick>7.99
|
24
|
+
Requires-Dist: trio>=0.22
|
25
|
+
Requires-Dist: anyio>=4
|
26
|
+
Requires-Dist: range_set>=0.2
|
27
|
+
Requires-Dist: attrs>=22
|
28
|
+
Requires-Dist: asyncserf>=0.16
|
29
|
+
Requires-Dist: asyncactor>=0.24
|
30
|
+
Requires-Dist: asyncscope>=0.10.4
|
31
|
+
Requires-Dist: jsonschema>=2.5
|
32
|
+
Requires-Dist: ruyaml>=0.89
|
33
|
+
Requires-Dist: PyNaCl>=1.3
|
34
|
+
Requires-Dist: moat-lib-diffiehellman~=0.13.4
|
38
35
|
Requires-Dist: psutil
|
39
|
-
Requires-Dist:
|
40
|
-
Requires-Dist:
|
41
|
-
Requires-Dist:
|
42
|
-
Requires-Dist:
|
43
|
-
Requires-Dist: exceptiongroup ; python_version < "3.11"
|
36
|
+
Requires-Dist: simpleeval>=0.9.10
|
37
|
+
Requires-Dist: moat-mqtt~=0.42.2
|
38
|
+
Requires-Dist: moat-util~=0.56.4
|
39
|
+
Requires-Dist: exceptiongroup; python_version < "3.11"
|
44
40
|
Provides-Extra: dev
|
45
|
-
Requires-Dist: moat-src
|
41
|
+
Requires-Dist: moat-src>=0.5.0; extra == "dev"
|
42
|
+
Dynamic: license-file
|
46
43
|
|
47
44
|
=======
|
48
45
|
MoaT-KV
|
@@ -0,0 +1,19 @@
|
|
1
|
+
moat/kv/__init__.py,sha256=TO2TyH5Focv78vDDqtiN1vZVLsVihrOqvHBAlLIgVRA,508
|
2
|
+
moat/kv/_cfg.yaml,sha256=fYMbr4A3-WuXxhqwJIY3AL_t2L_kKrlgJWU2bHry7t8,2249
|
3
|
+
moat/kv/_main.py,sha256=SgI4ef8AQDOC4N4pLRiyaiSiFIzN-J337WIcuC7DPOY,2234
|
4
|
+
moat/kv/client.py,sha256=c8YV0sjpO2XYpNE-fep7fDO2kgsNdShZxgCjohy23CY,34549
|
5
|
+
moat/kv/code.py,sha256=gM7WNsjCfukr7h2fKm1U3zMHN5Wj-_hgy5U817LP9qE,6427
|
6
|
+
moat/kv/codec.py,sha256=1AUNYxCOUJSZfZlny-asNZ0gmz0eaPmQKjr3biNDhWM,284
|
7
|
+
moat/kv/config.py,sha256=cWJ1m8PRwzzapsin1XSDjRtYJCgNN6g7gA9q48luDV8,1093
|
8
|
+
moat/kv/data.py,sha256=oiSGHnrrmJOkxC71bQj1ZsmBsVpE_vPT83IqRuHaNls,5992
|
9
|
+
moat/kv/errors.py,sha256=wmi2OVsO4IeedScGTTFWvECkHLHMRiukoWXLpjI4-Us,16742
|
10
|
+
moat/kv/exceptions.py,sha256=4gRsYa6kuBy1qFYiBUYElup_cvOe7QgPQtryHAYphzo,1849
|
11
|
+
moat/kv/model.py,sha256=il8TjxrvL3EJKTZ88IDx2pJXcaKbXUSwsOIV4lXsW9Q,33390
|
12
|
+
moat/kv/runner.py,sha256=eDXsNFWKidx5HLmP2MGpgRdeTeoL7dCSXLA_BKy55uE,41889
|
13
|
+
moat/kv/server.py,sha256=O-yJiJYT5sQPeku9iTRo-SXqkHBq7OhKpHSA5IbKtvM,94918
|
14
|
+
moat/kv/types.py,sha256=6klFuDHtbhRxrpLOYn1tnDndoRwE0nrolz3tFKOWtd8,14056
|
15
|
+
moat_kv-0.70.23.dist-info/licenses/LICENSE.txt,sha256=L5vKJLVOg5t0CEEPpW9-O_0vzbP0PEjEF06tLvnIDuk,541
|
16
|
+
moat_kv-0.70.23.dist-info/METADATA,sha256=1Cy2_BVrklwB0kxLDVArh59A5K8FQscAtSx8mYhvfKI,3370
|
17
|
+
moat_kv-0.70.23.dist-info/WHEEL,sha256=xcaH6rP_nCxh1LBIPM7Q0uOnzSGjsIye-Q44j_zbzw8,104
|
18
|
+
moat_kv-0.70.23.dist-info/top_level.txt,sha256=pcs9fl5w5AB5GVi4SvBqIVmFrkRwQkVw_dEvW0Q0cSA,5
|
19
|
+
moat_kv-0.70.23.dist-info/RECORD,,
|
@@ -0,0 +1,14 @@
|
|
1
|
+
The code in this repository, and all MoaT submodules it refers to,
|
2
|
+
is part of the MoaT project.
|
3
|
+
|
4
|
+
Unless a submodule's LICENSE.txt states otherwise, all included files are
|
5
|
+
licensed under the LGPL V3, as published by the FSF at
|
6
|
+
https://www.gnu.org/licenses/lgpl-3.0.html .
|
7
|
+
|
8
|
+
In addition to the LGPL's terms, the author(s) respectfully ask all users of
|
9
|
+
this code to contribute any bug fixes or enhancements. Also, please link back to
|
10
|
+
https://M-o-a-T.org.
|
11
|
+
|
12
|
+
Thank you.
|
13
|
+
|
14
|
+
Copyright © 2021 ff.: the MoaT contributor(s), as per the git changelog(s).
|