moat-kv 0.70.22__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.
Files changed (52) hide show
  1. moat/kv/__init__.py +1 -0
  2. moat/kv/_cfg.yaml +97 -0
  3. moat/kv/_main.py +6 -9
  4. moat/kv/client.py +34 -50
  5. moat/kv/code.py +10 -3
  6. moat/kv/codec.py +1 -0
  7. moat/kv/config.py +2 -0
  8. moat/kv/data.py +8 -7
  9. moat/kv/errors.py +17 -9
  10. moat/kv/exceptions.py +1 -7
  11. moat/kv/model.py +16 -24
  12. moat/kv/runner.py +38 -35
  13. moat/kv/server.py +86 -90
  14. moat/kv/types.py +5 -8
  15. {moat_kv-0.70.22.dist-info → moat_kv-0.70.23.dist-info}/METADATA +15 -18
  16. moat_kv-0.70.23.dist-info/RECORD +19 -0
  17. {moat_kv-0.70.22.dist-info → moat_kv-0.70.23.dist-info}/WHEEL +1 -1
  18. moat_kv-0.70.23.dist-info/licenses/LICENSE.txt +14 -0
  19. moat/kv/_config.yaml +0 -98
  20. moat/kv/actor/__init__.py +0 -97
  21. moat/kv/actor/deletor.py +0 -137
  22. moat/kv/auth/__init__.py +0 -446
  23. moat/kv/auth/_test.py +0 -172
  24. moat/kv/auth/password.py +0 -232
  25. moat/kv/auth/root.py +0 -56
  26. moat/kv/backend/__init__.py +0 -66
  27. moat/kv/backend/mqtt.py +0 -74
  28. moat/kv/backend/serf.py +0 -44
  29. moat/kv/command/__init__.py +0 -1
  30. moat/kv/command/acl.py +0 -174
  31. moat/kv/command/auth.py +0 -258
  32. moat/kv/command/code.py +0 -306
  33. moat/kv/command/codec.py +0 -190
  34. moat/kv/command/data.py +0 -274
  35. moat/kv/command/dump/__init__.py +0 -141
  36. moat/kv/command/error.py +0 -156
  37. moat/kv/command/internal.py +0 -257
  38. moat/kv/command/job.py +0 -438
  39. moat/kv/command/log.py +0 -52
  40. moat/kv/command/server.py +0 -115
  41. moat/kv/command/type.py +0 -203
  42. moat/kv/mock/__init__.py +0 -97
  43. moat/kv/mock/mqtt.py +0 -164
  44. moat/kv/mock/serf.py +0 -253
  45. moat/kv/mock/tracer.py +0 -65
  46. moat/kv/obj/__init__.py +0 -636
  47. moat/kv/obj/command.py +0 -246
  48. moat_kv-0.70.22.dist-info/LICENSE +0 -3
  49. moat_kv-0.70.22.dist-info/LICENSE.APACHE2 +0 -202
  50. moat_kv-0.70.22.dist-info/LICENSE.MIT +0 -20
  51. moat_kv-0.70.22.dist-info/RECORD +0 -49
  52. {moat_kv-0.70.22.dist-info → moat_kv-0.70.23.dist-info}/top_level.txt +0 -0
moat/kv/model.py CHANGED
@@ -9,7 +9,7 @@ from __future__ import annotations
9
9
  import weakref
10
10
  from collections import defaultdict
11
11
  from logging import getLogger
12
- from typing import Any, List
12
+ from typing import Any
13
13
 
14
14
  from moat.util import NotGiven, Path, attrdict, create_queue
15
15
  from range_set import RangeSet
@@ -39,9 +39,7 @@ class Node:
39
39
  tick: int = None
40
40
  _present: RangeSet = None # I have these as valid data. Superset of ``._deleted``.
41
41
  _deleted: RangeSet = None # I have these as no-longer-valid data
42
- _reported: RangeSet = (
43
- None # somebody else reported these missing data for this node
44
- )
42
+ _reported: RangeSet = None # somebody else reported these missing data for this node
45
43
  _superseded: RangeSet = None # I know these once existed, but no more.
46
44
  entries: dict = None
47
45
  tock: int = 0 # tock when node was last observed
@@ -371,7 +369,7 @@ class NodeEvent:
371
369
 
