runtimepy 5.14.0__py3-none-any.whl → 5.14.1__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.
runtimepy/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # =====================================
2
2
  # generator=datazen
3
3
  # version=3.2.3
4
- # hash=c6b2bd8ab0196f119c02bcdf6807ecab
4
+ # hash=49d1cdab220096c364c12f39a37de0aa
5
5
  # =====================================
6
6
 
7
7
  """
@@ -10,7 +10,7 @@ Useful defaults and other package metadata.
10
10
 
11
11
  DESCRIPTION = "A framework for implementing Python services."
12
12
  PKG_NAME = "runtimepy"
13
- VERSION = "5.14.0"
13
+ VERSION = "5.14.1"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -5,7 +5,7 @@ A module implementing an interface for receiving struct messages.
5
5
  # built-in
6
6
  from io import BytesIO
7
7
  import os
8
- from typing import Callable
8
+ from typing import Callable, Optional
9
9
 
10
10
  # third-party
11
11
  from vcorelib.logging import LoggerMixin
@@ -16,11 +16,15 @@ from runtimepy.primitives.byte_order import ByteOrder
16
16
  from runtimepy.primitives.int import UnsignedInt
17
17
 
18
18
  StructHandler = Callable[[Protocol], None]
19
+ NonStructHandler = Callable[[BytesIO], bool]
20
+
21
+ NON_STRUCT_ID = 0
19
22
 
20
23
 
21
24
  class StructReceiver(LoggerMixin):
22
25
  """A class for sending and receiving struct messages."""
23
26
 
27
+ non_struct_message_prefix: bytes
24
28
  id_primitive: UnsignedInt
25
29
  byte_order: ByteOrder
26
30
 
@@ -29,15 +33,22 @@ class StructReceiver(LoggerMixin):
29
33
 
30
34
  super().__init__()
31
35
 
36
+ self.non_struct_handler: Optional[NonStructHandler] = None
32
37
  self.handlers: dict[int, StructHandler] = {}
33
38
  self.instances: dict[int, Protocol] = {}
34
39
  for factory in factories:
35
40
  self.register(factory)
36
41
 
42
+ def add_non_struct_handler(self, handler: NonStructHandler) -> None:
43
+ """Set the non-struct handler for this instance."""
44
+ assert self.non_struct_handler is None
45
+ self.non_struct_handler = handler
46
+
37
47
  def add_handler(self, identifier: int, handler: StructHandler) -> None:
38
48
  """Add a struct message handler."""
39
49
 
40
50
  assert identifier not in self.handlers
51
+ assert identifier != NON_STRUCT_ID
41
52
  self.handlers[identifier] = handler
42
53
 
43
54
  def register(self, factory: type[ProtocolFactory]) -> None:
@@ -45,9 +56,14 @@ class StructReceiver(LoggerMixin):
45
56
 
46
57
  inst = factory.singleton()
47
58
 
59
+ assert inst.id != NON_STRUCT_ID
60
+
48
61
  if not hasattr(self, "id_primitive"):
49
62
  self.id_primitive = inst.id_primitive.copy() # type: ignore
50
63
  self.byte_order = inst.byte_order
64
+ self.non_struct_message_prefix = self.id_primitive.kind.encode(
65
+ NON_STRUCT_ID, byte_order=self.byte_order
66
+ )
51
67
  else:
52
68
  assert self.id_primitive.kind == inst.id_primitive.kind
53
69
  assert self.byte_order == inst.byte_order
@@ -67,7 +83,23 @@ class StructReceiver(LoggerMixin):
67
83
  ident = self.id_primitive.from_stream(
68
84
  stream, byte_order=self.byte_order
69
85
  )
70
- if ident in self.instances:
86
+
87
+ # Handle non-struct messages.
88
+ if ident == NON_STRUCT_ID:
89
+ if self.non_struct_handler is not None:
90
+ if not self.non_struct_handler(stream):
91
+ self.logger.error(
92
+ "Parsing non-struct message failed."
93
+ )
94
+ stream.seek(0, os.SEEK_END)
95
+ else:
96
+ self.logger.error(
97
+ "No handler for non-struct messages."
98
+ )
99
+ stream.seek(0, os.SEEK_END)
100
+
101
+ # Handle struct messages.
102
+ elif ident in self.instances:
71
103
  inst = self.instances[ident]
72
104
  inst.from_stream(stream)
73
105
  if ident in self.handlers:
@@ -81,11 +113,5 @@ class StructReceiver(LoggerMixin):
81
113
 
82
114
  # Can't continue reading if we don't know this identifier.
83
115
  else:
84
- self.logger.error(
85
- "Unknown struct identifier '%d' "
86
- "@%d/%d of stream (aborting).",
87
- ident,
88
- stream.tell(),
89
- end_pos,
90
- )
116
+ self.logger.error("Unknown struct identifier '%d'.", ident)
91
117
  stream.seek(0, os.SEEK_END)
@@ -93,7 +93,12 @@ class Primitive(_Generic[T]):
93
93
 
94
94
  def __copy__(self) -> "Primitive[T]":
95
95
  """Make a copy of this primitive."""
96
- return type(self)(value=self.value)
96
+
97
+ return type(self)(
98
+ value=self.value,
99
+ scaling=self.scaling,
100
+ time_source=self.time_source,
101
+ )
97
102
 
98
103
  def copy(self) -> "Primitive[T]":
99
104
  """A simple wrapper for copy."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runtimepy
