moat-lib-codec 0.4.21__tar.gz → 0.4.23__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.
Files changed (37) hide show
  1. {moat_lib_codec-0.4.21/src/moat_lib_codec.egg-info → moat_lib_codec-0.4.23}/PKG-INFO +20 -4
  2. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/README.md +15 -0
  3. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/debian/changelog +18 -0
  4. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/pyproject.toml +5 -4
  5. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/_base.py +2 -2
  6. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/_cbor.py +39 -21
  7. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/_moat_cbor.py +1 -1
  8. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/_moat_msgpack.py +1 -1
  9. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/bool.py +2 -2
  10. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/cbor.py +1 -1
  11. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/errors.py +1 -1
  12. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/json.py +1 -1
  13. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/jsonvalstr.py +1 -1
  14. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/jsonvalue.py +1 -1
  15. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/msgpack.py +11 -11
  16. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/noop.py +2 -2
  17. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/utf8.py +1 -1
  18. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/yaml.py +1 -1
  19. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23/src/moat_lib_codec.egg-info}/PKG-INFO +20 -4
  20. moat_lib_codec-0.4.23/src/moat_lib_codec.egg-info/requires.txt +6 -0
  21. moat_lib_codec-0.4.21/src/moat_lib_codec.egg-info/requires.txt +0 -5
  22. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/LICENSE.txt +0 -0
  23. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/Makefile +0 -0
  24. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/debian/.gitignore +0 -0
  25. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/debian/control +0 -0
  26. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/debian/py3dist-overrides +0 -0
  27. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/debian/rules +0 -0
  28. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/setup.cfg +0 -0
  29. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/__init__.py +0 -0
  30. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/binary.py +0 -0
  31. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/moat_cbor.py +0 -0
  32. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/moat_kv.py +0 -0
  33. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/moat_msgpack.py +0 -0
  34. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat/lib/codec/null.py +0 -0
  35. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat_lib_codec.egg-info/SOURCES.txt +0 -0
  36. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/src/moat_lib_codec.egg-info/dependency_links.txt +0 -0
  37. {moat_lib_codec-0.4.21 → moat_lib_codec-0.4.23}/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.21
3
+ Version: 0.4.23
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,10 +17,11 @@ Requires-Python: >=3.8
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE.txt
19
19
  Requires-Dist: anyio~=4.2
20
- Requires-Dist: moat-lib-rpc~=0.7.6
21
- Requires-Dist: moat-lib-micro~=0.3.4
20
+ Requires-Dist: moat-lib-rpc~=0.7.23
21
+ Requires-Dist: moat-lib-micro~=0.3.7
22
22
  Requires-Dist: moat-lib-proxy~=0.1.3
23
- Requires-Dist: moat-util~=0.64.0
23
+ Requires-Dist: moat-util~=0.64.13
24
+ Requires-Dist: moat-lib-path~=0.4.4
24
25
  Dynamic: license-file
25
26
 
26
27
  # The MoaT-Codec library
@@ -42,6 +43,21 @@ in a way that's reason- and stream-able.
42
43
  - JSON
43
44
  - YAML
44
45
 