372
370
  """
373
371
 
374
- def __init__(self, node: Node, tick: int = None, prev: "NodeEvent" = None):
372
+ def __init__(self, node: Node, tick: int = None, prev: NodeEvent = None):
375
373
  self.node = node
376
374
  if tick is None:
377
375
  tick = node.tick
@@ -524,13 +522,15 @@ class NodeEvent:
524
522
  self.prev = cls.deserialize(msg["prev"], cache=cache)
525
523
  return self
526
524
 
527
- def attach(self, prev: "NodeEvent" = None, server=None):
525
+ def attach(self, prev: NodeEvent = None, server=None):
528
526
  """Copy this node, if necessary, and attach a filtered `prev` chain to it"""
529
527
  if prev is not None:
530
528
  prev = prev.filter(self.node, server=server)
531
529
  if self.prev is not None or prev is not None:
532
530
  self = NodeEvent( # pylint: disable=self-cls-assignment
533
- node=self.node, tick=self.tick, prev=prev
531
+ node=self.node,
532
+ tick=self.tick,
533
+ prev=prev,
534
534
  )
535
535
  return self
536
536
 
@@ -538,9 +538,7 @@ class NodeEvent:
538
538
  class UpdateEvent:
539
539
  """Represents an event which updates something."""
540
540
 
541
- def __init__(
542
- self, event: NodeEvent, entry: "Entry", new_value, old_value=NotGiven, tock=None
543
- ):
541
+ def __init__(self, event: NodeEvent, entry: Entry, new_value, old_value=NotGiven, tock=None):
544
542
  self.event = event
545
543
  self.entry = entry
546
544
  self.new_value = new_value
@@ -611,10 +609,10 @@ class UpdateEvent:
611
609
  class Entry:
612
610
  """This class represents one key/value pair"""
613
611
 
614
- _parent: "Entry" = None
612
+ _parent: Entry = None
615
613
  name: str = None
616
- _path: List[str] = None
617
- _root: "Entry" = None
614
+ _path: list[str] = None
615
+ _root: Entry = None
618
616
  chain: NodeEvent = None
619
617
  SUBTYPE = None
620
618
  SUBTYPES = {}
@@ -622,7 +620,7 @@ class Entry:
622
620
 
623
621
  monitors = None
624
622
 
625
- def __init__(self, name: str, parent: "Entry", tock=None):
623
+ def __init__(self, name: str, parent: Entry, tock=None):
626
624
  self.name = name
627
625
  self._sub = {}
628
626
  self.monitors = set()
@@ -632,7 +630,7 @@ class Entry:
632
630
  parent._add_subnode(self)
633
631
  self._parent = weakref.ref(parent)
634
632
 
635
- def _add_subnode(self, child: "Entry"):
633
+ def _add_subnode(self, child: Entry):
636
634
  self._sub[child.name] = child
637
635
 
638
636
  def __hash__(self):
@@ -904,9 +902,7 @@ class Entry:
904
902
  if not loading:
905
903
  logger.warning("*** inconsistency ***")
906
904
  logger.warning("Node: %s", self.path)
907
- logger.warning(
908
- "Current: %s :%s: %r", self.chain, self.tock, self._data
909
- )
905
+ logger.warning("Current: %s :%s: %r", self.chain, self.tock, self._data)
910
906
  logger.warning("New: %s :%s: %r", evt.event, evt.tock, evt_val)
911
907
  if evt.tock < self.tock:
912
908
  if not loading:
@@ -934,9 +930,7 @@ class Entry:
934
930
  n.seen(t, self)
935
931
  await self.updated(evt)
936
932
 
937
- async def walk(
938
- self, proc, acl=None, max_depth=-1, min_depth=0, _depth=0, full=False
939
- ):
933
+ async def walk(self, proc, acl=None, max_depth=-1, min_depth=0, _depth=0, full=False):
940
934
  """
941
935
  Call coroutine ``proc`` on this node and all its children).
942
936
 
@@ -960,9 +954,7 @@ class Entry:
960
954
  if k is None and not full:
961
955
  continue
962
956
  a = acl.step(k) if acl is not None else None
963
- await v.walk(
964
- proc, acl=a, max_depth=max_depth, min_depth=min_depth, _depth=_depth
965
- )
957
+ await v.walk(proc, acl=a, max_depth=max_depth, min_depth=min_depth, _depth=_depth)
966
958
 
967
959
  def serialize(self, chop_path=0, nchain=2, conv=None):
968
960
  """Serialize this entry for msgpack.
moat/kv/runner.py CHANGED
@@ -3,6 +3,7 @@ This module's job is to run code, resp. to keep it running.
3
3
 
4
4
 
5
5
  """
6
+ from __future__ import annotations
6
7
 
7
8
  import time
8
9
  from collections.abc import Mapping