3
- Version: 5.14.0
3
+ Version: 5.14.1
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/libre-embedded/runtimepy
6
6
  Author: Libre Embedded
@@ -17,11 +17,11 @@ Classifier: Development Status :: 5 - Production/Stable
17
17
  Requires-Python: >=3.12
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
- Requires-Dist: vcorelib>=3.5.8
21
- Requires-Dist: psutil
22
- Requires-Dist: websockets
23
20
  Requires-Dist: aiofiles
21
+ Requires-Dist: websockets
24
22
  Requires-Dist: svgen>=0.7.12
23
+ Requires-Dist: vcorelib>=3.5.8
24
+ Requires-Dist: psutil
25
25
  Provides-Extra: test
26
26
  Requires-Dist: pylint; extra == "test"
27
27
  Requires-Dist: flake8; extra == "test"
@@ -51,11 +51,11 @@ Dynamic: requires-python
51
51
  =====================================
52
52
  generator=datazen
53
53
  version=3.2.3
54
- hash=f46a9eb2c8979cc9ff0a3444077956ec
54
+ hash=06a038e989fda153238ee650b2f26604
55
55
  =====================================
56
56
  -->
57
57
 
58
- # runtimepy ([5.14.0](https://pypi.org/project/runtimepy/))
58
+ # runtimepy ([5.14.1](https://pypi.org/project/runtimepy/))
59
59
 
