moat-lib-codec 0.4.10__tar.gz → 0.4.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {moat_lib_codec-0.4.10/src/moat_lib_codec.egg-info → moat_lib_codec-0.4.14}/PKG-INFO +5 -5
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/README.md +12 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/debian/changelog +42 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/pyproject.toml +5 -5
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/__init__.py +6 -2
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/_base.py +33 -14
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/_cbor.py +14 -9
- moat_lib_codec-0.4.14/src/moat/lib/codec/_moat_cbor.py +136 -0
- moat_lib_codec-0.4.14/src/moat/lib/codec/_moat_msgpack.py +132 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/cbor.py +6 -8
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/errors.py +6 -5
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/json.py +1 -1
- moat_lib_codec-0.4.14/src/moat/lib/codec/moat_cbor.py +257 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/moat_kv.py +1 -1
- moat_lib_codec-0.4.14/src/moat/lib/codec/moat_msgpack.py +29 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/msgpack.py +8 -8
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/yaml.py +7 -2
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14/src/moat_lib_codec.egg-info}/PKG-INFO +5 -5
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat_lib_codec.egg-info/SOURCES.txt +4 -0
- moat_lib_codec-0.4.14/src/moat_lib_codec.egg-info/requires.txt +5 -0
- moat_lib_codec-0.4.10/src/moat_lib_codec.egg-info/requires.txt +0 -5
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/LICENSE.txt +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/Makefile +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/debian/.gitignore +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/debian/control +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/debian/py3dist-overrides +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/debian/rules +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/setup.cfg +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/binary.py +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/bool.py +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/noop.py +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat/lib/codec/utf8.py +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat_lib_codec.egg-info/dependency_links.txt +0 -0
- {moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat_lib_codec.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moat-lib-codec
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.14
|
|
4
4
|
Summary: A simple command/stream multiplexer
|
|
5
5
|
Author-email: Matthias Urlichs <matthias@urlichs.de>
|
|
6
6
|
Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
|
|
@@ -17,8 +17,8 @@ Requires-Python: >=3.8
|
|
|
17
17
|
Description-Content-Type: text/x-rst
|
|
18
18
|
License-File: LICENSE.txt
|
|
19
19
|
Requires-Dist: anyio~=4.2
|
|
20
|
-
Requires-Dist: moat-lib-rpc~=0.
|
|
21
|
-
Requires-Dist: moat-lib-micro~=0.
|
|
22
|
-
Requires-Dist: moat-lib-proxy~=0.1.
|
|
23
|
-
Requires-Dist: moat-util~=0.
|
|
20
|
+
Requires-Dist: moat-lib-rpc~=0.6.1
|
|
21
|
+
Requires-Dist: moat-lib-micro~=0.2.2
|
|
22
|
+
Requires-Dist: moat-lib-proxy~=0.1.1
|
|
23
|
+
Requires-Dist: moat-util~=0.62.6
|
|
24
24
|
Dynamic: license-file
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
# The MoaT-Codec library
|
|
2
2
|
|
|
3
3
|
% start synopsis
|
|
4
|
+
% start main
|
|
4
5
|
|
|
5
6
|
This library packages various codecs used for MoaT protocols
|
|
6
7
|
in a way that's reason- and stream-able.
|
|
7
8
|
|
|
8
9
|
% end synopsis
|
|
9
10
|
|
|
11
|
+
## Supplied codecs
|
|
12
|
+
|
|
13
|
+
- CBOR
|
|
14
|
+
- msgpack
|
|
15
|
+
- no-op
|
|
16
|
+
- UTF-8
|
|
17
|
+
- JSON
|
|
18
|
+
- YAML
|
|
19
|
+
|
|
20
|
+
% end main
|
|
21
|
+
|
|
10
22
|
## Interface
|
|
11
23
|
|
|
12
24
|
### Codec
|
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
moat-lib-codec (0.4.14-1) unstable; urgency=medium
|
|
2
|
+
|
|
3
|
+
* New release for 26.0.1
|
|
4
|
+
|
|
5
|
+
-- Matthias Urlichs <matthias@urlichs.de> Wed, 18 Feb 2026 18:28:41 +0100
|
|
6
|
+
|
|
7
|
+
moat-lib-codec (0.4.14-1) unstable; urgency=medium
|
|
8
|
+
|
|
9
|
+
* New release for 26.0.1
|
|
10
|
+
|
|
11
|
+
-- Matthias Urlichs <matthias@urlichs.de> Wed, 18 Feb 2026 18:06:02 +0100
|
|
12
|
+
|
|
13
|
+
moat-lib-codec (0.4.11-2) unstable; urgency=medium
|
|
14
|
+
|
|
15
|
+
* New release for 26.0.0
|
|
16
|
+
|
|
17
|
+
-- Matthias Urlichs <matthias@urlichs.de> Sun, 08 Feb 2026 11:05:29 +0100
|
|
18
|
+
|
|
19
|
+
moat-lib-codec (0.4.11-2) unstable; urgency=medium
|
|
20
|
+
|
|
21
|
+
* New release for 26.0.0
|
|
22
|
+
|
|
23
|
+
-- Matthias Urlichs <matthias@urlichs.de> Sun, 08 Feb 2026 11:00:01 +0100
|
|
24
|
+
|
|
25
|
+
moat-lib-codec (0.4.11-2) unstable; urgency=medium
|
|
26
|
+
|
|
27
|
+
* New release for 26.0.0
|
|
28
|
+
|
|
29
|
+
-- Matthias Urlichs <matthias@urlichs.de> Sun, 08 Feb 2026 10:32:15 +0100
|
|
30
|
+
|
|
31
|
+
moat-lib-codec (0.4.10-7) unstable; urgency=medium
|
|
32
|
+
|
|
33
|
+
* New release for 25.8.0
|
|
34
|
+
|
|
35
|
+
-- Matthias Urlichs <matthias@urlichs.de> Mon, 05 Jan 2026 15:32:38 +0100
|
|
36
|
+
|
|
37
|
+
moat-lib-codec (0.4.10-6) unstable; urgency=medium
|
|
38
|
+
|
|
39
|
+
* New release for 25.7.7
|
|
40
|
+
|
|
41
|
+
-- Matthias Urlichs <matthias@urlichs.de> Mon, 05 Jan 2026 15:06:55 +0100
|
|
42
|
+
|
|
1
43
|
moat-lib-codec (0.4.10-5) unstable; urgency=medium
|
|
2
44
|
|
|
3
45
|
* New release for 25.7.0
|
|
@@ -13,10 +13,10 @@ classifiers = [
|
|
|
13
13
|
]
|
|
14
14
|
dependencies = [
|
|
15
15
|
"anyio ~= 4.2",
|
|
16
|
-
"moat-lib-rpc ~= 0.
|
|
17
|
-
"moat-lib-micro ~= 0.
|
|
18
|
-
"moat-lib-proxy ~= 0.1.
|
|
19
|
-
"moat-util ~= 0.
|
|
16
|
+
"moat-lib-rpc ~= 0.6.1",
|
|
17
|
+
"moat-lib-micro ~= 0.2.2",
|
|
18
|
+
"moat-lib-proxy ~= 0.1.1",
|
|
19
|
+
"moat-util ~= 0.62.6",
|
|
20
20
|
]
|
|
21
21
|
keywords = ["MoaT"]
|
|
22
22
|
requires-python = ">=3.8"
|
|
@@ -25,7 +25,7 @@ maintainers = [{email = "matthias@urlichs.de",name = "Matthias Urlichs"}]
|
|
|
25
25
|
description='A simple command/stream multiplexer'
|
|
26
26
|
readme = "README.rst"
|
|
27
27
|
authors = [{email = "matthias@urlichs.de",name = "Matthias Urlichs"}]
|
|
28
|
-
version = "0.4.
|
|
28
|
+
version = "0.4.14"
|
|
29
29
|
|
|
30
30
|
[project.urls]
|
|
31
31
|
homepage = "https://m-o-a-t.org"
|
|
@@ -15,15 +15,19 @@ if TYPE_CHECKING:
|
|
|
15
15
|
__all__ = ["Codec", "Extension", "NoCodecError", "get_codec"]
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def get_codec(codec: str, **kw) -> Codec:
|
|
18
|
+
def get_codec(codec: str | Codec, **kw) -> Codec:
|
|
19
19
|
"""
|
|
20
20
|
Loads and initializes the named codec.
|
|
21
21
|
"""
|
|
22
22
|
from moat.util import import_ # noqa: PLC0415
|
|
23
23
|
|
|
24
|
+
if isinstance(codec, Codec):
|
|
25
|
+
return codec
|
|
26
|
+
if codec is None:
|
|
27
|
+
codec = "noop"
|
|
24
28
|
if "." not in codec:
|
|
25
29
|
if codec.startswith("std-"):
|
|
26
|
-
codec = "moat.
|
|
30
|
+
codec = "moat.lib.codec.moat_" + codec[4:]
|
|
27
31
|
else:
|
|
28
32
|
codec = "moat.lib.codec." + codec
|
|
29
33
|
return import_(codec).Codec(**kw)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING, overload
|
|
4
4
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from collections.abc import Callable
|
|
7
7
|
from typing import Any, Self
|
|
8
8
|
|
|
9
|
-
ByteType = bytes | bytearray | memoryview
|
|
10
|
-
VarByteType = bytearray | memoryview
|
|
9
|
+
ByteType = bytes | bytearray | memoryview
|
|
10
|
+
VarByteType = bytearray | memoryview
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class NoCodecError(ValueError):
|
|
@@ -34,12 +34,12 @@ class Codec:
|
|
|
34
34
|
detected.
|
|
35
35
|
|
|
36
36
|
After the header is consumed, the application must repeat calling
|
|
37
|
-
|
|
37
|
+
``__anext__`` until an object is returned. (If the decoder
|
|
38
38
|
raises `StopAsyncIteration`, feed more data to it and repeat.)
|
|
39
39
|
|
|
40
40
|
The decoder must leave all incoming data extending past the object in
|
|
41
41
|
its buffer. It must not attempt to decode them until the next call to
|
|
42
|
-
|
|
42
|
+
``__anext__``.
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
45
|
def __init__(self, ext=None):
|
|
@@ -99,6 +99,11 @@ class Codec:
|
|
|
99
99
|
raise NotImplementedError
|
|
100
100
|
|
|
101
101
|
|
|
102
|
+
if TYPE_CHECKING:
|
|
103
|
+
EncoderFunc = Callable[[Codec, Any], ByteType | tuple[int, ByteType]]
|
|
104
|
+
DecoderFunc = Callable[[Codec, ByteType], Any]
|
|
105
|
+
|
|
106
|
+
|
|
102
107
|
class Extension:
|
|
103
108
|
def __init__(self):
|
|
104
109
|
self.enc: dict[type, tuple[int | None, Callable]] = {}
|
|
@@ -110,25 +115,39 @@ class Extension:
|
|
|
110
115
|
res.dec.update(self.dec)
|
|
111
116
|
return res
|
|
112
117
|
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
@overload
|
|
119
|
+
def encoder(self, key: int | None, cls: type) -> Callable[[EncoderFunc], EncoderFunc]: ...
|
|
120
|
+
|
|
121
|
+
@overload
|
|
122
|
+
def encoder(self, key: int | None, cls: type, fn: EncoderFunc) -> EncoderFunc: ...
|
|
123
|
+
|
|
124
|
+
def encoder(
|
|
125
|
+
self, key: int | None, cls: type, fn: EncoderFunc | None = None
|
|
126
|
+
) -> EncoderFunc | Callable[[EncoderFunc], EncoderFunc]:
|
|
127
|
+
def _enc(fn: EncoderFunc) -> EncoderFunc:
|
|
115
128
|
self.enc[cls] = (key, fn)
|
|
116
129
|
return fn
|
|
117
130
|
|
|
118
131
|
if fn is None:
|
|
119
132
|
return _enc
|
|
120
|
-
|
|
121
|
-
|
|
133
|
+
return _enc(fn)
|
|
134
|
+
|
|
135
|
+
@overload
|
|
136
|
+
def decoder(self, key: int | None) -> Callable[[DecoderFunc], DecoderFunc]: ...
|
|
137
|
+
|
|
138
|
+
@overload
|
|
139
|
+
def decoder(self, key: int | None, fn: DecoderFunc) -> DecoderFunc: ...
|
|
122
140
|
|
|
123
|
-
def decoder(
|
|
124
|
-
|
|
125
|
-
|
|
141
|
+
def decoder(
|
|
142
|
+
self, key: int | None, fn: DecoderFunc | None = None
|
|
143
|
+
) -> DecoderFunc | Callable[[DecoderFunc], DecoderFunc]:
|
|
144
|
+
def _dec(fn: DecoderFunc) -> DecoderFunc:
|
|
145
|
+
self.dec[key] = fn # type: ignore[index] # key can be None for catch-all
|
|
126
146
|
return fn
|
|
127
147
|
|
|
128
148
|
if fn is None:
|
|
129
149
|
return _dec
|
|
130
|
-
|
|
131
|
-
_dec(fn)
|
|
150
|
+
return _dec(fn)
|
|
132
151
|
|
|
133
152
|
def encode(self, codec: Codec, obj) -> tuple[int, ByteType]:
|
|
134
153
|
try:
|
|
@@ -13,10 +13,10 @@ from ._base import Codec as _Codec
|
|
|
13
13
|
from ._base import NoCodecError
|
|
14
14
|
|
|
15
15
|
# Typing
|
|
16
|
-
from typing import
|
|
16
|
+
from typing import TYPE_CHECKING, cast # isort:skip
|
|
17
17
|
|
|
18
18
|
try:
|
|
19
|
-
from micropython import const #
|
|
19
|
+
from micropython import const # type: ignore[import-not-found] # MicroPython only
|
|
20
20
|
except ImportError:
|
|
21
21
|
|
|
22
22
|
def const(x: int) -> int:
|
|
@@ -29,7 +29,11 @@ if TYPE_CHECKING:
|
|
|
29
29
|
from typing import Any
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
__all__ = ["Codec", "ExtraData", "Tag"]
|
|
32
|
+
__all__ = ["CBOR_TAG_CBOR_FILEHEADER", "CBOR_TAG_CBOR_LEADER", "Codec", "ExtraData", "Tag"]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
CBOR_TAG_CBOR_FILEHEADER = const(55799) # single CBOR content
|
|
36
|
+
CBOR_TAG_CBOR_LEADER = const(55800) # header for multiple CBOR items
|
|
33
37
|
|
|
34
38
|
|
|
35
39
|
class Tag:
|
|
@@ -142,7 +146,7 @@ class Codec(_Codec):
|
|
|
142
146
|
if self._buffer:
|
|
143
147
|
raise RuntimeError("Codec is busy")
|
|
144
148
|
|
|
145
|
-
self._buffer = data
|
|
149
|
+
self._buffer = cast(bytes, data)
|
|
146
150
|
try:
|
|
147
151
|
res = self._dec_any()
|
|
148
152
|
# chop off the part we've read
|
|
@@ -157,12 +161,12 @@ class Codec(_Codec):
|
|
|
157
161
|
"Add additional input"
|
|
158
162
|
if self._buffer and self._buf_pos < len(self._buffer):
|
|
159
163
|
if self._buf_pos == 0:
|
|
160
|
-
self._buffer
|
|
164
|
+
self._buffer = cast(bytes, self._buffer + data)
|
|
161
165
|
return
|
|
162
|
-
data = self._buffer[self._buf_pos :] + data
|
|
163
|
-
|
|
166
|
+
data = cast(bytes, self._buffer[self._buf_pos :] + data)
|
|
167
|
+
if isinstance(data, memoryview):
|
|
164
168
|
data = bytearray(data)
|
|
165
|
-
self._buffer = data
|
|
169
|
+
self._buffer = cast(bytes, data)
|
|
166
170
|
self._buf_pos = 0
|
|
167
171
|
|
|
168
172
|
def unfeed(self, buf: VarByteType) -> int:
|
|
@@ -276,7 +280,8 @@ class Codec(_Codec):
|
|
|
276
280
|
self._enc_any(val)
|
|
277
281
|
|
|
278
282
|
def _w(self, d):
|
|
279
|
-
self._buf_out
|
|
283
|
+
assert self._buf_out is not None # set by encode() before calling _enc_any()
|
|
284
|
+
self._buf_out.extend(d)
|
|
280
285
|
|
|
281
286
|
def _enc_any(self, ob):
|
|
282
287
|
w = self._w
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
An overly-simple CBOR packer/unpacker.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Original Copyright 2014-2015 Brian Olson
|
|
6
|
+
# Apache 2.0 license
|
|
7
|
+
# http://docs.ros.org/en/noetic/api/rosbridge_library/html/cbor_8py_source.html
|
|
8
|
+
# rather heavily modified
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from moat.util import NotGiven
|
|
13
|
+
|
|
14
|
+
# Typing
|
|
15
|
+
from moat.lib.path import Path
|
|
16
|
+
from moat.lib.proxy import DProxy, Proxy, get_proxy, name2obj, obj2name, unwrap_obj, wrap_obj
|
|
17
|
+
|
|
18
|
+
from . import Extension
|
|
19
|
+
from . import cbor as _cbor
|
|
20
|
+
from .cbor import Tag
|
|
21
|
+
|
|
22
|
+
from typing import TYPE_CHECKING
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from moat.lib.codec import ByteType
|
|
26
|
+
|
|
27
|
+
__all__ = ["Codec", "std_ext"]
|
|
28
|
+
|
|
29
|
+
std_ext = Extension()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Codec(_cbor.Codec):
|
|
33
|
+
"""
|
|
34
|
+
CBOR codec with MoaT's standard extensions.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self):
|
|
38
|
+
super().__init__(ext=std_ext)
|
|
39
|
+
|
|
40
|
+
def decode(self, data: ByteType): # noqa:D102,RUF100
|
|
41
|
+
if data == b"":
|
|
42
|
+
return NotGiven
|
|
43
|
+
return super().decode(data)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@std_ext.encoder(27, DProxy)
|
|
47
|
+
def _enc_dpr(codec, obj):
|
|
48
|
+
codec # noqa:B018
|
|
49
|
+
res = [obj.name] + obj.a
|
|
50
|
+
if obj.k or (res and isinstance(res[-1], dict)):
|
|
51
|
+
res.append(obj.k)
|
|
52
|
+
return res
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@std_ext.encoder(32769, Proxy)
|
|
56
|
+
def _enc_pr(codec, obj):
|
|
57
|
+
codec # noqa:B018
|
|
58
|
+
return obj.name
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@std_ext.decoder(32769)
|
|
62
|
+
def _dec_proxy(codec, val):
|
|
63
|
+
codec # noqa:B018
|
|
64
|
+
try:
|
|
65
|
+
if isinstance(val, (str, int)):
|
|
66
|
+
return name2obj(val)
|
|
67
|
+
return unwrap_obj(val)
|
|
68
|
+
except KeyError:
|
|
69
|
+
return Proxy(val)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@std_ext.decoder(27)
|
|
73
|
+
def _dec_obj(codec, val):
|
|
74
|
+
codec # noqa:B018
|
|
75
|
+
if isinstance(val[0], Tag):
|
|
76
|
+
if val[0].tag != 32769:
|
|
77
|
+
return Tag(27, val) # not decodable
|
|
78
|
+
val[0] = val[0].value
|
|
79
|
+
return unwrap_obj(val)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@std_ext.encoder(39, Path)
|
|
83
|
+
def _enc_path(codec, val):
|
|
84
|
+
codec # noqa:B018
|
|
85
|
+
return val.raw_rooted
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@std_ext.decoder(39)
|
|
89
|
+
def _dec_path(codec, val):
|
|
90
|
+
codec # noqa:B018
|
|
91
|
+
if not isinstance(val, (list, tuple)):
|
|
92
|
+
return Tag(39, val) # not decodable
|
|
93
|
+
return Path.build(val, decoded=True)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@std_ext.encoder(258, set)
|
|
97
|
+
def _pack_set(codec, data):
|
|
98
|
+
codec # noqa:B018
|
|
99
|
+
return list(data)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@std_ext.decoder(258)
|
|
103
|
+
def _dec_set(codec, val):
|
|
104
|
+
codec # noqa:B018
|
|
105
|
+
return set(val)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@std_ext.encoder(None, object)
|
|
109
|
+
def enc_any(codec, obj):
|
|
110
|
+
codec # noqa:B018
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
name = obj2name(obj)
|
|
114
|
+
except KeyError:
|
|
115
|
+
pass
|
|
116
|
+
else:
|
|
117
|
+
return 32769, name
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
name = obj2name(type(obj))
|
|
121
|
+
except KeyError:
|
|
122
|
+
pass
|
|
123
|
+
else:
|
|
124
|
+
p = wrap_obj(obj, name=name)
|
|
125
|
+
return 27, p
|
|
126
|
+
|
|
127
|
+
if isinstance(obj, Exception):
|
|
128
|
+
# RemoteError, cf. moat.lib.codec.errors
|
|
129
|
+
res = ["_rErr", obj.__class__.__name__]
|
|
130
|
+
try:
|
|
131
|
+
res.extend(obj.args)
|
|
132
|
+
except AttributeError:
|
|
133
|
+
pass
|
|
134
|
+
return 27, res
|
|
135
|
+
|
|
136
|
+
return 32769, get_proxy(obj)
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains extension handlers for msgpack.
|
|
3
|
+
|
|
4
|
+
Extension types defined here:
|
|
5
|
+
2: contains raw bytes, interpreted as unsigned bignum
|
|
6
|
+
3: Path, as a msgpack object stream of its elements
|
|
7
|
+
4: contains raw bytes, interpreted as UTF-8, returned as (named) Proxy object
|
|
8
|
+
5: object constructor
|
|
9
|
+
6: marked Path
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from moat.lib.path import Path
|
|
15
|
+
from moat.lib.proxy import DProxy, Proxy, _CProxy, get_proxy, obj2name, unwrap_obj, wrap_obj
|
|
16
|
+
|
|
17
|
+
from . import Extension
|
|
18
|
+
from . import msgpack as _msgpack
|
|
19
|
+
|
|
20
|
+
__all__ = ["Codec", "std_ext"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
std_ext = Extension()
|
|
24
|
+
ExtType = _msgpack.ExtType
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Codec(_msgpack.Codec):
|
|
28
|
+
"A MsgPack codec with our extensions"
|
|
29
|
+
|
|
30
|
+
def __init__(self):
|
|
31
|
+
super().__init__(ext=std_ext, use_attrdict=True)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@std_ext.encoder(5, DProxy)
|
|
35
|
+
def _enc_dproxy(codec, obj):
|
|
36
|
+
a = obj.a[:]
|
|
37
|
+
if obj.k or (a and isinstance(a[-1], dict)):
|
|
38
|
+
a.append(obj.k)
|
|
39
|
+
return codec.encode(obj.name) + b"".join(codec.encode(x) for x in a)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# not actually used
|
|
43
|
+
@std_ext.encoder(None, ExtType)
|
|
44
|
+
def _enc_exttype(codec, obj):
|
|
45
|
+
codec # noqa:B018
|
|
46
|
+
return obj.type, obj.data
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@std_ext.encoder(None, Path)
|
|
50
|
+
def _enc_path(codec, obj):
|
|
51
|
+
if obj.mark:
|
|
52
|
+
return 6, codec.encode(obj.mark) + b"".join(codec.encode(x) for x in obj.raw)
|
|
53
|
+
return 3, b"".join(codec.encode(x) for x in obj.raw)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@std_ext.encoder(4, Proxy)
|
|
57
|
+
def _enc_proxy(codec, obj):
|
|
58
|
+
codec # noqa:B018
|
|
59
|
+
return obj.name.encode("utf-8")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@std_ext.encoder(None, object)
|
|
63
|
+
def _enc_any(codec, obj):
|
|
64
|
+
try:
|
|
65
|
+
name = obj2name(obj)
|
|
66
|
+
except KeyError:
|
|
67
|
+
pass
|
|
68
|
+
else:
|
|
69
|
+
return 4, name.encode("utf-8")
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
name = obj2name(type(obj))
|
|
73
|
+
except KeyError:
|
|
74
|
+
pass
|
|
75
|
+
else:
|
|
76
|
+
p = wrap_obj(obj, name=name)
|
|
77
|
+
return 5, b"".join(codec.encode(x) for x in p)
|
|
78
|
+
|
|
79
|
+
if isinstance(obj, Exception):
|
|
80
|
+
# RemoteError, cf. moat.lib.codec.errors
|
|
81
|
+
return 5, codec.encode("_rErr") + codec.encode(obj.__class__.__name__) + b"".join(
|
|
82
|
+
codec.encode(x) for x in obj.args
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return 4, get_proxy(obj).encode("utf-8")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@std_ext.decoder(3)
|
|
89
|
+
def _dec_path(codec, data):
|
|
90
|
+
codec # noqa:B018
|
|
91
|
+
s = Codec()
|
|
92
|
+
s.feed(data)
|
|
93
|
+
return Path.build(iter(s), decoded=True)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@std_ext.decoder(4)
|
|
97
|
+
def _dec_proxy(codec, data):
|
|
98
|
+
codec # noqa:B018
|
|
99
|
+
if isinstance(data, memoryview):
|
|
100
|
+
data = bytearray(data)
|
|
101
|
+
try:
|
|
102
|
+
n = data.decode("utf-8")
|
|
103
|
+
except UnicodeError:
|
|
104
|
+
n = str(data)
|
|
105
|
+
try:
|
|
106
|
+
return _CProxy[n]
|
|
107
|
+
except KeyError:
|
|
108
|
+
return Proxy(n)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@std_ext.decoder(5)
|
|
112
|
+
def _dec_proxy_obj(codec, data):
|
|
113
|
+
codec = codec.copy()
|
|
114
|
+
codec.feed(data)
|
|
115
|
+
s = list(iter(codec))
|
|
116
|
+
return unwrap_obj(s)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@std_ext.decoder(6)
|
|
120
|
+
def _dec_marked_path(codec, data):
|
|
121
|
+
# A marked path. Deprecated.
|
|
122
|
+
codec = codec.copy()
|
|
123
|
+
codec.feed(data)
|
|
124
|
+
s = iter(codec)
|
|
125
|
+
mark = next(s)
|
|
126
|
+
p = Path(*s, mark=mark)
|
|
127
|
+
return p
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@std_ext.decoder(None)
|
|
131
|
+
def _dec_blank(codec, data):
|
|
132
|
+
return ExtType(codec, data)
|
|
@@ -6,16 +6,14 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import struct
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
try:
|
|
10
|
+
from ruyaml import representer
|
|
11
|
+
except ImportError:
|
|
12
|
+
from ruamel.yaml import representer # fallback if ruyaml unavailable
|
|
10
13
|
|
|
11
|
-
from
|
|
14
|
+
from ._cbor import CBOR_TAG_CBOR_FILEHEADER, CBOR_TAG_CBOR_LEADER, Codec, Tag # noqa:F401
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SafeRepresenter = yaml.representer.SafeRepresenter # pyright:ignore
|
|
16
|
-
|
|
17
|
-
CBOR_TAG_CBOR_FILEHEADER = const(55799) # single CBOR content
|
|
18
|
-
CBOR_TAG_CBOR_LEADER = const(55800) # header for multiple CBOR items
|
|
16
|
+
SafeRepresenter = representer.SafeRepresenter
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
def _tag_repr(dumper, data):
|
|
@@ -4,8 +4,8 @@ FUSE operations for MoaT-micro-FS
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
from moat.util import ExpAttrError, ExpKeyError
|
|
7
8
|
from moat.lib.proxy import as_proxy
|
|
8
|
-
from moat.util.exc import ExpAttrError, ExpKeyError
|
|
9
9
|
|
|
10
10
|
try:
|
|
11
11
|
from moat.lib.rpc import RemoteError
|
|
@@ -16,7 +16,7 @@ except ImportError:
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
@as_proxy("_rErrS")
|
|
19
|
-
class SilentRemoteError(RemoteError):
|
|
19
|
+
class SilentRemoteError(RemoteError): # type: ignore[misc] # RemoteError may be from two different sources
|
|
20
20
|
"""
|
|
21
21
|
Forwarded error from a remote system.
|
|
22
22
|
|
|
@@ -29,7 +29,7 @@ class NoPathError(KeyError):
|
|
|
29
29
|
"""An error that marks a nonexisting path"""
|
|
30
30
|
|
|
31
31
|
def __str__(self):
|
|
32
|
-
from moat.
|
|
32
|
+
from moat.lib.path import Path # noqa: PLC0415
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
35
|
f"‹NoPath {self.args[0]} {Path.build(self.args[1])}"
|
|
@@ -42,7 +42,7 @@ class NoPathError(KeyError):
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
try:
|
|
45
|
-
FileNotFoundError # noqa:
|
|
45
|
+
FileNotFoundError = FileNotFoundError # noqa:A001,PLW0127
|
|
46
46
|
except NameError:
|
|
47
47
|
|
|
48
48
|
class FileNotFoundError(SilentRemoteError): # noqa:A001
|
|
@@ -55,7 +55,7 @@ except NameError:
|
|
|
55
55
|
as_proxy("_FnErr", FileNotFoundError)
|
|
56
56
|
|
|
57
57
|
try:
|
|
58
|
-
FileExistsError # noqa:
|
|
58
|
+
FileExistsError = FileExistsError # noqa:A001,PLW0127
|
|
59
59
|
except NameError:
|
|
60
60
|
|
|
61
61
|
class FileExistsError(SilentRemoteError): # noqa:A001
|
|
@@ -69,6 +69,7 @@ as_proxy("_FxErr", FileExistsError)
|
|
|
69
69
|
|
|
70
70
|
as_proxy("_KyErr", KeyError)
|
|
71
71
|
as_proxy("_EKyErr", ExpKeyError)
|
|
72
|
+
as_proxy("_IdxErr", IndexError)
|
|
72
73
|
as_proxy("_AtErr", AttributeError)
|
|
73
74
|
as_proxy("_EAtErr", ExpAttrError)
|
|
74
75
|
as_proxy("_NiErr", NotImplementedError)
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""
|
|
2
|
+
An overly-simple CBOR packer/unpacker.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Original Copyright 2014-2015 Brian Olson
|
|
6
|
+
# Apache 2.0 license
|
|
7
|
+
# http://docs.ros.org/en/noetic/api/rosbridge_library/html/cbor_8py_source.html
|
|
8
|
+
# rather heavily modified
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import contextlib
|
|
13
|
+
import datetime as dt
|
|
14
|
+
import re
|
|
15
|
+
from ipaddress import (
|
|
16
|
+
IPv4Address,
|
|
17
|
+
IPv4Interface,
|
|
18
|
+
IPv4Network,
|
|
19
|
+
IPv6Address,
|
|
20
|
+
IPv6Interface,
|
|
21
|
+
IPv6Network,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from ._moat_cbor import Codec, std_ext
|
|
25
|
+
|
|
26
|
+
# Typing
|
|
27
|
+
from .cbor import CBOR_TAG_CBOR_FILEHEADER, CBOR_TAG_CBOR_LEADER, Tag
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"CBOR_TAG_MOAT_CHANGE",
|
|
31
|
+
"CBOR_TAG_MOAT_FILE_END",
|
|
32
|
+
"CBOR_TAG_MOAT_FILE_ID",
|
|
33
|
+
"Codec",
|
|
34
|
+
"gen_start",
|
|
35
|
+
"gen_stop",
|
|
36
|
+
"std_ext",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
CBOR_TAG_MOAT_FILE_ID = 1299145044 # 'MoaT'
|
|
40
|
+
CBOR_TAG_MOAT_FILE_END = 1298493254 # 'MeoF'
|
|
41
|
+
CBOR_TAG_MOAT_CHANGE = 1298360423 # 'Mchg'
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def gen_start(text: str, /, **kw) -> Tag:
|
|
45
|
+
"""
|
|
46
|
+
Generate a MoaT file start tag
|
|
47
|
+
"""
|
|
48
|
+
if len(text) > 255:
|
|
49
|
+
raise ValueError("Description too long")
|
|
50
|
+
# add padding if too short
|
|
51
|
+
text += " " * (24 - len(text))
|
|
52
|
+
|
|
53
|
+
return Tag(CBOR_TAG_CBOR_LEADER, Tag(CBOR_TAG_MOAT_FILE_ID, (text, kw)))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def gen_stop(**kw) -> Tag:
|
|
57
|
+
"""
|
|
58
|
+
Generate a MoaT file stop tag
|
|
59
|
+
"""
|
|
60
|
+
return Tag(CBOR_TAG_MOAT_FILE_END, kw)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def gen_change(**kw) -> Tag:
|
|
64
|
+
"""
|
|
65
|
+
Generate a MoaT file stop tag
|
|
66
|
+
"""
|
|
67
|
+
return Tag(CBOR_TAG_MOAT_CHANGE, kw)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@std_ext.encoder(1, dt.datetime)
|
|
71
|
+
def _enc_datetime_ts(codec, value):
|
|
72
|
+
codec # noqa:B018
|
|
73
|
+
if not value.tzinfo:
|
|
74
|
+
raise ValueError(f"naive datetime {value!r}")
|
|
75
|
+
|
|
76
|
+
return value.timestamp()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# @std_ext.encoder(0, dt.datetime)
|
|
80
|
+
def _enc_datetime_str(codec, value):
|
|
81
|
+
codec # noqa:B018
|
|
82
|
+
|
|
83
|
+
if not value.tzinfo:
|
|
84
|
+
raise ValueError(f"naive datetime {value!r}")
|
|
85
|
+
|
|
86
|
+
return value.isoformat().replace("+00:00", "Z")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
_timestamp_re = re.compile(
|
|
90
|
+
r"^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.(\d{1,6})\d*)?(?:Z|([+-])(\d\d):(\d\d))$",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@std_ext.decoder(0)
|
|
95
|
+
def _dec_datetime_string(codec, value) -> dt.datetime:
|
|
96
|
+
codec # noqa:B018
|
|
97
|
+
|
|
98
|
+
match = _timestamp_re.match(value)
|
|
99
|
+
if match:
|
|
100
|
+
(
|
|
101
|
+
year,
|
|
102
|
+
month,
|
|
103
|
+
day,
|
|
104
|
+
hour,
|
|
105
|
+
minute,
|
|
106
|
+
second,
|
|
107
|
+
secfrac,
|
|
108
|
+
offset_sign,
|
|
109
|
+
offset_h,
|
|
110
|
+
offset_m,
|
|
111
|
+
) = match.groups()
|
|
112
|
+
microsecond = 0 if secfrac is None else int(f"{secfrac:<06}")
|
|
113
|
+
|
|
114
|
+
if offset_h:
|
|
115
|
+
sign = -1 if offset_sign == "-" else 1
|
|
116
|
+
hours = int(offset_h) * sign
|
|
117
|
+
minutes = int(offset_m) * sign
|
|
118
|
+
tz = dt.timezone(dt.timedelta(hours=hours, minutes=minutes))
|
|
119
|
+
else:
|
|
120
|
+
tz = dt.UTC
|
|
121
|
+
|
|
122
|
+
return dt.datetime(
|
|
123
|
+
int(year),
|
|
124
|
+
int(month),
|
|
125
|
+
int(day),
|
|
126
|
+
int(hour),
|
|
127
|
+
int(minute),
|
|
128
|
+
int(second),
|
|
129
|
+
microsecond,
|
|
130
|
+
tz,
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
raise ValueError(f"invalid datetime string: {value!r}")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@std_ext.decoder(1)
|
|
137
|
+
def _dec_ts(codec, val):
|
|
138
|
+
codec # noqa:B018
|
|
139
|
+
return dt.datetime.fromtimestamp(val, dt.UTC)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@std_ext.decoder(2)
|
|
143
|
+
def _dec_bigp(codec, val):
|
|
144
|
+
codec # noqa:B018
|
|
145
|
+
return int.from_bytes(val, "big")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@std_ext.decoder(3)
|
|
149
|
+
def _dec_bign(codec, val):
|
|
150
|
+
codec # noqa:B018
|
|
151
|
+
return -1 - int.from_bytes(val, "big")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _pad(buf, n):
|
|
155
|
+
buf = bytes(buf) # SIGH
|
|
156
|
+
if (lb := len(buf)) == n:
|
|
157
|
+
return buf
|
|
158
|
+
return buf + b"\x00" * (n - lb)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@std_ext.decoder(52)
|
|
162
|
+
def _dec_ip4address(codec, buf) -> IPv4Address | IPv4Network | IPv4Interface:
|
|
163
|
+
codec # noqa:B018
|
|
164
|
+
from ipaddress import IPv4Address, IPv4Interface, IPv4Network # noqa: PLC0415
|
|
165
|
+
|
|
166
|
+
if isinstance(buf, (bytes, bytearray, memoryview)):
|
|
167
|
+
return IPv4Address(_pad(buf, 4))
|
|
168
|
+
elif len(buf) != 2:
|
|
169
|
+
pass
|
|
170
|
+
elif isinstance(buf[1], int):
|
|
171
|
+
return IPv4Interface((_pad(buf[0], 4), buf[1]))
|
|
172
|
+
else:
|
|
173
|
+
return IPv4Network((_pad(buf[1], 4), buf[0]))
|
|
174
|
+
|
|
175
|
+
raise ValueError(f"invalid ipaddress value {buf!r}")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@std_ext.decoder(54)
|
|
179
|
+
def _dec_ip6address(codec, buf) -> IPv6Address | IPv6Network | IPv6Interface:
|
|
180
|
+
codec # noqa:B018
|
|
181
|
+
from ipaddress import IPv6Address, IPv6Interface, IPv6Network # noqa: PLC0415
|
|
182
|
+
|
|
183
|
+
if isinstance(buf, (bytes, bytearray, memoryview)):
|
|
184
|
+
return IPv6Address(_pad(buf, 16))
|
|
185
|
+
elif len(buf) != 2:
|
|
186
|
+
pass
|
|
187
|
+
elif isinstance(buf[1], int):
|
|
188
|
+
return IPv6Interface((_pad(buf[0], 16), buf[1]))
|
|
189
|
+
else:
|
|
190
|
+
return IPv6Network((_pad(buf[1], 16), buf[0]))
|
|
191
|
+
|
|
192
|
+
raise ValueError(f"invalid ipaddress value {buf!r}")
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@std_ext.encoder(52, IPv4Address)
|
|
196
|
+
@std_ext.encoder(54, IPv6Address)
|
|
197
|
+
def _pack_ip(codec, adr):
|
|
198
|
+
codec # noqa:B018
|
|
199
|
+
return adr.packed.rstrip(b"\x00")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@std_ext.encoder(52, IPv4Network)
|
|
203
|
+
@std_ext.encoder(54, IPv6Network)
|
|
204
|
+
def _pack_ipnet(codec, adr):
|
|
205
|
+
codec # noqa:B018
|
|
206
|
+
return (adr.prefixlen, _pack_ip(codec, adr.network_address))
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
@std_ext.encoder(52, IPv4Interface)
|
|
210
|
+
@std_ext.encoder(54, IPv6Interface)
|
|
211
|
+
def _pack_ipintf(codec, adr):
|
|
212
|
+
codec # noqa:B018
|
|
213
|
+
return (_pack_ip(codec, adr), adr.network.prefixlen)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@std_ext.decoder(260)
|
|
217
|
+
def _dec_old_ipaddress(codec, buf) -> IPv4Address | IPv6Address | Tag:
|
|
218
|
+
codec # noqa:B018
|
|
219
|
+
if isinstance(buf, (bytes, bytearray, memoryview)) or len(buf) not in (4, 6, 16):
|
|
220
|
+
if len(buf) == 4:
|
|
221
|
+
return IPv4Address(bytes(buf))
|
|
222
|
+
elif len(buf) == 16:
|
|
223
|
+
return IPv6Address(bytes(buf))
|
|
224
|
+
elif len(buf) == 6:
|
|
225
|
+
# MAC address
|
|
226
|
+
return Tag(260, buf)
|
|
227
|
+
|
|
228
|
+
raise ValueError(f"invalid ipaddress value {buf!r}")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@std_ext.decoder(261)
|
|
232
|
+
def _dec_old_ipnetwork(codec, buf) -> IPv4Network | IPv6Network:
|
|
233
|
+
codec # noqa:B018
|
|
234
|
+
if isinstance(buf, dict) and len(buf) == 1:
|
|
235
|
+
mask, buf = next(iter(buf.items()))
|
|
236
|
+
if len(buf) == 4:
|
|
237
|
+
return IPv4Network((bytes(buf), mask))
|
|
238
|
+
elif len(buf) == 16:
|
|
239
|
+
return IPv6Network((bytes(buf), mask))
|
|
240
|
+
|
|
241
|
+
raise ValueError(f"invalid ipnetwork value {buf!r}")
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@std_ext.decoder(CBOR_TAG_CBOR_FILEHEADER)
|
|
245
|
+
def _dec_file_cbor(codec, val):
|
|
246
|
+
codec # noqa:B018
|
|
247
|
+
with contextlib.suppress(AttributeError):
|
|
248
|
+
val._cbor_tag = CBOR_TAG_CBOR_FILEHEADER # noqa: SLF001
|
|
249
|
+
return val
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@std_ext.decoder(CBOR_TAG_CBOR_LEADER)
|
|
253
|
+
def _dec_file_cbor(codec, val):
|
|
254
|
+
codec # noqa:B018
|
|
255
|
+
with contextlib.suppress(AttributeError):
|
|
256
|
+
val._cbor_tag = CBOR_TAG_CBOR_LEADER # noqa: SLF001
|
|
257
|
+
return val
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains helper functions for packing+unpacking of single messages,
|
|
3
|
+
plus an unpacker factory for streams.
|
|
4
|
+
|
|
5
|
+
Extension types defined here:
|
|
6
|
+
2: contains raw bytes, interpreted as unsigned bignum
|
|
7
|
+
3: Path, as a msgpack object stream of its elements
|
|
8
|
+
4: contains raw bytes, interpreted as UTF-8, returned as (named) Proxy object
|
|
9
|
+
5: object constructor
|
|
10
|
+
6: marked Path
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from ._moat_msgpack import Codec, std_ext
|
|
16
|
+
|
|
17
|
+
__all__ = ["Codec", "std_ext"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@std_ext.encoder(2, int)
|
|
21
|
+
def _enc_int(codec, n):
|
|
22
|
+
codec # noqa:B018
|
|
23
|
+
return n.to_bytes((n.bit_length() + 7) // 8, "big")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@std_ext.decoder(2)
|
|
27
|
+
def _dec_bignum(codec, data):
|
|
28
|
+
codec # noqa:B018
|
|
29
|
+
return int.from_bytes(data, "big")
|
|
@@ -137,7 +137,7 @@ _TYPE_EXT = const(5)
|
|
|
137
137
|
DEFAULT_RECURSE_LIMIT = 20
|
|
138
138
|
|
|
139
139
|
|
|
140
|
-
_MSGPACK_HEADERS = {
|
|
140
|
+
_MSGPACK_HEADERS: dict[int, tuple[int, str] | tuple[int, str, int]] = {
|
|
141
141
|
0xC4: (1, "", _TYPE_BIN),
|
|
142
142
|
0xC5: (2, ">H", _TYPE_BIN),
|
|
143
143
|
0xC6: (4, ">I", _TYPE_BIN),
|
|
@@ -273,7 +273,7 @@ class Unpacker:
|
|
|
273
273
|
elif b == 0xC3:
|
|
274
274
|
obj = True
|
|
275
275
|
elif b <= 0xC6:
|
|
276
|
-
size, fmt, typ = _MSGPACK_HEADERS[b]
|
|
276
|
+
size, fmt, typ = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 3-tuple for these keys
|
|
277
277
|
self._reserve(size)
|
|
278
278
|
if len(fmt) > 0:
|
|
279
279
|
n = struct.unpack_from(fmt, self._buffer, self._buf_pos)[0]
|
|
@@ -282,13 +282,13 @@ class Unpacker:
|
|
|
282
282
|
self._buf_pos += size
|
|
283
283
|
obj = self._read(n)
|
|
284
284
|
elif b <= 0xC9:
|
|
285
|
-
size, fmt, typ = _MSGPACK_HEADERS[b]
|
|
285
|
+
size, fmt, typ = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 3-tuple for these keys
|
|
286
286
|
self._reserve(size)
|
|
287
287
|
L, n = struct.unpack_from(fmt, self._buffer, self._buf_pos)
|
|
288
288
|
self._buf_pos += size
|
|
289
289
|
obj = self._read(L)
|
|
290
290
|
elif b <= 0xD3:
|
|
291
|
-
size, fmt = _MSGPACK_HEADERS[b]
|
|
291
|
+
size, fmt = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 2-tuple for these keys
|
|
292
292
|
self._reserve(size)
|
|
293
293
|
if len(fmt) > 0:
|
|
294
294
|
obj = struct.unpack_from(fmt, self._buffer, self._buf_pos)[0]
|
|
@@ -296,12 +296,12 @@ class Unpacker:
|
|
|
296
296
|
obj = self._buffer[self._buf_pos]
|
|
297
297
|
self._buf_pos += size
|
|
298
298
|
elif b <= 0xD8:
|
|
299
|
-
size, fmt, typ = _MSGPACK_HEADERS[b]
|
|
299
|
+
size, fmt, typ = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 3-tuple for these keys
|
|
300
300
|
self._reserve(size + 1)
|
|
301
301
|
n, obj = struct.unpack_from(fmt, self._buffer, self._buf_pos)
|
|
302
302
|
self._buf_pos += size + 1
|
|
303
303
|
elif b <= 0xDB:
|
|
304
|
-
size, fmt, typ = _MSGPACK_HEADERS[b]
|
|
304
|
+
size, fmt, typ = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 3-tuple for these keys
|
|
305
305
|
self._reserve(size)
|
|
306
306
|
if len(fmt) > 0:
|
|
307
307
|
(n,) = struct.unpack_from(fmt, self._buffer, self._buf_pos)
|
|
@@ -310,12 +310,12 @@ class Unpacker:
|
|
|
310
310
|
self._buf_pos += size
|
|
311
311
|
obj = self._read(n)
|
|
312
312
|
elif b <= 0xDD:
|
|
313
|
-
size, fmt, typ = _MSGPACK_HEADERS[b]
|
|
313
|
+
size, fmt, typ = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 3-tuple for these keys
|
|
314
314
|
self._reserve(size)
|
|
315
315
|
(n,) = struct.unpack_from(fmt, self._buffer, self._buf_pos)
|
|
316
316
|
self._buf_pos += size
|
|
317
317
|
else: # if b <= 0xDF: # can't be anything else
|
|
318
|
-
size, fmt, typ = _MSGPACK_HEADERS[b]
|
|
318
|
+
size, fmt, typ = _MSGPACK_HEADERS[b] # type: ignore[misc] # always 3-tuple for these keys
|
|
319
319
|
self._reserve(size)
|
|
320
320
|
(n,) = struct.unpack_from(fmt, self._buffer, self._buf_pos)
|
|
321
321
|
self._buf_pos += size
|
|
@@ -6,6 +6,11 @@ from moat.util import yload, yprint
|
|
|
6
6
|
|
|
7
7
|
from ._base import Codec as _Codec
|
|
8
8
|
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from ._base import ByteType
|
|
13
|
+
|
|
9
14
|
|
|
10
15
|
class Codec(_Codec):
|
|
11
16
|
"basic JSON codec"
|
|
@@ -24,8 +29,8 @@ class Codec(_Codec):
|
|
|
24
29
|
"basic decoder"
|
|
25
30
|
return yload(data.decode("utf-8"))
|
|
26
31
|
|
|
27
|
-
def feed(self,
|
|
28
|
-
self._buf.extend(
|
|
32
|
+
def feed(self, data: ByteType) -> None: # noqa: D102
|
|
33
|
+
self._buf.extend(data)
|
|
29
34
|
|
|
30
35
|
def __next__(self):
|
|
31
36
|
i = self._buf.find(b"\n---\n")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moat-lib-codec
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.14
|
|
4
4
|
Summary: A simple command/stream multiplexer
|
|
5
5
|
Author-email: Matthias Urlichs <matthias@urlichs.de>
|
|
6
6
|
Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
|
|
@@ -17,8 +17,8 @@ Requires-Python: >=3.8
|
|
|
17
17
|
Description-Content-Type: text/x-rst
|
|
18
18
|
License-File: LICENSE.txt
|
|
19
19
|
Requires-Dist: anyio~=4.2
|
|
20
|
-
Requires-Dist: moat-lib-rpc~=0.
|
|
21
|
-
Requires-Dist: moat-lib-micro~=0.
|
|
22
|
-
Requires-Dist: moat-lib-proxy~=0.1.
|
|
23
|
-
Requires-Dist: moat-util~=0.
|
|
20
|
+
Requires-Dist: moat-lib-rpc~=0.6.1
|
|
21
|
+
Requires-Dist: moat-lib-micro~=0.2.2
|
|
22
|
+
Requires-Dist: moat-lib-proxy~=0.1.1
|
|
23
|
+
Requires-Dist: moat-util~=0.62.6
|
|
24
24
|
Dynamic: license-file
|
|
@@ -10,12 +10,16 @@ debian/rules
|
|
|
10
10
|
src/moat/lib/codec/__init__.py
|
|
11
11
|
src/moat/lib/codec/_base.py
|
|
12
12
|
src/moat/lib/codec/_cbor.py
|
|
13
|
+
src/moat/lib/codec/_moat_cbor.py
|
|
14
|
+
src/moat/lib/codec/_moat_msgpack.py
|
|
13
15
|
src/moat/lib/codec/binary.py
|
|
14
16
|
src/moat/lib/codec/bool.py
|
|
15
17
|
src/moat/lib/codec/cbor.py
|
|
16
18
|
src/moat/lib/codec/errors.py
|
|
17
19
|
src/moat/lib/codec/json.py
|
|
20
|
+
src/moat/lib/codec/moat_cbor.py
|
|
18
21
|
src/moat/lib/codec/moat_kv.py
|
|
22
|
+
src/moat/lib/codec/moat_msgpack.py
|
|
19
23
|
src/moat/lib/codec/msgpack.py
|
|
20
24
|
src/moat/lib/codec/noop.py
|
|
21
25
|
src/moat/lib/codec/utf8.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moat_lib_codec-0.4.10 → moat_lib_codec-0.4.14}/src/moat_lib_codec.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|