moat-kv 0.70.22__py3-none-any.whl → 0.70.24__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.
Files changed (142) hide show
  1. build/lib/docs/source/conf.py +201 -0
  2. build/lib/examples/pathify.py +45 -0
  3. build/lib/moat/kv/__init__.py +19 -0
  4. build/lib/moat/kv/_cfg.yaml +97 -0
  5. build/lib/moat/kv/_main.py +91 -0
  6. build/lib/moat/kv/actor/__init__.py +98 -0
  7. build/lib/moat/kv/actor/deletor.py +139 -0
  8. build/lib/moat/kv/auth/__init__.py +444 -0
  9. build/lib/moat/kv/auth/_test.py +166 -0
  10. build/lib/moat/kv/auth/password.py +234 -0
  11. build/lib/moat/kv/auth/root.py +58 -0
  12. build/lib/moat/kv/backend/__init__.py +67 -0
  13. build/lib/moat/kv/backend/mqtt.py +74 -0
  14. build/lib/moat/kv/backend/serf.py +45 -0
  15. build/lib/moat/kv/client.py +1025 -0
  16. build/lib/moat/kv/code.py +236 -0
  17. build/lib/moat/kv/codec.py +11 -0
  18. build/lib/moat/kv/command/__init__.py +1 -0
  19. build/lib/moat/kv/command/acl.py +180 -0
  20. build/lib/moat/kv/command/auth.py +261 -0
  21. build/lib/moat/kv/command/code.py +293 -0
  22. build/lib/moat/kv/command/codec.py +186 -0
  23. build/lib/moat/kv/command/data.py +265 -0
  24. build/lib/moat/kv/command/dump/__init__.py +143 -0
  25. build/lib/moat/kv/command/error.py +149 -0
  26. build/lib/moat/kv/command/internal.py +248 -0
  27. build/lib/moat/kv/command/job.py +433 -0
  28. build/lib/moat/kv/command/log.py +53 -0
  29. build/lib/moat/kv/command/server.py +114 -0
  30. build/lib/moat/kv/command/type.py +201 -0
  31. build/lib/moat/kv/config.py +46 -0
  32. build/lib/moat/kv/data.py +216 -0
  33. build/lib/moat/kv/errors.py +561 -0
  34. build/lib/moat/kv/exceptions.py +126 -0
  35. build/lib/moat/kv/mock/__init__.py +101 -0
  36. build/lib/moat/kv/mock/mqtt.py +159 -0
  37. build/lib/moat/kv/mock/serf.py +250 -0
  38. build/lib/moat/kv/mock/tracer.py +63 -0
  39. build/lib/moat/kv/model.py +1069 -0
  40. build/lib/moat/kv/obj/__init__.py +646 -0
  41. build/lib/moat/kv/obj/command.py +241 -0
  42. build/lib/moat/kv/runner.py +1347 -0
  43. build/lib/moat/kv/server.py +2809 -0
  44. build/lib/moat/kv/types.py +513 -0
  45. debian/moat-kv/usr/lib/python3/dist-packages/docs/source/conf.py +201 -0
  46. debian/moat-kv/usr/lib/python3/dist-packages/examples/pathify.py +45 -0
  47. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/__init__.py +19 -0
  48. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/_cfg.yaml +97 -0
  49. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/_main.py +91 -0
  50. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/actor/__init__.py +98 -0
  51. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/actor/deletor.py +139 -0
  52. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/__init__.py +444 -0
  53. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/_test.py +166 -0
  54. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/password.py +234 -0
  55. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/root.py +58 -0
  56. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/__init__.py +67 -0
  57. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/mqtt.py +74 -0
  58. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/serf.py +45 -0
  59. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/client.py +1025 -0
  60. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/code.py +236 -0
  61. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/codec.py +11 -0
  62. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/__init__.py +1 -0
  63. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/acl.py +180 -0
  64. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/auth.py +261 -0
  65. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/code.py +293 -0
  66. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/codec.py +186 -0
  67. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/data.py +265 -0
  68. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/dump/__init__.py +143 -0
  69. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/error.py +149 -0
  70. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/internal.py +248 -0
  71. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/job.py +433 -0
  72. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/log.py +53 -0
  73. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/server.py +114 -0
  74. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/type.py +201 -0
  75. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/config.py +46 -0
  76. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/data.py +216 -0
  77. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/errors.py +561 -0
  78. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/exceptions.py +126 -0
  79. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/__init__.py +101 -0
  80. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/mqtt.py +159 -0
  81. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/serf.py +250 -0
  82. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/tracer.py +63 -0
  83. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/model.py +1069 -0
  84. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/obj/__init__.py +646 -0
  85. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/obj/command.py +241 -0
  86. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/runner.py +1347 -0
  87. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/server.py +2809 -0
  88. debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/types.py +513 -0
  89. docs/source/conf.py +201 -0
  90. examples/pathify.py +45 -0
  91. moat/kv/__init__.py +1 -0
  92. moat/kv/_cfg.yaml +97 -0
  93. moat/kv/_main.py +6 -9
  94. moat/kv/actor/__init__.py +2 -1
  95. moat/kv/actor/deletor.py +3 -1
  96. moat/kv/auth/__init__.py +8 -10
  97. moat/kv/auth/_test.py +6 -12
  98. moat/kv/auth/password.py +2 -0
  99. moat/kv/auth/root.py +2 -0
  100. moat/kv/backend/__init__.py +1 -0
  101. moat/kv/backend/mqtt.py +3 -3
  102. moat/kv/backend/serf.py +1 -0
  103. moat/kv/client.py +34 -50
  104. moat/kv/code.py +10 -3
  105. moat/kv/codec.py +1 -0
  106. moat/kv/command/acl.py +12 -6
  107. moat/kv/command/auth.py +5 -2
  108. moat/kv/command/code.py +10 -23
  109. moat/kv/command/codec.py +10 -14
  110. moat/kv/command/data.py +12 -21
  111. moat/kv/command/dump/__init__.py +4 -2
  112. moat/kv/command/error.py +5 -12
  113. moat/kv/command/internal.py +6 -15
  114. moat/kv/command/job.py +26 -31
  115. moat/kv/command/log.py +1 -0
  116. moat/kv/command/server.py +2 -3
  117. moat/kv/command/type.py +26 -28
  118. moat/kv/config.py +2 -0
  119. moat/kv/data.py +8 -7
  120. moat/kv/errors.py +17 -9
  121. moat/kv/exceptions.py +1 -7
  122. moat/kv/mock/__init__.py +9 -5
  123. moat/kv/mock/mqtt.py +7 -12
  124. moat/kv/mock/serf.py +6 -9
  125. moat/kv/mock/tracer.py +2 -4
  126. moat/kv/model.py +16 -24
  127. moat/kv/obj/__init__.py +30 -20
  128. moat/kv/obj/command.py +7 -12
  129. moat/kv/runner.py +38 -35
  130. moat/kv/server.py +86 -90
  131. moat/kv/types.py +5 -8
  132. {moat_kv-0.70.22.dist-info → moat_kv-0.70.24.dist-info}/METADATA +15 -18
  133. moat_kv-0.70.24.dist-info/RECORD +137 -0
  134. {moat_kv-0.70.22.dist-info → moat_kv-0.70.24.dist-info}/WHEEL +1 -1
  135. moat_kv-0.70.24.dist-info/licenses/LICENSE.txt +14 -0
  136. moat_kv-0.70.24.dist-info/top_level.txt +9 -0
  137. moat/kv/_config.yaml +0 -98
  138. moat_kv-0.70.22.dist-info/LICENSE +0 -3
  139. moat_kv-0.70.22.dist-info/LICENSE.APACHE2 +0 -202
  140. moat_kv-0.70.22.dist-info/LICENSE.MIT +0 -20
  141. moat_kv-0.70.22.dist-info/RECORD +0 -49
  142. moat_kv-0.70.22.dist-info/top_level.txt +0 -1
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, yload
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, Dict
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, acl=client.acl, acl_key="x", create=True, nulls_ok=client.nulls_ok
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, nchain=nchain, conv=conv
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: "Server", stream: Stream):
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, acl=acl2, acl_key=mode, nulls_ok=False, create=None
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, acl=self.acl, acl_key="e", create=False, nulls_ok=_nulls_ok
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, nchain=msg.get("nchain", 0), conv=self.conv
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, create=False, acl=self.acl, acl_key="r", nulls_ok=_nulls_ok
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 !r} not {msg.chain !r} for {msg.path}"
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, acl=self.acl, acl_key="d", nulls_ok=self.nulls_ok
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", self._client_nr, repr(msg)
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 ``_config.yaml`` for default values.
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
- CFG = yload(FPath(__file__).parent / "_config.yaml")["kv"]
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: Dict[str, Node] = {}
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", iter=False, nchain=-1, nodes=nodes.serialize()
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, r, cache=self.node_cache, nulls_ok=True
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, r, cache=self.node_cache, nulls_ok=True
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, path: str = None, stream=None, done: ValueEvent = None, save_state=False
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 EnvironmentError as err:
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
1
+ Metadata-Version: 2.4
2
2
  Name: moat-kv