46
+ On CPython the CBOR codec is implemented in pure Python. MicroPython
47
+ uses the [ccbor](https://github.com/M-o-a-T/micropython-ccbor) C module
48
+ instead (compiled into the firmware; `moat micro prep` builds it into the
49
+ test interpreters). The wire format is identical; the C decoder is stricter
50
+ than the pure-Python one in a few places:
51
+
52
+ - duplicate map keys are an error instead of silently overwriting the
53
+ earlier value,
54
+ - unassigned CBOR simple values are an error instead of a `Tag`,
55
+ - half/single-precision floats decode to their exact value instead of
56
+ being rounded to a fixed number of significant digits,
57
+ - the nesting depth is limited (default 32),
58
+ - a not-well-formed byte in an incremental stream is skipped after the
59
+ error is reported, so decoding can resynchronise.
60
+
45
61
  % end main
46
62
 
47
63
  ## Interface
@@ -17,6 +17,21 @@ in a way that's reason- and stream-able.
17
17
  - JSON
18
18
  - YAML
19
19
 
20
+ On CPython the CBOR codec is implemented in pure Python. MicroPython
21
+ uses the [ccbor](https://github.com/M-o-a-T/micropython-ccbor) C module
22
+ instead (compiled into the firmware; `moat micro prep` builds it into the
23
+ test interpreters). The wire format is identical; the C decoder is stricter
24
+ than the pure-Python one in a few places:
25
+
26
+ - duplicate map keys are an error instead of silently overwriting the
27
+ earlier value,
28
+ - unassigned CBOR simple values are an error instead of a `Tag`,
29
+ - half/single-precision floats decode to their exact value instead of
30
+ being rounded to a fixed number of significant digits,
31
+ - the nesting depth is limited (default 32),
32
+ - a not-well-formed byte in an incremental stream is skipped after the
33
+ error is reported, so decoding can resynchronise.
34
+
20
35
  % end main
21
36
 
22
37
  ## Interface
@@ -1,3 +1,21 @@
1
+ moat-lib-codec (0.4.23-1) unstable; urgency=medium
2
+
3
+ * New release for 26.5.49
4
+
5
+ -- Matthias Urlichs <matthias@urlichs.de> Fri, 06 Nov 2026 11:29:06 +0100
6
+
7
+ moat-lib-codec (0.4.22-2) unstable; urgency=medium
8
+
9
+ * New release for 26.5.35
10
+
11
+ -- Matthias Urlichs <matthias@urlichs.de> Wed, 04 Nov 2026 19:27:19 +0100
12
+
13
+ moat-lib-codec (0.4.22-1) unstable; urgency=medium
14
+
15
+ * New release for 26.4.26
16
+
17
+ -- Matthias Urlichs <matthias@urlichs.de> Sat, 03 Oct 2026 12:52:54 +0200
18
+
1
19
  moat-lib-codec (0.4.21-2) unstable; urgency=medium
2
20
 
3
21
  * New release for 26.4.8
@@ -13,10 +13,11 @@ classifiers = [
13
13
  ]
14
14
  dependencies = [
15
15
  "anyio ~= 4.2",
16
- "moat-lib-rpc ~= 0.7.6",
17
- "moat-lib-micro ~= 0.3.4",
16
+ "moat-lib-rpc ~= 0.7.23",
17
+ "moat-lib-micro ~= 0.3.7",
18
18
  "moat-lib-proxy ~= 0.1.3",
19
- "moat-util ~= 0.64.0",
19
+ "moat-util ~= 0.64.13",
20
+ "moat-lib-path ~= 0.4.4",
20
21
  ]
21
22
  keywords = ["MoaT"]
22
23
  requires-python = ">=3.8"
@@ -25,7 +26,7 @@ maintainers = [{email = "matthias@urlichs.de",name = "Matthias Urlichs"}]
25
26
  description='A simple command/stream multiplexer'
26
27
  readme = "README.md"
27
28
  authors = [{email = "matthias@urlichs.de",name = "Matthias Urlichs"}]
28
- version = "0.4.21"
29
+ version = "0.4.23"
29
30
 
30
31
  [project.urls]
31
32
  homepage = "https://m-o-a-t.org"
@@ -42,7 +42,7 @@ class Codec:
42
42
  ``__anext__``.
43
43
  """
44
44
 
45
- def __init__(self, ext=None):
45
+ def __init__(self, ext=None) -> None:
46
46
  if ext is None:
47
47
  ext = Extension() # empty
48
48
  self.ext = ext
@@ -113,7 +113,7 @@ if TYPE_CHECKING:
113
113
 
114
114
 
115
115
  class Extension:
116
- def __init__(self):
116
+ def __init__(self) -> None:
117
117
  self.enc: dict[type, tuple[int | None, Callable]] = {}
118
118
  self.dec: dict[int, Callable] = {}
119
119
 
@@ -42,11 +42,11 @@ CBOR_TAG_CBOR_LEADER = const(55800) # header for multiple CBOR items
42
42
  class Tag:
43
43
  "a random CBOR tag"
44
44
 
45
- def __init__(self, tag: int, value: Any = None):
45
+ def __init__(self, tag: int, value: Any = None) -> None:
46
46
  self.tag = tag
47
47
  self.value = value
48
48
 
49
- def __repr__(self):
49
+ def __repr__(self) -> str:
50
50
  return f"Tag({self.tag!r}, {self.value!r})"
51
51
 
52
52
  def __eq__(self, other):
@@ -107,10 +107,36 @@ def _bignum_to_bytearray(val):
107
107
  class ExtraData(ValueError):
108
108
  "buffer contains data beyond end of encoded object"
109
109
 
110
- def __str__(self):
110
+ def __str__(self) -> str:
111
111
  return "decoder received extra data."
112
112
 
113
113
 
114
+ def _shortest(data: bytes, fmt: str, digits: int) -> float:
115
+ """
116
+ Decode a half or single precision float.
117
+
118
+ The result is the shortest decimal number that encodes to the same
119
+ value, so that e.g. single precision 100.2 doesn't decode to
120
+ 100.19999694824219.
121
+
122
+ Args:
123
+ data: the encoded value.
124
+ fmt: its `struct` format.
125
+ digits: the number of significant digits that is always sufficient.
126
+ """
127
+ pf = struct.unpack(fmt, data)[0]
128
+ if pf == 0 or not math.isfinite(pf):
129
+ return pf
130
+ for n in range(1, digits):
131
+ res = float(f"{pf:.{n}g}")
132
+ try:
133
+ if struct.pack(fmt, res) == data:
134
+ return res
135
+ except OverflowError:
136
+ pass
137
+ return pf
138
+
139
+
114
140
  class Codec(_Codec):
115
141
  "Basic CBOR codec"
116
142
 
@@ -119,7 +145,7 @@ class Codec(_Codec):
119
145
 
120
146
  _buf_out: bytearray | None = None
121
147
 
122
- def __init__(self, use_attrdict: bool = False, **kw):
148
+ def __init__(self, use_attrdict: bool = False, **kw) -> None:
123
149
  super().__init__(**kw)
124
150
  self.use_attrdict = use_attrdict
125
151
  self.__kw = kw
@@ -247,7 +273,7 @@ class Codec(_Codec):
247
273
  self._enc_type_num(CBOR_BYTES, len(outb))
248
274
  w(outb)
249
275
 
250
- def _enc_string(self, val):
276
+ def _enc_string(self, val) -> None:
251
277
  if isinstance(val, str):
252
278
  val = val.encode("utf8", "surrogateescape")
253
279
  self._enc_type_num(CBOR_TEXT, len(val))
@@ -255,7 +281,7 @@ class Codec(_Codec):
255
281
  self._enc_type_num(CBOR_BYTES, len(val))
256
282
  self._w(val)
257
283
 
258
- def _enc_array(self, arr):
284
+ def _enc_array(self, arr) -> None:
259
285
  try:
260
286
  self._enc_type_num(CBOR_ARRAY, len(arr))
261
287
  except TypeError:
@@ -267,26 +293,26 @@ class Codec(_Codec):
267
293
  for x in arr:
268
294
  self._enc_any(x)
269
295
 
270
- def _enc_dict(self, d):
296
+ def _enc_dict(self, d) -> None:
271
297
  self._enc_type_num(CBOR_MAP, len(d))
272
298
  for k, v in d.items():
273
299
  self._enc_any(k)
274
300
  self._enc_any(v)
275
301
 
276
- def _enc_bool(self, b):
302
+ def _enc_bool(self, b) -> None:
277
303
  self._w(struct.pack("B", CBOR_TRUE if b else CBOR_FALSE))
278
304
 
279
- def _enc_tag(self, t, val=...):
305
+ def _enc_tag(self, t, val=...) -> None:
280
306
  if val is Ellipsis:
281
307
  t, val = t.tag, t.value
282
308
  self._enc_type_num(CBOR_TAG, t)
283
309
  self._enc_any(val)
284
310
 
285
- def _w(self, d):
311
+ def _w(self, d) -> None:
286
312
  assert self._buf_out is not None # set by encode() before calling _enc_any()
287
313
  self._buf_out.extend(d)
288
314
 
289
- def _enc_any(self, ob):
315
+ def _enc_any(self, ob) -> None:
290
316
  w = self._w
291
317
  if ob is None:
292
318
  w(struct.pack("B", CBOR_NULL))
@@ -405,17 +431,9 @@ class Codec(_Codec):
405
431
  def _dec_tagged(self, tb):
406
432
  # Some special cases of CBOR_7 best handled by special struct.unpack logic here
407
433
  if tb == CBOR_FLOAT16:
408
- data = self._read(2)
409
- pf = struct.unpack_from("!e", data, 0)[0]
410
- if pf != 0:
411
- pf = round(pf, int(4 - math.log10(abs(pf))))
412
- return pf
434
+ return _shortest(self._read(2), "!e", 5)
413
435
  elif tb == CBOR_FLOAT32:
414
- data = self._read(4)
415
- pf = struct.unpack_from("!f", data, 0)[0]
416
- if pf != 0:
417
- pf = round(pf, int(8 - math.log10(abs(pf))))
418
- return pf
436
+ return _shortest(self._read(4), "!f", 9)
419
437
  elif tb == CBOR_FLOAT64:
420
438
  data = self._read(8)
421
439
  pf = struct.unpack_from("!d", data, 0)[0]
@@ -34,7 +34,7 @@ class Codec(_cbor.Codec):
34
34
  CBOR codec with MoaT's standard extensions.
35
35
  """
36
36
 
37
- def __init__(self):
37
+ def __init__(self) -> None:
38
38
  super().__init__(ext=std_ext)
39
39
 
40
40
  def decode(self, data: ByteType): # noqa:D102,RUF100
@@ -29,7 +29,7 @@ ExtType = _msgpack.ExtType
29
29
  class Codec(_msgpack.Codec):
30
30
  "A MsgPack codec with our extensions"
31
31
 
32
- def __init__(self):
32
+ def __init__(self) -> None:
33
33
  super().__init__(ext=std_ext, use_attrdict=True)
34
34
 
35
35
 
@@ -14,7 +14,7 @@ class Codec(_Codec):
14
14
 
15
15
  null: bytes | None = None
16
16
 
17
- def __init__(self, on="on", off="off", null=None, **kw):
17
+ def __init__(self, on="on", off="off", null=None, **kw) -> None:
18
18
  super().__init__(**kw)
19
19
  if on is not None:
20
20
  self.on = on.encode("utf-8", "surrogateescape")
@@ -33,7 +33,7 @@ class Codec(_Codec):
33
33
  return self.on
34
34
  raise ValueError(obj)
35
35
 
36
- def decode(self, data):
36
+ def decode(self, data) -> bool | None:
37
37
  "some text > bool"
38
38
  if data == self.on:
39
39
  return True
@@ -21,7 +21,7 @@ def _tag_repr(dumper, data):
21
21
 
22
22
 
23
23
  class XTag: # noqa: D101
24
- def __init__(self, tag):
24
+ def __init__(self, tag) -> None:
25
25
  self.tag = tag
26
26
 
27
27
 
@@ -28,7 +28,7 @@ class SilentRemoteError(RemoteError): # ty:ignore[unsupported-base] # RemoteEr
28
28
  class NoPathError(KeyError):
29
29
  """An error that marks a nonexisting path"""
30
30
 
31
- def __str__(self):
31
+ def __str__(self) -> str:
32
32
  from moat.lib.path import Path # noqa: PLC0415
33
33
 
34
34
  return (
@@ -15,7 +15,7 @@ except ImportError:
15
15
  class Codec(_Codec):
16
16
  "basic JSON codec"
17
17
 
18
- def __init__(self, ext=None):
18
+ def __init__(self, ext=None) -> None:
19
19
  if ext is not None:
20
20
  raise ValueError("You can't extend the JSON codec")
21
21
  super().__init__()
@@ -10,7 +10,7 @@ from .jsonvalue import Codec as _Codec
10
10
  class Codec(_Codec):
11
11
  "JSON+Value using a stringified element"
12
12
 
13
- def __init__(self, ext=None):
13
+ def __init__(self, ext=None) -> None:
14
14
  if ext is not None:
15
15
  raise ValueError("You can't extend the JSON codec")
16
16
  super().__init__()
@@ -8,7 +8,7 @@ from .json import Codec as _Codec
8
8
  class Codec(_Codec):
9
9
  "JSON codec with 'value' element"
10
10
 
11
- def __init__(self, ext=None):
11
+ def __init__(self, ext=None) -> None:
12
12
  if ext is not None:
13
13
  raise ValueError("You can't extend the JSON codec")
14
14
  super().__init__()
@@ -39,7 +39,7 @@ __all__ = ["Codec", "ExtType"]
39
39
  class Codec(_Codec):
40
40
  "Extensible msgpack codec"
41
41
 
42
- def __init__(self, use_attrdict: bool = False, **kw):
42
+ def __init__(self, use_attrdict: bool = False, **kw) -> None:
43
43
  # TODO add keywords for msgpack enc/dec settings
44
44
  super().__init__(**kw)
45
45
  self.use_attrdict = use_attrdict
@@ -76,7 +76,7 @@ class Codec(_Codec):
76
76
  except NoCodecError:
77
77
  return ExtType(key, data)
78
78
 
79
- def feed(self, data):
79
+ def feed(self, data) -> None:
80
80
  "Add more bytes. Returns an iterator for the result."
81
81
  self.stream.feed(data)
82
82
 
@@ -107,24 +107,24 @@ class FormatError(UnpackException):
107
107
  class ExtraData(ValueError):
108
108
  "too much data in buffer"
109
109
 
110
- def __init__(self, unpacked, extra):
110
+ def __init__(self, unpacked, extra) -> None:
111
111
  self.unpacked = unpacked
112
112
  self.extra = extra
113
113
 
114
- def __str__(self):
114
+ def __str__(self) -> str:
115
115
  return "unpack(b) received extra data."
116
116
 
117
117
 
118
118
  class ExtType:
119
119
  """ExtType represents extension types in msgpack."""
120
120
 
121
- def __init__(self, code, data):
121
+ def __init__(self, code, data) -> None:
122
122
  if isinstance(data, memoryview):
123
123
  data = bytes(data)
124
124
  self.code = code
125
125
  self.data = data
126
126
 
127
- def __repr__(self):
127
+ def __repr__(self) -> str:
128
128
  return f"Ext({self.code}:{self.data})"
129
129
 
130
130
 
@@ -180,7 +180,7 @@ class Unpacker:
180
180
  ext_hook=ExtType,
181
181
  use_attrdict=False,
182
182
  min_memview_len=-1,
183
- ):
183
+ ) -> None:
184
184
  #: array of bytes fed.
185
185
  self._buffer = bytearray()
186
186
  #: Which position we currently reads
@@ -190,7 +190,7 @@ class Unpacker:
190
190
  self._min_memview_len = min_memview_len
191
191
  self._use_attrdict = use_attrdict
192
192
 
193
- def feed(self, data):
193
+ def feed(self, data) -> None:
194
194
  "set the buffer"
195
195
  if self._buffer and self._buf_pos < len(self._buffer):
196
196
  if self._buf_pos == 0:
@@ -235,7 +235,7 @@ class Unpacker:
235
235
  self._buf_pos = i + len(ret)
236
236
  return ret
237
237
 
238
- def _reserve(self, n):
238
+ def _reserve(self, n) -> None:
239
239
  remain_bytes = len(self._buffer) - self._buf_pos - n
240
240
 
241
241
  # Fast path: buffer has n bytes already
@@ -394,12 +394,12 @@ class Packer:
394
394
  self,
395
395
  # unicode_errors=None,
396
396
  default=None,
397
- ):
397
+ ) -> None:
398
398
  self._buffer = BytesIO()
