moat-kv 0.70.24__py3-none-any.whl → 0.71.6__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 +6 -7
- moat/kv/_cfg.yaml +5 -8
- moat/kv/actor/__init__.py +2 -1
- moat/kv/actor/deletor.py +4 -1
- moat/kv/auth/__init__.py +12 -13
- moat/kv/auth/_test.py +4 -1
- moat/kv/auth/password.py +11 -7
- moat/kv/backend/mqtt.py +4 -8
- moat/kv/client.py +20 -39
- moat/kv/code.py +3 -3
- moat/kv/command/data.py +4 -3
- moat/kv/command/dump/__init__.py +29 -29
- moat/kv/command/internal.py +2 -3
- moat/kv/command/job.py +1 -2
- moat/kv/command/type.py +3 -6
- moat/kv/data.py +9 -8
- moat/kv/errors.py +16 -8
- moat/kv/mock/__init__.py +2 -12
- moat/kv/model.py +28 -32
- moat/kv/obj/__init__.py +3 -3
- moat/kv/obj/command.py +3 -3
- moat/kv/runner.py +4 -5
- moat/kv/server.py +106 -126
- moat/kv/types.py +8 -6
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.6.dist-info}/METADATA +7 -6
- moat_kv-0.71.6.dist-info/RECORD +47 -0
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.6.dist-info}/WHEEL +1 -1
- moat_kv-0.71.6.dist-info/licenses/LICENSE +3 -0
- moat_kv-0.71.6.dist-info/licenses/LICENSE.APACHE2 +202 -0
- moat_kv-0.71.6.dist-info/licenses/LICENSE.MIT +20 -0
- moat_kv-0.71.6.dist-info/top_level.txt +1 -0
- build/lib/docs/source/conf.py +0 -201
- build/lib/examples/pathify.py +0 -45
- build/lib/moat/kv/__init__.py +0 -19
- build/lib/moat/kv/_cfg.yaml +0 -97
- build/lib/moat/kv/_main.py +0 -91
- build/lib/moat/kv/actor/__init__.py +0 -98
- build/lib/moat/kv/actor/deletor.py +0 -139
- build/lib/moat/kv/auth/__init__.py +0 -444
- build/lib/moat/kv/auth/_test.py +0 -166
- build/lib/moat/kv/auth/password.py +0 -234
- build/lib/moat/kv/auth/root.py +0 -58
- build/lib/moat/kv/backend/__init__.py +0 -67
- build/lib/moat/kv/backend/mqtt.py +0 -74
- build/lib/moat/kv/backend/serf.py +0 -45
- build/lib/moat/kv/client.py +0 -1025
- build/lib/moat/kv/code.py +0 -236
- build/lib/moat/kv/codec.py +0 -11
- build/lib/moat/kv/command/__init__.py +0 -1
- build/lib/moat/kv/command/acl.py +0 -180
- build/lib/moat/kv/command/auth.py +0 -261
- build/lib/moat/kv/command/code.py +0 -293
- build/lib/moat/kv/command/codec.py +0 -186
- build/lib/moat/kv/command/data.py +0 -265
- build/lib/moat/kv/command/dump/__init__.py +0 -143
- build/lib/moat/kv/command/error.py +0 -149
- build/lib/moat/kv/command/internal.py +0 -248
- build/lib/moat/kv/command/job.py +0 -433
- build/lib/moat/kv/command/log.py +0 -53
- build/lib/moat/kv/command/server.py +0 -114
- build/lib/moat/kv/command/type.py +0 -201
- build/lib/moat/kv/config.py +0 -46
- build/lib/moat/kv/data.py +0 -216
- build/lib/moat/kv/errors.py +0 -561
- build/lib/moat/kv/exceptions.py +0 -126
- build/lib/moat/kv/mock/__init__.py +0 -101
- build/lib/moat/kv/mock/mqtt.py +0 -159
- build/lib/moat/kv/mock/serf.py +0 -250
- build/lib/moat/kv/mock/tracer.py +0 -63
- build/lib/moat/kv/model.py +0 -1069
- build/lib/moat/kv/obj/__init__.py +0 -646
- build/lib/moat/kv/obj/command.py +0 -241
- build/lib/moat/kv/runner.py +0 -1347
- build/lib/moat/kv/server.py +0 -2809
- build/lib/moat/kv/types.py +0 -513
- debian/moat-kv/usr/lib/python3/dist-packages/docs/source/conf.py +0 -201
- debian/moat-kv/usr/lib/python3/dist-packages/examples/pathify.py +0 -45
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/__init__.py +0 -19
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/_cfg.yaml +0 -97
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/_main.py +0 -91
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/actor/__init__.py +0 -98
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/actor/deletor.py +0 -139
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/__init__.py +0 -444
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/_test.py +0 -166
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/password.py +0 -234
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/auth/root.py +0 -58
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/__init__.py +0 -67
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/mqtt.py +0 -74
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/serf.py +0 -45
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/client.py +0 -1025
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/code.py +0 -236
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/codec.py +0 -11
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/__init__.py +0 -1
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/acl.py +0 -180
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/auth.py +0 -261
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/code.py +0 -293
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/codec.py +0 -186
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/data.py +0 -265
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/dump/__init__.py +0 -143
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/error.py +0 -149
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/internal.py +0 -248
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/job.py +0 -433
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/log.py +0 -53
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/server.py +0 -114
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/command/type.py +0 -201
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/config.py +0 -46
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/data.py +0 -216
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/errors.py +0 -561
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/exceptions.py +0 -126
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/__init__.py +0 -101
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/mqtt.py +0 -159
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/serf.py +0 -250
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/tracer.py +0 -63
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/model.py +0 -1069
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/obj/__init__.py +0 -646
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/obj/command.py +0 -241
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/runner.py +0 -1347
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/server.py +0 -2809
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/types.py +0 -513
- docs/source/conf.py +0 -201
- examples/pathify.py +0 -45
- moat/kv/backend/serf.py +0 -45
- moat/kv/codec.py +0 -11
- moat/kv/mock/serf.py +0 -250
- moat_kv-0.70.24.dist-info/RECORD +0 -137
- moat_kv-0.70.24.dist-info/top_level.txt +0 -9
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.6.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,101 +0,0 @@
|
|
1
|
-
# from asyncclick.testing import CliRunner
|
2
|
-
from __future__ import annotations
|
3
|
-
import io
|
4
|
-
import logging
|
5
|
-
import shlex
|
6
|
-
import socket
|
7
|
-
import sys
|
8
|
-
from pathlib import Path
|
9
|
-
|
10
|
-
import attr
|
11
|
-
from asyncscope import main_scope, scope
|
12
|
-
from moat.src.test import run # pylint:disable=import-error,no-name-in-module
|
13
|
-
from moat.util import ( # pylint:disable=no-name-in-module
|
14
|
-
CFG,
|
15
|
-
OptCtx,
|
16
|
-
attrdict,
|
17
|
-
combine_dict,
|
18
|
-
ensure_cfg,
|
19
|
-
list_ext,
|
20
|
-
load_ext,
|
21
|
-
wrap_main,
|
22
|
-
yload,
|
23
|
-
)
|
24
|
-
|
25
|
-
from moat.kv.client import _scoped_client, client_scope
|
26
|
-
|
27
|
-
logger = logging.getLogger(__name__)
|
28
|
-
try:
|
29
|
-
from contextlib import asynccontextmanager
|
30
|
-
except ImportError:
|
31
|
-
from async_generator import asynccontextmanager
|
32
|
-
|
33
|
-
ensure_cfg("moat.kv")
|
34
|
-
|
35
|
-
|
36
|
-
@attr.s
|
37
|
-
class S:
|
38
|
-
tg = attr.ib()
|
39
|
-
client_ctx = attr.ib()
|
40
|
-
s = attr.ib(factory=list) # servers
|
41
|
-
c = attr.ib(factory=list) # clients
|
42
|
-
_seq = 1
|
43
|
-
|
44
|
-
async def ready(self, i=None):
|
45
|
-
if i is not None:
|
46
|
-
await self.s[i].is_ready
|
47
|
-
return self.s[i]
|
48
|
-
for s in self.s:
|
49
|
-
if s is not None:
|
50
|
-
await s.is_ready
|
51
|
-
return self.s
|
52
|
-
|
53
|
-
def __iter__(self):
|
54
|
-
return iter(self.s)
|
55
|
-
|
56
|
-
@asynccontextmanager
|
57
|
-
async def client(self, i: int = 0, **kv):
|
58
|
-
"""Get a (new) client for the i'th server."""
|
59
|
-
await self.s[i].is_serving
|
60
|
-
self._seq += 1
|
61
|
-
for host, port, *_ in self.s[i].ports:
|
62
|
-
if host != "::" and host[0] == ":":
|
63
|
-
continue
|
64
|
-
try:
|
65
|
-
cfg = combine_dict(
|
66
|
-
dict(conn=dict(host=host, port=port, ssl=self.client_ctx, **kv)),
|
67
|
-
CFG["kv"],
|
68
|
-
)
|
69
|
-
|
70
|
-
async def scc(s, **cfg):
|
71
|
-
scope.requires(s._scope)
|
72
|
-
return await _scoped_client(scope.name, **cfg)
|
73
|
-
|
74
|
-
async with scope.using_scope():
|
75
|
-
c = await scope.service(
|
76
|
-
f"moat.kv.client.{i}.{self._seq}",
|
77
|
-
scc,
|
78
|
-
self.s[i],
|
79
|
-
**cfg,
|
80
|
-
)
|
81
|
-
yield c
|
82
|
-
return
|
83
|
-
except socket.gaierror:
|
84
|
-
pass
|
85
|
-
raise RuntimeError("Duh? no connection")
|
86
|
-
|
87
|
-
async def run(self, *args, do_stdout=True):
|
88
|
-
h = p = None
|
89
|
-
for s in self.s:
|
90
|
-
for h, p, *_ in s.ports:
|
91
|
-
if h[0] != ":":
|
92
|
-
break
|
93
|
-
else:
|
94
|
-
continue
|
95
|
-
break
|
96
|
-
if len(args) == 1:
|
97
|
-
args = args[0]
|
98
|
-
if isinstance(args, str):
|
99
|
-
args = args.split(" ")
|
100
|
-
async with scope.using_scope():
|
101
|
-
return await run("-VV", "kv", "-h", h, "-p", p, *args, do_stdout=do_stdout)
|
build/lib/moat/kv/mock/mqtt.py
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
import copy
|
3
|
-
import logging
|
4
|
-
import os
|
5
|
-
import time
|
6
|
-
from contextlib import AsyncExitStack, asynccontextmanager
|
7
|
-
from functools import partial
|
8
|
-
|
9
|
-
import anyio
|
10
|
-
from unittest import mock
|
11
|
-
import trio
|
12
|
-
from asyncscope import main_scope, scope
|
13
|
-
from moat.mqtt.broker import create_broker
|
14
|
-
from moat.util import NotGiven, attrdict, combine_dict
|
15
|
-
|
16
|
-
from moat.kv.mock import S
|
17
|
-
from moat.kv.server import Server
|
18
|
-
|
19
|
-
from . import CFG
|
20
|
-
|
21
|
-
logger = logging.getLogger(__name__)
|
22
|
-
|
23
|
-
otm = time.time
|
24
|
-
|
25
|
-
PORT = 40000 + (os.getpid() + 10) % 10000
|
26
|
-
|
27
|
-
broker_cfg = {
|
28
|
-
"listeners": {"default": {"type": "tcp", "bind": f"127.0.0.1:{PORT}"}},
|
29
|
-
"timeout-disconnect-delay": 2,
|
30
|
-
"auth": {"allow-anonymous": True, "password-file": None},
|
31
|
-
}
|
32
|
-
|
33
|
-
URI = f"mqtt://127.0.0.1:{PORT}/"
|
34
|
-
|
35
|
-
|
36
|
-
@asynccontextmanager
|
37
|
-
async def stdtest(n=1, run=True, ssl=False, tocks=20, **kw):
|
38
|
-
C_OUT = CFG.get("_stdout", NotGiven)
|
39
|
-
if C_OUT is not NotGiven:
|
40
|
-
del CFG["_stdout"]
|
41
|
-
TESTCFG = copy.deepcopy(CFG["kv"])
|
42
|
-
TESTCFG.server.port = None
|
43
|
-
TESTCFG.root = "test"
|
44
|
-
if C_OUT is not NotGiven:
|
45
|
-
CFG["_stdout"] = C_OUT
|
46
|
-
TESTCFG["_stdout"] = C_OUT
|
47
|
-
|
48
|
-
if ssl:
|
49
|
-
import ssl
|
50
|
-
|
51
|
-
import trustme
|
52
|
-
|
53
|
-
ca = trustme.CA()
|
54
|
-
cert = ca.issue_server_cert("127.0.0.1")
|
55
|
-
server_ctx = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
|
56
|
-
client_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
|
57
|
-
ca.configure_trust(client_ctx)
|
58
|
-
cert.configure_cert(server_ctx)
|
59
|
-
else:
|
60
|
-
server_ctx = client_ctx = False
|
61
|
-
|
62
|
-
clock = trio.lowlevel.current_clock()
|
63
|
-
try:
|
64
|
-
clock.autojump_threshold = 0.02 # networking
|
65
|
-
except Exception:
|
66
|
-
pass # test doesn't have autojump_clock fixture
|
67
|
-
|
68
|
-
async def mock_get_host_port(st, host):
|
69
|
-
i = int(host[host.rindex("_") + 1 :])
|
70
|
-
s = st.s[i]
|
71
|
-
await s.is_serving
|
72
|
-
for host, port, *_ in s.ports:
|
73
|
-
if host == "::" or host[0] != ":":
|
74
|
-
return host, port
|
75
|
-
|
76
|
-
def tm():
|
77
|
-
try:
|
78
|
-
return trio.current_time()
|
79
|
-
except RuntimeError:
|
80
|
-
return otm()
|
81
|
-
|
82
|
-
async def mock_set_tock(self, old):
|
83
|
-
assert self._tock < tocks, "Test didn't terminate. Limit:" + str(tocks)
|
84
|
-
await old()
|
85
|
-
|
86
|
-
done = False
|
87
|
-
async with main_scope("moat.kv.test.mqtt") as scp:
|
88
|
-
tg = scp._tg
|
89
|
-
st = S(tg, client_ctx)
|
90
|
-
async with AsyncExitStack() as ex:
|
91
|
-
st.ex = ex # pylint: disable=attribute-defined-outside-init
|
92
|
-
ex.enter_context(mock.patch("time.time", new=tm))
|
93
|
-
ex.enter_context(mock.patch("time.monotonic", new=tm))
|
94
|
-
logging._startTime = tm()
|
95
|
-
|
96
|
-
async def run_broker(cfg):
|
97
|
-
async with create_broker(config=cfg) as srv:
|
98
|
-
# NB: some services use "async with await …"
|
99
|
-
scope.register(srv)
|
100
|
-
await scope.no_more_dependents()
|
101
|
-
|
102
|
-
async def with_broker(s, *a, **k):
|
103
|
-
await scope.service("moat.mqtt.broker", run_broker, broker_cfg)
|
104
|
-
s._scope = scope.get()
|
105
|
-
return await s._scoped_serve(*a, **k)
|
106
|
-
|
107
|
-
args_def = kw.get("args", attrdict())
|
108
|
-
for i in range(n):
|
109
|
-
name = "test_" + str(i)
|
110
|
-
args = kw.get(name, args_def)
|
111
|
-
args = combine_dict(
|
112
|
-
args,
|
113
|
-
args_def,
|
114
|
-
{
|
115
|
-
"cfg": {
|
116
|
-
"conn": {"ssl": client_ctx},
|
117
|
-
"server": {
|
118
|
-
"bind_default": {
|
119
|
-
"host": "127.0.0.1",
|
120
|
-
"port": i + PORT + 1,
|
121
|
-
"ssl": server_ctx,
|
122
|
-
},
|
123
|
-
"backend": "mqtt",
|
124
|
-
"mqtt": {"uri": URI},
|
125
|
-
},
|
126
|
-
},
|
127
|
-
},
|
128
|
-
{"cfg": TESTCFG},
|
129
|
-
)
|
130
|
-
args_def.pop("init", None)
|
131
|
-
s = Server(name, **args)
|
132
|
-
ex.enter_context(
|
133
|
-
mock.patch.object(s, "_set_tock", new=partial(mock_set_tock, s, s._set_tock)),
|
134
|
-
)
|
135
|
-
ex.enter_context(
|
136
|
-
mock.patch.object(s, "_get_host_port", new=partial(mock_get_host_port, st)),
|
137
|
-
)
|
138
|
-
st.s.append(s)
|
139
|
-
|
140
|
-
evts = []
|
141
|
-
for i in range(n):
|
142
|
-
if kw.get(f"run_{i}", run):
|
143
|
-
evt = anyio.Event()
|
144
|
-
await scp.spawn_service(with_broker, st.s[i], ready_evt=evt)
|
145
|
-
evts.append(evt)
|
146
|
-
else:
|
147
|
-
setattr(st, f"run_{i}", partial(scp.spawn_service, with_broker, st.s[i]))
|
148
|
-
|
149
|
-
for e in evts:
|
150
|
-
await e.wait()
|
151
|
-
try:
|
152
|
-
done = True
|
153
|
-
yield st
|
154
|
-
finally:
|
155
|
-
with anyio.fail_after(2, shield=True):
|
156
|
-
logger.info("Runtime: %s", clock.current_time())
|
157
|
-
tg.cancel_scope.cancel()
|
158
|
-
if not done:
|
159
|
-
yield None
|
build/lib/moat/kv/mock/serf.py
DELETED
@@ -1,250 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
import copy
|
3
|
-
import logging
|
4
|
-
import time
|
5
|
-
from contextlib import AsyncExitStack, asynccontextmanager
|
6
|
-
from functools import partial
|
7
|
-
|
8
|
-
import anyio
|
9
|
-
import attr
|
10
|
-
from unittest import mock
|
11
|
-
import trio
|
12
|
-
from asyncscope import main_scope, scope
|
13
|
-
from asyncserf.stream import SerfEvent
|
14
|
-
from moat.util import NotGiven, ValueEvent, attrdict, combine_dict, create_queue
|
15
|
-
|
16
|
-
from moat.kv.codec import unpacker
|
17
|
-
from moat.kv.mock import S as _S
|
18
|
-
from moat.kv.server import Server
|
19
|
-
|
20
|
-
logger = logging.getLogger(__name__)
|
21
|
-
|
22
|
-
otm = time.time
|
23
|
-
|
24
|
-
from . import CFG
|
25
|
-
|
26
|
-
|
27
|
-
@asynccontextmanager
|
28
|
-
async def stdtest(n=1, run=True, ssl=False, tocks=20, **kw):
|
29
|
-
C_OUT = CFG.get("_stdout", NotGiven)
|
30
|
-
if C_OUT is not NotGiven:
|
31
|
-
del CFG["_stdout"]
|
32
|
-
TESTCFG = copy.deepcopy(CFG["kv"])
|
33
|
-
TESTCFG.server.port = None
|
34
|
-
TESTCFG.server.backend = "serf"
|
35
|
-
TESTCFG.root = "test"
|
36
|
-
if C_OUT is not NotGiven:
|
37
|
-
CFG["_stdout"] = C_OUT
|
38
|
-
TESTCFG["_stdout"] = C_OUT
|
39
|
-
|
40
|
-
if ssl:
|
41
|
-
import ssl
|
42
|
-
|
43
|
-
import trustme
|
44
|
-
|
45
|
-
ca = trustme.CA()
|
46
|
-
cert = ca.issue_server_cert("127.0.0.1")
|
47
|
-
server_ctx = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
|
48
|
-
client_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
|
49
|
-
ca.configure_trust(client_ctx)
|
50
|
-
cert.configure_cert(server_ctx)
|
51
|
-
else:
|
52
|
-
server_ctx = client_ctx = False
|
53
|
-
|
54
|
-
clock = trio.lowlevel.current_clock()
|
55
|
-
clock.autojump_threshold = 0.0
|
56
|
-
# clock.rate = 5
|
57
|
-
|
58
|
-
@attr.s
|
59
|
-
class S(_S):
|
60
|
-
splits = attr.ib(factory=set)
|
61
|
-
serfs = attr.ib(factory=set)
|
62
|
-
|
63
|
-
def split(self, s):
|
64
|
-
assert s not in self.splits
|
65
|
-
logger.debug("Split: add %d", s)
|
66
|
-
self.splits.add(s)
|
67
|
-
|
68
|
-
def join(self, s):
|
69
|
-
logger.debug("Split: join %d", s)
|
70
|
-
self.splits.remove(s)
|
71
|
-
|
72
|
-
async def mock_get_host_port(st, host):
|
73
|
-
i = int(host[host.rindex("_") + 1 :])
|
74
|
-
s = st.s[i]
|
75
|
-
await s.is_serving
|
76
|
-
for host, port, *_ in s.ports:
|
77
|
-
if host == "::" or host[0] != ":":
|
78
|
-
return host, port
|
79
|
-
|
80
|
-
def tm():
|
81
|
-
try:
|
82
|
-
return trio.current_time()
|
83
|
-
except RuntimeError:
|
84
|
-
return otm()
|
85
|
-
|
86
|
-
async def mock_set_tock(self, old):
|
87
|
-
assert self._tock < tocks, "Test didn't terminate. Limit:" + str(tocks)
|
88
|
-
await old()
|
89
|
-
|
90
|
-
async with main_scope("moat.kv.test.serf") as scp:
|
91
|
-
tg = scp._tg
|
92
|
-
st = S(tg, client_ctx)
|
93
|
-
async with AsyncExitStack() as ex:
|
94
|
-
st.ex = ex # pylint: disable=attribute-defined-outside-init
|
95
|
-
ex.enter_context(mock.patch("time.time", new=tm))
|
96
|
-
ex.enter_context(mock.patch("time.monotonic", new=tm))
|
97
|
-
logging._startTime = tm()
|
98
|
-
|
99
|
-
ex.enter_context(
|
100
|
-
mock.patch("asyncserf.serf_client", new=partial(mock_serf_client, st)),
|
101
|
-
)
|
102
|
-
|
103
|
-
for i in range(n):
|
104
|
-
name = "test_" + str(i)
|
105
|
-
args = kw.get(name, kw.get("args", attrdict()))
|
106
|
-
args["cfg"] = combine_dict(
|
107
|
-
args.get("cfg", {}),
|
108
|
-
{
|
109
|
-
"kv": {
|
110
|
-
"conn": {"ssl": client_ctx},
|
111
|
-
},
|
112
|
-
"server": {
|
113
|
-
"bind_default": {
|
114
|
-
"host": "127.0.0.1",
|
115
|
-
"port": i + 50120,
|
116
|
-
"ssl": server_ctx,
|
117
|
-
},
|
118
|
-
"serf": {"i": i},
|
119
|
-
},
|
120
|
-
},
|
121
|
-
TESTCFG,
|
122
|
-
)
|
123
|
-
s = Server(name, **args)
|
124
|
-
ex.enter_context(
|
125
|
-
mock.patch.object(s, "_set_tock", new=partial(mock_set_tock, s, s._set_tock)),
|
126
|
-
)
|
127
|
-
ex.enter_context(
|
128
|
-
mock.patch.object(s, "_get_host_port", new=partial(mock_get_host_port, st)),
|
129
|
-
)
|
130
|
-
st.s.append(s)
|
131
|
-
|
132
|
-
async def with_serf(s, *a, **k):
|
133
|
-
s._scope = scope.get()
|
134
|
-
return await s._scoped_serve(*a, **k)
|
135
|
-
|
136
|
-
evts = []
|
137
|
-
for i in range(n):
|
138
|
-
if kw.get("run_" + str(i), run):
|
139
|
-
evt = anyio.Event()
|
140
|
-
await scp.spawn_service(with_serf, st.s[i], ready_evt=evt)
|
141
|
-
evts.append(evt)
|
142
|
-
for e in evts:
|
143
|
-
await e.wait()
|
144
|
-
try:
|
145
|
-
yield st
|
146
|
-
finally:
|
147
|
-
with anyio.fail_after(2, shield=True):
|
148
|
-
logger.info("Runtime: %s", clock.current_time())
|
149
|
-
tg.cancel_scope.cancel()
|
150
|
-
logger.info("End")
|
151
|
-
pass # unwinding ex:AsyncExitStack
|
152
|
-
|
153
|
-
|
154
|
-
@asynccontextmanager
|
155
|
-
async def mock_serf_client(master, **cfg):
|
156
|
-
async with scope.using_scope():
|
157
|
-
ms = MockServ(master, **cfg)
|
158
|
-
master.serfs.add(ms)
|
159
|
-
ms._scope = scope.get() # pylint:disable=attribute-defined-outside-init
|
160
|
-
try:
|
161
|
-
yield ms
|
162
|
-
finally:
|
163
|
-
master.serfs.remove(ms)
|
164
|
-
pass # terminating mock_serf_client nursery
|
165
|
-
|
166
|
-
|
167
|
-
class MockServ:
|
168
|
-
def __init__(self, master, **cfg):
|
169
|
-
self.cfg = cfg
|
170
|
-
self._tg = scope._tg
|
171
|
-
self.streams = {}
|
172
|
-
self._master = master
|
173
|
-
|
174
|
-
def __hash__(self):
|
175
|
-
return id(self)
|
176
|
-
|
177
|
-
async def spawn(self, fn, *args, **kw):
|
178
|
-
async def run(evt):
|
179
|
-
with anyio.CancelScope() as sc:
|
180
|
-
await evt.set(sc)
|
181
|
-
await fn(*args, **kw)
|
182
|
-
|
183
|
-
evt = ValueEvent()
|
184
|
-
self._tg.spawn(run, evt)
|
185
|
-
return await evt.get()
|
186
|
-
|
187
|
-
async def event(self, name, payload, coalesce=True):
|
188
|
-
try:
|
189
|
-
logger.debug("SERF:%s: %r", name, unpacker(payload))
|
190
|
-
except Exception:
|
191
|
-
logger.debug("SERF:%s: %r (raw)", name, payload)
|
192
|
-
assert not coalesce, "'coalesce' must be cleared!"
|
193
|
-
|
194
|
-
i_self = self.cfg.get("i", 0)
|
195
|
-
for s in list(self._master.serfs):
|
196
|
-
i_s = s.cfg.get("i", 0)
|
197
|
-
for x in self._master.splits:
|
198
|
-
if (i_s < x) != (i_self < x):
|
199
|
-
break
|
200
|
-
else:
|
201
|
-
n = tuple(name.split("."))
|
202
|
-
while n:
|
203
|
-
sl = s.streams.get(n, ())
|
204
|
-
for sn in sl:
|
205
|
-
await sn.q.put((name, payload))
|
206
|
-
n = n[:-1]
|
207
|
-
|
208
|
-
def stream(self, typ):
|
209
|
-
"""compat for supporting asyncactor"""
|
210
|
-
if not typ.startswith("user:"):
|
211
|
-
raise RuntimeError("not supported")
|
212
|
-
typ = typ[5:]
|
213
|
-
return self.serf_mon(typ)
|
214
|
-
|
215
|
-
def serf_mon(self, typ):
|
216
|
-
if "," in typ:
|
217
|
-
raise RuntimeError("not supported")
|
218
|
-
s = MockSerfStream(self, "user:" + typ)
|
219
|
-
return s
|
220
|
-
|
221
|
-
async def serf_send(self, typ, payload):
|
222
|
-
"""compat for supporting asyncactor"""
|
223
|
-
return await self.event(typ, payload)
|
224
|
-
|
225
|
-
|
226
|
-
class MockSerfStream:
|
227
|
-
q = None
|
228
|
-
|
229
|
-
def __init__(self, serf, typ):
|
230
|
-
self.serf = serf
|
231
|
-
assert typ.startswith("user:")
|
232
|
-
self.typ = tuple(typ[5:].split("."))
|
233
|
-
|
234
|
-
async def __aenter__(self):
|
235
|
-
self.q = create_queue(100)
|
236
|
-
self.serf.streams.setdefault(self.typ, []).append(self)
|
237
|
-
return self
|
238
|
-
|
239
|
-
async def __aexit__(self, *tb):
|
240
|
-
self.serf.streams[self.typ].remove(self)
|
241
|
-
del self.q
|
242
|
-
|
243
|
-
def __aiter__(self):
|
244
|
-
return self
|
245
|
-
|
246
|
-
async def __anext__(self):
|
247
|
-
res = await self.q.get()
|
248
|
-
evt = SerfEvent(self)
|
249
|
-
evt.topic, evt.payload = res
|
250
|
-
return evt
|
build/lib/moat/kv/mock/tracer.py
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
import traceback
|
3
|
-
|
4
|
-
import trio
|
5
|
-
from outcome import Error
|
6
|
-
|
7
|
-
import moat
|
8
|
-
|
9
|
-
moat.kill = False
|
10
|
-
|
11
|
-
import logging
|
12
|
-
|
13
|
-
logger = logging.getLogger("TRACE")
|
14
|
-
e = logger.error
|
15
|
-
|
16
|
-
|
17
|
-
class Tracer(trio.abc.Instrument):
|
18
|
-
def __init__(self):
|
19
|
-
super().__init__()
|
20
|
-
self.etasks = set()
|
21
|
-
|
22
|
-
def _print_with_task(self, msg, task, err=None):
|
23
|
-
# repr(task) is perhaps more useful than task.name in general,
|
24
|
-
# but in context of a tutorial the extra noise is unhelpful.
|
25
|
-
if err is not None:
|
26
|
-
e("%s: %s %s", msg, task.name, repr(err))
|
27
|
-
traceback.print_exception(type(err), err, err.__traceback__)
|
28
|
-
else:
|
29
|
-
e("%s: %s", msg, task.name)
|
30
|
-
|
31
|
-
def nursery_end(self, task, exception):
|
32
|
-
if isinstance(exception, Exception):
|
33
|
-
self.etasks.add(task)
|
34
|
-
self._print_with_task("*** task excepted", task, exception)
|
35
|
-
|
36
|
-
def before_task_step(self, task):
|
37
|
-
if isinstance(task._next_send, Error) and isinstance(task._next_send.error, Exception):
|
38
|
-
self._print_with_task("*** step resume ERROR", task, task._next_send.error)
|
39
|
-
self.etasks.add(task)
|
40
|
-
elif moat.kill: # pylint: disable=c-extension-no-member # OH COME ON
|
41
|
-
self._print_with_task("*** step resume", task)
|
42
|
-
|
43
|
-
def task_scheduled(self, task):
|
44
|
-
e("SCHED %r", task)
|
45
|
-
|
46
|
-
def task_exited(self, task):
|
47
|
-
self._print_with_task("*** task exited", task)
|
48
|
-
self.etasks.discard(task)
|
49
|
-
|
50
|
-
def before_io_wait(self, timeout):
|
51
|
-
if timeout > 10000 and self.etasks:
|
52
|
-
e("\n\n\n\n\n\n\n\n\n\n")
|
53
|
-
e("*** ERROR: lock-out, killing off error tasks")
|
54
|
-
e("\n\n\n\n")
|
55
|
-
for t in self.etasks:
|
56
|
-
if t._next_send_fn is None:
|
57
|
-
self._print_with_task("!!! Killing", t)
|
58
|
-
t._runner.reschedule(t, Error(RuntimeError("*** Locked ***")))
|
59
|
-
else:
|
60
|
-
self._print_with_task("??? already scheduled", t)
|
61
|
-
|
62
|
-
|
63
|
-
# trio.run(main_, instruments=[Tracer()])
|