3
- Version: 0.70.22
3
+ Version: 0.70.24
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-kv
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
- License-File: LICENSE.APACHE2
26
- License-File: LICENSE.MIT
27
- Requires-Dist: PyNaCl>=1.3
22
+ License-File: LICENSE.txt
23
+ Requires-Dist: asyncclick>7.99
24
+ Requires-Dist: trio>=0.22
28
25
  Requires-Dist: anyio>=4
26
+ Requires-Dist: range_set>=0.2
27
+ Requires-Dist: attrs>=22
28
+ Requires-Dist: asyncserf>=0.16
29
29
  Requires-Dist: asyncactor>=0.24
30
- Requires-Dist: asyncclick>7.99
31
30
  Requires-Dist: asyncscope>=0.10.4
32
- Requires-Dist: asyncserf>=0.16
33
- Requires-Dist: attrs>=22
34
31
  Requires-Dist: jsonschema>=2.5
35
- Requires-Dist: moat-lib-diffiehellman~=0.13.1.6
36
- Requires-Dist: moat-mqtt~=0.39.4
37
- Requires-Dist: moat-util>=0.51.3
38
- Requires-Dist: psutil
39
- Requires-Dist: range-set>=0.2
40
32
  Requires-Dist: ruyaml>=0.89
33
+ Requires-Dist: PyNaCl>=1.3
34
+ Requires-Dist: moat-lib-diffiehellman~=0.13.4
35
+ Requires-Dist: psutil
41
36
  Requires-Dist: simpleeval>=0.9.10
42
- Requires-Dist: trio>=0.22
37
+ Requires-Dist: moat-mqtt~=0.42.3
38
+ Requires-Dist: moat-util~=0.56.4
43
39
  Requires-Dist: exceptiongroup; python_version < "3.11"
44
40
  Provides-Extra: dev
45
41
  Requires-Dist: moat-src>=0.5.0; extra == "dev"
42
+ Dynamic: license-file
46
43
 
47
44
  =======
48
45
  MoaT-KV