moat-lib-codec 0.2.4__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.2.4/.gitignore +48 -0
- moat_lib_codec-0.2.4/Makefile +15 -0
- moat_lib_codec-0.2.4/PKG-INFO +80 -0
- moat_lib_codec-0.2.4/README.rst +60 -0
- moat_lib_codec-0.2.4/moat/__init__.py +9 -0
- moat_lib_codec-0.2.4/moat/lib/codec/__init__.py +21 -0
- moat_lib_codec-0.2.4/moat/lib/codec/_base.py +80 -0
- moat_lib_codec-0.2.4/moat/lib/codec/cbor.py +457 -0
- moat_lib_codec-0.2.4/moat/lib/codec/json.py +31 -0
- moat_lib_codec-0.2.4/moat/lib/codec/msgpack.py +74 -0
- moat_lib_codec-0.2.4/moat/lib/codec/noop.py +29 -0
- moat_lib_codec-0.2.4/moat/lib/codec/proxy.py +280 -0
- moat_lib_codec-0.2.4/moat/lib/codec/utf8.py +44 -0
- moat_lib_codec-0.2.4/moat_lib_codec.egg-info/PKG-INFO +80 -0
- moat_lib_codec-0.2.4/moat_lib_codec.egg-info/SOURCES.txt +19 -0
- moat_lib_codec-0.2.4/moat_lib_codec.egg-info/dependency_links.txt +1 -0
- moat_lib_codec-0.2.4/moat_lib_codec.egg-info/requires.txt +1 -0
- moat_lib_codec-0.2.4/moat_lib_codec.egg-info/top_level.txt +1 -0
- moat_lib_codec-0.2.4/pyproject.toml +136 -0
- moat_lib_codec-0.2.4/setup.cfg +4 -0
- moat_lib_codec-0.2.4/tests/test_basic.py +85 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
/debian/
|
|
3
|
+
.#*
|
|
4
|
+
\#*
|
|
5
|
+
/build/
|
|
6
|
+
.cache
|
|
7
|
+
/*.cfg
|
|
8
|
+
*,cover
|
|
9
|
+
.coverage
|
|
10
|
+
.coverage.*
|
|
11
|
+
/.coverage
|
|
12
|
+
/coverage.xml
|
|
13
|
+
/dist/
|
|
14
|
+
docs/_build/
|
|
15
|
+
docs/build/
|
|
16
|
+
/downloads/
|
|
17
|
+
/*.egg
|
|
18
|
+
/*.egg-info/
|
|
19
|
+
/.eggs/
|
|
20
|
+
/eggs/
|
|
21
|
+
/.env
|
|
22
|
+
/env/
|
|
23
|
+
/ENV/
|
|
24
|
+
/htmlcov/
|
|
25
|
+
/.hypothesis/
|
|
26
|
+
/.installed.cfg
|
|
27
|
+
*.log
|
|
28
|
+
*.manifest
|
|
29
|
+
*.mo
|
|
30
|
+
/obj/
|
|
31
|
+
/parts/
|
|
32
|
+
pip-delete-this-directory.txt
|
|
33
|
+
pip-log.txt
|
|
34
|
+
*.pot
|
|
35
|
+
/.pybuild/
|
|
36
|
+
*.py[cod]
|
|
37
|
+
/.pytest_cache/
|
|
38
|
+
/sdist/
|
|
39
|
+
*.so
|
|
40
|
+
/tests/plugins/test.db
|
|
41
|
+
.tox/
|
|
42
|
+
/var/
|
|
43
|
+
/.venv
|
|
44
|
+
/venv/
|
|
45
|
+
/wheels/
|
|
46
|
+
|
|
47
|
+
# Debian packaging
|
|
48
|
+
/debian/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/make -f
|
|
2
|
+
|
|
3
|
+
PACKAGE = moat-lib-codec
|
|
4
|
+
MAKEINCL ?= $(shell python3 -mmoat src path)/make/py
|
|
5
|
+
|
|
6
|
+
ifneq ($(wildcard $(MAKEINCL)),)
|
|
7
|
+
include $(MAKEINCL)
|
|
8
|
+
# availabe via http://github.com/smurfix/sourcemgr
|
|
9
|
+
|
|
10
|
+
else
|
|
11
|
+
%:
|
|
12
|
+
@echo "Please fix 'python3 -mmoat src path'."
|
|
13
|
+
@exit 1
|
|
14
|
+
endif
|
|
15
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: moat-lib-codec
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: A simple command/stream multiplexer
|
|
5
|
+
Author-email: Matthias Urlichs <matthias@urlichs.de>
|
|
6
|
+
Maintainer-email: Matthias Urlichs <matthias@urlichs.de>
|
|
7
|
+
Project-URL: homepage, https://m-o-a-t.org
|
|
8
|
+
Project-URL: repository, https://github.com/M-o-a-T/moat-lib-codec
|
|
9
|
+
Keywords: MoaT
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: License :: OSI Approved
|
|
12
|
+
Classifier: Framework :: AnyIO
|
|
13
|
+
Classifier: Framework :: Trio
|
|
14
|
+
Classifier: Framework :: AsyncIO
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/x-rst
|
|
19
|
+
Requires-Dist: anyio~=3.0
|
|
20
|
+
|
|
21
|
+
======================
|
|
22
|
+
The MoaT-Codec library
|
|
23
|
+
======================
|
|
24
|
+
|
|
25
|
+
This library packages various codecs used for MoaT protocols
|
|
26
|
+
in a way that's reason- and stream-able.
|
|
27
|
+
|
|
28
|
+
Interface
|
|
29
|
+
+++++++++
|
|
30
|
+
|
|
31
|
+
Codec
|
|
32
|
+
-----
|
|
33
|
+
|
|
34
|
+
* encode(obj)
|
|
35
|
+
|
|
36
|
+
Encode the object to a bytestream.
|
|
37
|
+
|
|
38
|
+
* decode(bytes)
|
|
39
|
+
|
|
40
|
+
Decode the given bytes to a single object.
|
|
41
|
+
|
|
42
|
+
* feed(bytes, final=False)
|
|
43
|
+
|
|
44
|
+
Data stream. Returns an array of objects.
|
|
45
|
+
|
|
46
|
+
This method only exists when a sequence of encoded objects can be streamed,
|
|
47
|
+
i.e. contains built-in message boundaries.
|
|
48
|
+
|
|
49
|
+
if @final is ``True``, raise an exception if there is an incomplete
|
|
50
|
+
object in the buffer after this call.
|
|
51
|
+
|
|
52
|
+
* getstate(), setstate(\*args)
|
|
53
|
+
|
|
54
|
+
A streaming decoder may store partially-decoded state (unprocessed
|
|
55
|
+
buffer) here.
|
|
56
|
+
|
|
57
|
+
The list of accepted objects is implementation dependent.
|
|
58
|
+
|
|
59
|
+
Extension
|
|
60
|
+
---------
|
|
61
|
+
|
|
62
|
+
Extension types vary by whether they carry binary data as in (msgpack), or
|
|
63
|
+
objects (as in cbor).
|
|
64
|
+
|
|
65
|
+
* binary (classvar): True if msgpack-style, False if cbor-style
|
|
66
|
+
|
|
67
|
+
* encoder(cls, key, fn)
|
|
68
|
+
|
|
69
|
+
Encode an object ``obj`` of type ``type``. ``fn(codec, obj)`` must return
|
|
70
|
+
a bytestring / an encodeable object. If the registration key is ``None``
|
|
71
|
+
the function must return a tuple with the key as first element.
|
|
72
|
+
|
|
73
|
+
* decoder(key, fn)
|
|
74
|
+
|
|
75
|
+
Add a decoder (key, data) to an object. ``fn(codec, data)`` is called with a
|
|
76
|
+
bytestring / a decoded object, and returns whatever has been encoded.
|
|
77
|
+
|
|
78
|
+
Extensions get the codec as their first argument. They can use it to store
|
|
79
|
+
data, e.g. references. The extension object is available as ``codec.ext``.
|
|
80
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
======================
|
|
2
|
+
The MoaT-Codec library
|
|
3
|
+
======================
|
|
4
|
+
|
|
5
|
+
This library packages various codecs used for MoaT protocols
|
|
6
|
+
in a way that's reason- and stream-able.
|
|
7
|
+
|
|
8
|
+
Interface
|
|
9
|
+
+++++++++
|
|
10
|
+
|
|
11
|
+
Codec
|
|
12
|
+
-----
|
|
13
|
+
|
|
14
|
+
* encode(obj)
|
|
15
|
+
|
|
16
|
+
Encode the object to a bytestream.
|
|
17
|
+
|
|
18
|
+
* decode(bytes)
|
|
19
|
+
|
|
20
|
+
Decode the given bytes to a single object.
|
|
21
|
+
|
|
22
|
+
* feed(bytes, final=False)
|
|
23
|
+
|
|
24
|
+
Data stream. Returns an array of objects.
|
|
25
|
+
|
|
26
|
+
This method only exists when a sequence of encoded objects can be streamed,
|
|
27
|
+
i.e. contains built-in message boundaries.
|
|
28
|
+
|
|
29
|
+
if @final is ``True``, raise an exception if there is an incomplete
|
|
30
|
+
object in the buffer after this call.
|
|
31
|
+
|
|
32
|
+
* getstate(), setstate(\*args)
|
|
33
|
+
|
|
34
|
+
A streaming decoder may store partially-decoded state (unprocessed
|
|
35
|
+
buffer) here.
|
|
36
|
+
|
|
37
|
+
The list of accepted objects is implementation dependent.
|
|
38
|
+
|
|
39
|
+
Extension
|
|
40
|
+
---------
|
|
41
|
+
|
|
42
|
+
Extension types vary by whether they carry binary data as in (msgpack), or
|
|
43
|
+
objects (as in cbor).
|
|
44
|
+
|
|
45
|
+
* binary (classvar): True if msgpack-style, False if cbor-style
|
|
46
|
+
|
|
47
|
+
* encoder(cls, key, fn)
|
|
48
|
+
|
|
49
|
+
Encode an object ``obj`` of type ``type``. ``fn(codec, obj)`` must return
|
|
50
|
+
a bytestring / an encodeable object. If the registration key is ``None``
|
|
51
|
+
the function must return a tuple with the key as first element.
|
|
52
|
+
|
|
53
|
+
* decoder(key, fn)
|
|
54
|
+
|
|
55
|
+
Add a decoder (key, data) to an object. ``fn(codec, data)`` is called with a
|
|
56
|
+
bytestring / a decoded object, and returns whatever has been encoded.
|
|
57
|
+
|
|
58
|
+
Extensions get the codec as their first argument. They can use it to store
|
|
59
|
+
data, e.g. references. The extension object is available as ``codec.ext``.
|
|
60
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Codec library.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from ._base import Codec, Extension, NoCodecError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__all__ = ["Codec", "Extension", "get_codec", "NoCodecError"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_codec(name, *a, **kw) -> Codec:
|
|
14
|
+
"""
|
|
15
|
+
Loads and initializes the named codec.
|
|
16
|
+
"""
|
|
17
|
+
from importlib import import_module
|
|
18
|
+
|
|
19
|
+
if "." not in name:
|
|
20
|
+
name = "moat.lib.codec." + name
|
|
21
|
+
return import_module(name).Codec(*a, **kw)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from typing import Any, Callable
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NoCodecError(ValueError):
|
|
10
|
+
"No codec found"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class IncompleteData(ValueError):
|
|
14
|
+
"Stream chopped off"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Codec:
|
|
18
|
+
def __init__(self, ext=None):
|
|
19
|
+
if ext is None:
|
|
20
|
+
ext = Extension() # empty
|
|
21
|
+
self.ext = ext
|
|
22
|
+
self.buf = b""
|
|
23
|
+
|
|
24
|
+
def encode(self, obj: Any) -> bytes:
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
|
|
27
|
+
def decode(self, data: Any) -> Any:
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
def feed(self, data, final: bool = False) -> list[Any]:
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Extension:
|
|
35
|
+
binary: bool = None
|
|
36
|
+
|
|
37
|
+
def __init__(self):
|
|
38
|
+
self.enc: dict[type, tuple[int | None, Callable]] = {}
|
|
39
|
+
self.dec: dict(int, Callable) = {}
|
|
40
|
+
|
|
41
|
+
def encoder(self, key: int | None, cls: type, fn=None) -> None:
|
|
42
|
+
def _enc(fn):
|
|
43
|
+
self.enc[cls] = (key, fn)
|
|
44
|
+
return fn
|
|
45
|
+
|
|
46
|
+
if fn is None:
|
|
47
|
+
return _enc
|
|
48
|
+
else:
|
|
49
|
+
_enc(fn)
|
|
50
|
+
|
|
51
|
+
def decoder(self, key: int, fn=None) -> None:
|
|
52
|
+
def _dec(fn):
|
|
53
|
+
self.dec[key] = fn
|
|
54
|
+
return fn
|
|
55
|
+
|
|
56
|
+
if fn is None:
|
|
57
|
+
return _dec
|
|
58
|
+
else:
|
|
59
|
+
_dec(fn)
|
|
60
|
+
|
|
61
|
+
def encode(self, codec, obj) -> tuple[int, bytes]:
|
|
62
|
+
try:
|
|
63
|
+
key, fn = self.enc[type(obj)]
|
|
64
|
+
except KeyError:
|
|
65
|
+
try:
|
|
66
|
+
key, fn = self.enc[object]
|
|
67
|
+
except KeyError:
|
|
68
|
+
raise NoCodecError(codec, obj) from None
|
|
69
|
+
|
|
70
|
+
res = fn(codec, obj)
|
|
71
|
+
if key is None:
|
|
72
|
+
key, res = res
|
|
73
|
+
return key, res
|
|
74
|
+
|
|
75
|
+
def decode(self, codec, key, data):
|
|
76
|
+
try:
|
|
77
|
+
fn = self.dec[key]
|
|
78
|
+
except KeyError:
|
|
79
|
+
raise NoCodecError(codec, key) from None
|
|
80
|
+
return fn(codec, data)
|