60
60
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
61
61
  ![Build Status](https://github.com/libre-embedded/runtimepy/workflows/Python%20Package/badge.svg)
@@ -1,4 +1,4 @@
1
- runtimepy/__init__.py,sha256=QTcIVQhNPp8R5ZdjWYD99HzoCmAlfUyTO-OLPwSonys,391
1
+ runtimepy/__init__.py,sha256=wIq7AXNNH4hbtlOUrh_ZOpeVYs9my1uq06w3IeQ8EXk,391
2
2
  runtimepy/__main__.py,sha256=IKioH2xOtsXwrwb9zABDQEJvuAX--Lnh84TeSz0XSs0,332
3
3
  runtimepy/app.py,sha256=Er1ZKKrG9U0FV0gQg_GYF9xDb89HgYnVzS5SjxGa2Tg,970
4
4
  runtimepy/dev_requirements.txt,sha256=VZhW6bJ5YbwaoN4d_XxZFuN5BbDLaG7ngKrGnugVPRw,245
@@ -27,7 +27,7 @@ runtimepy/codec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  runtimepy/codec/protocol/__init__.py,sha256=0mdPIb5mpkqofClqW23kslsgc3V_aSKJ1RmjEHmKfeI,1673
28
28
  runtimepy/codec/protocol/base.py,sha256=8pt8va16zHcHIgFTyhfx6tgDcsQxbqL93CfSgq0ZTBY,11796
29
29
  runtimepy/codec/protocol/json.py,sha256=pDEpHYFNYjiU2whvQemdZmH9Igx7aLEYCoS_Xpnqdcs,4483
30
- runtimepy/codec/protocol/receiver.py,sha256=67fH90YY3bgMzF-aqsyUvpIF77qxaMX3NJVwCC4BgKc,2976
30
+ runtimepy/codec/protocol/receiver.py,sha256=RGfpTNiFB_ZtDXtnMYSQ6oO3HiIJKcwCSwoIgvtMsbY,4085
31
31
  runtimepy/codec/system/__init__.py,sha256=fIOUo7QhwI81YAIz9myeSo1oo94De41sK5HKJ-sAdfY,7959
32
32
  runtimepy/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  runtimepy/commands/all.py,sha256=eAn52vuAgOh0jr93LROfbTjSPuJILGFRCPB9UeS3Q1c,1537
@@ -248,7 +248,7 @@ runtimepy/net/websocket/__init__.py,sha256=YjSmoxiigmsI_hcQw6nueX7bxhrRGerEERnPv
248
248
  runtimepy/net/websocket/connection.py,sha256=BMR58bLpHuulCdbLGnmMdFJOF53wVxYcUe52WbdzKEM,9025
249
249
  runtimepy/noise/__init__.py,sha256=EJM7h3t_z74wwrn6FAFQwYE2yUcOZQ1K1IQqOb8Z0AI,384
250
250
  runtimepy/primitives/__init__.py,sha256=g5IK6e_UZuGhj9QNYoCn5TbhNatWX0nEYUs-JzsOizQ,2618
251
- runtimepy/primitives/base.py,sha256=BaGPUTeVMnLnTPcpjqnS2lzPN74Pe5C0XaQdgrTfW7A,9185
251
+ runtimepy/primitives/base.py,sha256=5bMNHA9LA10qg8Qpg1YDjkfRZK0XWyaQsTNkNzaR9Es,9285
252
252
  runtimepy/primitives/bool.py,sha256=lATPgb1e62rjLn5XlJX8lP3tVYR3DlxV8RT9HpOMdT0,1640
253
253
  runtimepy/primitives/byte_order.py,sha256=J2Pg3gXg8Lmu_uU2mduNJt3mnP_enwDI4Y-X8kWAUP0,1456
254
254
  runtimepy/primitives/evaluation.py,sha256=0N7mT8uoiJaY-coF2PeEXU2WO-FmbyN2Io9_EaghO9Q,4657
@@ -302,9 +302,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
302
302
  runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
303
303
  runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
304
304
  runtimepy/ui/controls.py,sha256=yvT7h3thbYaitsakcIAJ90EwKzJ4b-jnc6p3UuVf_XE,1241
305
- runtimepy-5.14.0.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
306
- runtimepy-5.14.0.dist-info/METADATA,sha256=7g1Ho2eto4w_nLS1GXjqyuHOlAZYXvFHXeYoOq8s194,9269
307
- runtimepy-5.14.0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
308
- runtimepy-5.14.0.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
309
- runtimepy-5.14.0.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
310
- runtimepy-5.14.0.dist-info/RECORD,,
305
+ runtimepy-5.14.1.dist-info/licenses/LICENSE,sha256=yKBRwbO-cOPBrlpsZmJkkSa33DfY31aE8t7lZ0DwlUo,1071
306
+ runtimepy-5.14.1.dist-info/METADATA,sha256=r0_VenSwssfIdr8Qd4p-yFS-h_gDAZAtba3-OGnA5hc,9269
307
+ runtimepy-5.14.1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
308
+ runtimepy-5.14.1.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
309
+ runtimepy-5.14.1.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
310
+ runtimepy-5.14.1.dist-info/RECORD,,