399
399
  # self._unicode_errors = unicode_errors or "strict"
400
400
  self._default = default
401
401
 
402
- def _pack(self, obj, default=None):
402
+ def _pack(self, obj, default=None) -> None:
403
403
  # Warning, does not deal with recursive data structures
404
404
  # (except by running out of memory)
405
405
  list_types = (list, tuple)
@@ -8,7 +8,7 @@ from ._base import Codec as _Codec
8
8
  class Codec(_Codec):
9
9
  "no-op codec"
10
10
 
11
- def __init__(self, ext=None):
11
+ def __init__(self, ext=None) -> None:
12
12
  if ext is not None:
13
13
  raise ValueError("You can't extend the Null codec")
14
14
  super().__init__()
@@ -26,7 +26,7 @@ class Codec(_Codec):
26
26
  "no-op decode"
27
27
  return data
28
28
 
29
- def feed(self, data):
29
+ def feed(self, data) -> None:
30
30
  "no-op feed"
31
31
  self._buf += data
32
32
 
@@ -24,7 +24,7 @@ if TYPE_CHECKING:
24
24
  class Codec(_Codec):
25
25
  "Basic UTF-8 codec"
26
26
 
27
- def __init__(self, ext=None):
27
+ def __init__(self, ext=None) -> None:
28
28
  if ext is not None:
29
29
  raise ValueError("You can't extend the UTF8 codec")
30
30
  super().__init__()
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
15
15
  class Codec(_Codec):
16
16
  "basic JSON codec"
17
17
 
18
- def __init__(self, ext=None):
18
+ def __init__(self, ext=None) -> None:
19
19
  if ext is not None:
20
20
  raise ValueError("You can't extend the JSON codec")
21
21
  super().__init__()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moat-lib-codec
3
- Version: 0.4.21
3
+ Version: 0.4.23
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,10 +17,11 @@ Requires-Python: >=3.8
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE.txt
19
19
  Requires-Dist: anyio~=4.2
20
- Requires-Dist: moat-lib-rpc~=0.7.6
21
- Requires-Dist: moat-lib-micro~=0.3.4
20
+ Requires-Dist: moat-lib-rpc~=0.7.23
21
+ Requires-Dist: moat-lib-micro~=0.3.7
22
22
  Requires-Dist: moat-lib-proxy~=0.1.3
23
- Requires-Dist: moat-util~=0.64.0
23
+ Requires-Dist: moat-util~=0.64.13
24
+ Requires-Dist: moat-lib-path~=0.4.4
24
25
  Dynamic: license-file
25
26
 
26
27
  # The MoaT-Codec library
@@ -42,6 +43,21 @@ in a way that's reason- and stream-able.
42
43
  - JSON