@@ -131,6 +132,7 @@ for _c in (
131
132
 
132
133
  _CLASSES["NotGiven"] = NotGiven # ellipsis
133
134
 
135
+
134
136
  class CallAdmin:
135
137
  """
136
138
  This class collects some standard tasks which async MoaT-KV-embedded
@@ -169,9 +171,9 @@ class CallAdmin:
169
171
  """Called by the runner to actually execute the code."""
170
172
  self._logger.debug("Start %s with %s", self._runner._path, self._runner.code)
171
173
  async with (
172
- anyio.create_task_group() as tg,
173
- AsyncExitStack() as stack,
174
- ):
174
+ anyio.create_task_group() as tg,
175
+ AsyncExitStack() as stack,
176
+ ):
175
177
  self._stack = stack
176
178
  self._taskgroup = tg
177
179
  self._runner.scope = sc = tg.cancel_scope
@@ -249,7 +251,7 @@ class CallAdmin:
249
251
  path = self._path
250
252
  r = await self._err.record_error("run", path, **kw)
251
253
  await self._err.root.wait_chain(r.chain)
252
- raise ErrorRecorded()
254
+ raise ErrorRecorded
253
255
 
254
256
  async def open_context(self, ctx):
255
257
  return await self._stack.enter_async_context(ctx)
@@ -294,9 +296,7 @@ class CallAdmin:
294
296
  async with slf.client.watch(path, **kw) as watcher:
295
297
  yield watcher
296
298
  else:
297
- raise RuntimeError(
298
- f"What should I do with a path marked {path.mark !r}?"
299
- )
299
+ raise RuntimeError(f"What should I do with a path marked {path.mark!r}?")
300
300
 
301
301
  with anyio.CancelScope() as sc:
302
302
  slf.scope = sc
@@ -318,9 +318,7 @@ class CallAdmin:
318
318
  elif msg.get("state", "") == "uptodate":
319
319
  slf.admin._n_watch_seen += 1
320
320
  if slf.admin._n_watch_seen == slf.admin._n_watch:
321
- await slf.runner.send_event(
322
- ReadyMsg(slf.admin._n_watch_seen)
323
- )
321
+ await slf.runner.send_event(ReadyMsg(slf.admin._n_watch_seen))
324
322
 
325
323
  def cancel(slf):
326
324
  if slf.scope is None:
@@ -361,7 +359,7 @@ class CallAdmin:
361
359
  if path.mark == "r":
362
360
  return await self.send(path, value)
363
361
  elif path.mark:
364
- raise RuntimeError(f"What should I do with a path marked {path.mark !r}")
362
+ raise RuntimeError(f"What should I do with a path marked {path.mark!r}")
365
363
 
366
364
  if isinstance(path, (tuple, list)):
367
365
  path = Path.build(path)
@@ -556,7 +554,9 @@ class RunnerEntry(AttrClientEntry):
556
554
  raise RuntimeError(f"already running on {state.node}")
557
555
  code = self.root.code.follow(self.code, create=False)
558
556
  data = combine_dict(
559
- self.data or {}, {} if code.value is NotGiven else code.value.get("default", {}), deep=True
557
+ self.data or {},
558
+ {} if code.value is NotGiven else code.value.get("default", {}),
559
+ deep=True,
560
560
  )
561
561
 
562
562
  if code.is_async:
@@ -574,9 +574,7 @@ class RunnerEntry(AttrClientEntry):
574
574
 
575
575
  await state.save(wait=True)
576
576
  if state.node != state.root.name:
577
- raise RuntimeError(
578
- "Rudely taken away from us.", state.node, state.root.name
579
- )
577
+ raise RuntimeError("Rudely taken away from us.", state.node, state.root.name)
580
578
 
581
579
  data["_self"] = calls = CallAdmin(self, state, data)
582
580
  res = await calls._run(code, data)
@@ -600,7 +598,11 @@ class RunnerEntry(AttrClientEntry):
600
598
  c, self._comment = self._comment, None
601
599
  with anyio.move_on_after(5, shield=True):
602
600
  r = await self.root.err.record_error(
603
- "run", self._path, exc=exc, data=self.data, comment=c
601
+ "run",
602
+ self._path,
603
+ exc=exc,
604
+ data=self.data,
605
+ comment=c,
604
606
  )
605
607
  if r is not None:
606
608
  await self.root.err.wait_chain(r.chain)
@@ -803,7 +805,9 @@ class StateEntry(AttrClientEntry):
803
805
  self.node = None
804
806
  self.backoff = min(20, self.backoff + 1)
805
807
  await self.root.runner.err.record_error(
806
- "run", self.runner._path, message="Runner restarted"
808
+ "run",
809
+ self.runner._path,
810
+ message="Runner restarted",
807
811
  )
808
812
  await self.save()
809
813
 
@@ -848,7 +852,7 @@ class StateEntry(AttrClientEntry):
848
852
  return
849
853
  elif self.node is None or n == self.root.runner.name:
850
854
  # Owch. Our job got taken away from us.
851
- run._comment = f"Cancel: Node set to {self.node !r}"
855
+ run._comment = f"Cancel: Node set to {self.node!r}"
852
856
  run.scope.cancel()
853
857
  elif n is not None:
854
858
  logger.warning(
@@ -918,7 +922,8 @@ class StateRoot(MirrorRoot):
918
922
  await self.update(val)
919
923
  else:
920
924
  await self.client.msg_send(
921
- "run", {"group": self.runner.group, "time": t, "node": self.name}
925
+ "run",
926
+ {"group": self.runner.group, "time": t, "node": self.name},
922
927
  )
923
928
 
924
929
 
@@ -961,9 +966,7 @@ class _BaseRunnerRoot(ClientRoot):
961
966
  cfg_ = client._cfg["runner"]
962
967
  else:
963
968
  cfg_ = combine_dict(cfg, client._cfg["runner"])
964
- return await super().as_handler(
965
- client, subpath=subpath, _subpath=subpath, cfg=cfg_, **kw
966
- )
969
+ return await super().as_handler(client, subpath=subpath, _subpath=subpath, cfg=cfg_, **kw)
967
970
 
968
971
  async def run_starting(self):
969
972
  from .code import CodeRoot
@@ -984,7 +987,10 @@ class _BaseRunnerRoot(ClientRoot):
984
987
 
985
988
  async def _state_runner(self):
986
989
  self.state = await StateRoot.as_handler(
987
- self.client, cfg=self._cfg, subpath=self._x_subpath, key="state"
990
+ self.client,
991
+ cfg=self._cfg,
992
+ subpath=self._x_subpath,
993
+ key="state",
988
994
  )
989
995
 
990
996
  @property
@@ -1014,7 +1020,7 @@ class _BaseRunnerRoot(ClientRoot):
1014
1020
 
1015
1021
  Its job is to control which tasks are started.
1016
1022
  """
1017
- raise RuntimeError("You want to override me." "")
1023
+ raise RuntimeError("You want to override me.")
1018
1024
 
1019
1025
  async def trigger_rescan(self):
1020
1026
  """Tell the _run_actor task to rescan our job list prematurely"""
@@ -1096,9 +1102,7 @@ class AnyRunnerRoot(_BaseRunnerRoot):
1096
1102
  def __init__(self, *a, **kw):
1097
1103
  super().__init__(*a, **kw)
1098
1104
  self.group = (
1099
- P(self.client.config.server["root"]) + P(self._cfg["name"])
1100
- | "any"
1101
- | self._path[-1]
1105
+ P(self.client.config.server["root"]) + P(self._cfg["name"]) | "any" | self._path[-1]
1102
1106
  )
1103
1107
 
1104
1108
  def get_node(self, name):
@@ -1116,7 +1120,10 @@ class AnyRunnerRoot(_BaseRunnerRoot):
1116
1120
  Monitor the Actor state, run a :meth:`_run_now` subtask whenever we're 'it'.
1117
1121
  """
1118
1122
  async with ClientActor(
1119
- self.client, self.name, topic=self.group, cfg=self._cfg["actor"]
1123
+ self.client,
1124
+ self.name,
1125
+ topic=self.group,
1126
+ cfg=self._cfg["actor"],
1120
1127
  ) as act:
1121
1128
  self._act = act
1122
1129
 
@@ -1176,7 +1183,7 @@ class AnyRunnerRoot(_BaseRunnerRoot):
1176
1183
  self._stale_times.append(cur)
1177
1184
  if self._stale_times[0] > cur - self.max_age:
1178
1185
  return
1179
- if len(self._stale_times) <= 2*self._cfg["actor"]["n_hosts"]+1:
1186
+ if len(self._stale_times) <= 2 * self._cfg["actor"]["n_hosts"] + 1:
1180
1187
  return
1181
1188
  cut = self._stale_times.pop(0)
1182
1189
 
@@ -1278,9 +1285,7 @@ class SingleRunnerRoot(_BaseRunnerRoot):
1278
1285
  async with anyio.create_task_group() as tg:
1279
1286
  age_q = create_queue(1)
1280
1287
 
1281
- async with ClientActor(
1282
- self.client, self.name, topic=self.group, cfg=self._cfg
1283
- ) as act:
1288
+ async with ClientActor(self.client, self.name, topic=self.group, cfg=self._cfg) as act:
1284
1289
  self._act = act
1285
1290
  tg.start_soon(self._age_notifier, age_q)
1286
1291
  await self.spawn(self._run_now)
@@ -1330,9 +1335,7 @@ class AllRunnerRoot(SingleRunnerRoot):
1330
1335
  def __init__(self, *a, **kw):
1331
1336
  super().__init__(*a, **kw)
1332
1337
  self.group = (
1333
- P(self.client.config.server["root"]) + P(self._cfg["name"])
1334
- | "all"
1335
- | self._path[-1]
1338
+ P(self.client.config.server["root"]) + P(self._cfg["name"]) | "all" | self._path[-1]
1336
1339
  )
1337
1340
 
1338
1341
  async def _state_runner(self):