43
44
  - YAML
44
45
 
46
+ On CPython the CBOR codec is implemented in pure Python. MicroPython
47
+ uses the [ccbor](https://github.com/M-o-a-T/micropython-ccbor) C module
48
+ instead (compiled into the firmware; `moat micro prep` builds it into the
49
+ test interpreters). The wire format is identical; the C decoder is stricter
50
+ than the pure-Python one in a few places:
51
+
52
+ - duplicate map keys are an error instead of silently overwriting the
53
+ earlier value,
54
+ - unassigned CBOR simple values are an error instead of a `Tag`,
55
+ - half/single-precision floats decode to their exact value instead of
56
+ being rounded to a fixed number of significant digits,
57
+ - the nesting depth is limited (default 32),
58
+ - a not-well-formed byte in an incremental stream is skipped after the
59
+ error is reported, so decoding can resynchronise.
60
+
45
61
  % end main
46
62
 
47
63
  ## Interface
@@ -0,0 +1,6 @@
1
+ anyio~=4.2
2
+ moat-lib-micro~=0.3.7
3
+ moat-lib-path~=0.4.4
4
+ moat-lib-proxy~=0.1.3
5
+ moat-lib-rpc~=0.7.23
6
+ moat-util~=0.64.13
@@ -1,5 +0,0 @@
1
- anyio~=4.2
2
- moat-lib-micro~=0.3.4
3
- moat-lib-proxy~=0.1.3
4
- moat-lib-rpc~=0.7.6
5
- moat-util~=0.64.0