runtimepy 5.14.2__py3-none-any.whl → 5.15.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 +2 -2
- runtimepy/channel/__init__.py +1 -4
- runtimepy/channel/environment/__init__.py +93 -2
- runtimepy/channel/environment/create.py +16 -1
- runtimepy/channel/environment/sample.py +10 -2
- runtimepy/channel/registry.py +2 -3
- runtimepy/codec/protocol/base.py +34 -14
- runtimepy/codec/protocol/json.py +5 -3
- runtimepy/codec/system/__init__.py +6 -2
- runtimepy/control/source.py +1 -1
- runtimepy/data/404.md +16 -0
- runtimepy/data/base.yaml +3 -0
- runtimepy/data/css/bootstrap_extra.css +59 -44
- runtimepy/data/css/main.css +23 -4
- runtimepy/data/dummy_load.yaml +5 -2
- runtimepy/data/factories.yaml +1 -0
- runtimepy/data/js/classes/App.js +54 -2
- runtimepy/data/js/classes/ChannelTable.js +6 -8
- runtimepy/data/js/classes/Plot.js +9 -4
- runtimepy/data/js/classes/TabFilter.js +47 -9
- runtimepy/data/js/classes/TabInterface.js +106 -11
- runtimepy/data/js/classes/WindowHashManager.js +30 -15
- runtimepy/data/js/init.js +18 -1
- runtimepy/data/js/markdown_page.js +10 -0
- runtimepy/data/js/sample.js +1 -0
- runtimepy/data/schemas/BitFields.yaml +9 -0
- runtimepy/data/schemas/RuntimeEnum.yaml +6 -0
- runtimepy/data/schemas/StructConfig.yaml +9 -1
- runtimepy/data/static/css/bootstrap-icons.min.css +4 -3
- runtimepy/data/static/css/bootstrap.min.css +3 -4
- runtimepy/data/static/css/fonts/bootstrap-icons.woff +0 -0
- runtimepy/data/static/css/fonts/bootstrap-icons.woff2 +0 -0
- runtimepy/data/static/js/bootstrap.bundle.min.js +5 -4
- runtimepy/data/static/js/webglplot.umd.min.js +2 -1
- runtimepy/data/static/svg/outline-dark.svg +22 -0
- runtimepy/data/static/svg/outline-light.svg +22 -0
- runtimepy/enum/__init__.py +13 -1
- runtimepy/enum/registry.py +13 -1
- runtimepy/message/__init__.py +3 -3
- runtimepy/mixins/logging.py +6 -1
- runtimepy/net/__init__.py +0 -2
- runtimepy/net/arbiter/info.py +36 -4
- runtimepy/net/arbiter/struct/__init__.py +3 -2
- runtimepy/net/connection.py +6 -7
- runtimepy/net/html/__init__.py +29 -11
- runtimepy/net/html/bootstrap/__init__.py +2 -2
- runtimepy/net/html/bootstrap/elements.py +44 -24
- runtimepy/net/html/bootstrap/tabs.py +18 -11
- runtimepy/net/http/__init__.py +3 -3
- runtimepy/net/http/request_target.py +3 -3
- runtimepy/net/mixin.py +4 -2
- runtimepy/net/server/__init__.py +16 -9
- runtimepy/net/server/app/__init__.py +1 -0
- runtimepy/net/server/app/create.py +3 -3
- runtimepy/net/server/app/env/__init__.py +30 -4
- runtimepy/net/server/app/env/settings.py +4 -7
- runtimepy/net/server/app/env/tab/base.py +2 -1
- runtimepy/net/server/app/env/tab/controls.py +141 -27
- runtimepy/net/server/app/env/tab/html.py +68 -26
- runtimepy/net/server/app/env/widgets.py +115 -61
- runtimepy/net/server/app/landing_page.py +1 -1
- runtimepy/net/server/app/tab.py +12 -3
- runtimepy/net/server/html.py +2 -2
- runtimepy/net/server/json.py +1 -1
- runtimepy/net/server/markdown.py +29 -12
- runtimepy/net/server/mux.py +29 -0
- runtimepy/net/stream/__init__.py +6 -5
- runtimepy/net/stream/base.py +4 -2
- runtimepy/net/tcp/connection.py +5 -3
- runtimepy/net/tcp/http/__init__.py +10 -9
- runtimepy/net/tcp/protocol.py +2 -2
- runtimepy/net/tcp/scpi/__init__.py +5 -2
- runtimepy/net/tcp/telnet/__init__.py +2 -1
- runtimepy/net/udp/connection.py +10 -6
- runtimepy/net/udp/protocol.py +5 -6
- runtimepy/net/udp/queue.py +5 -2
- runtimepy/net/udp/tftp/base.py +2 -1
- runtimepy/net/websocket/connection.py +58 -9
- runtimepy/primitives/array/__init__.py +7 -5
- runtimepy/primitives/base.py +3 -2
- runtimepy/primitives/field/__init__.py +35 -2
- runtimepy/primitives/field/fields.py +11 -2
- runtimepy/primitives/field/manager/base.py +19 -2
- runtimepy/primitives/serializable/base.py +5 -2
- runtimepy/primitives/serializable/fixed.py +5 -2
- runtimepy/primitives/serializable/prefixed.py +4 -1
- runtimepy/primitives/types/base.py +4 -1
- runtimepy/primitives/types/bounds.py +10 -4
- runtimepy/registry/__init__.py +20 -0
- runtimepy/registry/name.py +6 -0
- runtimepy/requirements.txt +2 -2
- runtimepy/ui/controls.py +20 -1
- {runtimepy-5.14.2.dist-info → runtimepy-5.15.1.dist-info}/METADATA +6 -6
- {runtimepy-5.14.2.dist-info → runtimepy-5.15.1.dist-info}/RECORD +98 -94
- {runtimepy-5.14.2.dist-info → runtimepy-5.15.1.dist-info}/WHEEL +1 -1
- runtimepy/data/404.html +0 -7
- {runtimepy-5.14.2.dist-info → runtimepy-5.15.1.dist-info}/entry_points.txt +0 -0
- {runtimepy-5.14.2.dist-info → runtimepy-5.15.1.dist-info}/licenses/LICENSE +0 -0
- {runtimepy-5.14.2.dist-info → runtimepy-5.15.1.dist-info}/top_level.txt +0 -0
|
@@ -14,6 +14,7 @@ from typing import cast as _cast
|
|
|
14
14
|
from vcorelib.io import ARBITER as _ARBITER
|
|
15
15
|
from vcorelib.io.types import EncodeResult as _EncodeResult
|
|
16
16
|
from vcorelib.io.types import JsonObject as _JsonObject
|
|
17
|
+
from vcorelib.namespace import Namespace
|
|
17
18
|
from vcorelib.paths import Pathlike as _Pathlike
|
|
18
19
|
|
|
19
20
|
# internal
|
|
@@ -86,7 +87,12 @@ class BitFieldsManagerBase:
|
|
|
86
87
|
"""Encode this bit-fields manager to a file."""
|
|
87
88
|
return fields_to_file(path, self.fields, **kwargs)
|
|
88
89
|
|
|
89
|
-
def add(
|
|
90
|
+
def add(
|
|
91
|
+
self,
|
|
92
|
+
fields: _BitFields,
|
|
93
|
+
namespace: Namespace = None,
|
|
94
|
+
track: bool = False,
|
|
95
|
+
) -> int:
|
|
90
96
|
"""Add new bit-fields to manage."""
|
|
91
97
|
|
|
92
98
|
# Ensure that new fields can't be added after the current fields
|
|
@@ -97,7 +103,12 @@ class BitFieldsManagerBase:
|
|
|
97
103
|
self.fields.append(fields)
|
|
98
104
|
|
|
99
105
|
# Register fields into the lookup structure.
|
|
106
|
+
to_add = {}
|
|
100
107
|
for name, field in fields.fields.items():
|
|
108
|
+
if namespace is not None:
|
|
109
|
+
name = namespace.namespace(name=name, track=track)
|
|
110
|
+
to_add[name] = field
|
|
111
|
+
|
|
101
112
|
ident = self.registry.register_name(name)
|
|
102
113
|
assert ident is not None, "Couldn't register bit-field '{name}'!"
|
|
103
114
|
assert name not in self.lookup, name
|
|
@@ -105,7 +116,13 @@ class BitFieldsManagerBase:
|
|
|
105
116
|
|
|
106
117
|
# Also store the enum mapping.
|
|
107
118
|
if field.is_enum:
|
|
108
|
-
|
|
119
|
+
runtime = self.enums[field.enum]
|
|
120
|
+
self.enum_lookup[name] = runtime
|
|
121
|
+
if runtime.default:
|
|
122
|
+
self.set(name, runtime.default)
|
|
123
|
+
|
|
124
|
+
# Add possible namespaced-name mappings.
|
|
125
|
+
fields.fields.update(to_add)
|
|
109
126
|
|
|
110
127
|
return index
|
|
111
128
|
|
|
@@ -11,6 +11,7 @@ from typing import TypeVar
|
|
|
11
11
|
|
|
12
12
|
# third-party
|
|
13
13
|
from vcorelib import DEFAULT_ENCODING
|
|
14
|
+
from vcorelib.io import BinaryMessage
|
|
14
15
|
|
|
15
16
|
# internal
|
|
16
17
|
from runtimepy.primitives.byte_order import (
|
|
@@ -133,7 +134,7 @@ class Serializable(ABC):
|
|
|
133
134
|
)
|
|
134
135
|
|
|
135
136
|
@abstractmethod
|
|
136
|
-
def update(self, data:
|
|
137
|
+
def update(self, data: BinaryMessage, timestamp_ns: int = None) -> int:
|
|
137
138
|
"""Update this serializable from a bytes instance."""
|
|
138
139
|
|
|
139
140
|
def update_str(self, data: str, timestamp_ns: int = None) -> int:
|
|
@@ -158,7 +159,9 @@ class Serializable(ABC):
|
|
|
158
159
|
|
|
159
160
|
return result
|
|
160
161
|
|
|
161
|
-
def update_chain(
|
|
162
|
+
def update_chain(
|
|
163
|
+
self, data: BinaryMessage, timestamp_ns: int = None
|
|
164
|
+
) -> int:
|
|
162
165
|
"""Update this serializable from a bytes instance."""
|
|
163
166
|
|
|
164
167
|
with _BytesIO(data) as stream:
|
|
@@ -5,6 +5,9 @@ A module implementing a fixed-size bytes serializable.
|
|
|
5
5
|
# built-in
|
|
6
6
|
from copy import copy as _copy
|
|
7
7
|
|
|
8
|
+
# third-party
|
|
9
|
+
from vcorelib.io import BinaryMessage
|
|
10
|
+
|
|
8
11
|
# internal
|
|
9
12
|
from runtimepy.primitives.serializable.base import Serializable
|
|
10
13
|
|
|
@@ -31,11 +34,11 @@ class FixedChunk(Serializable):
|
|
|
31
34
|
"""Get this serializable as a bytes instance."""
|
|
32
35
|
return self.data
|
|
33
36
|
|
|
34
|
-
def update(self, data:
|
|
37
|
+
def update(self, data: BinaryMessage, timestamp_ns: int = None) -> int:
|
|
35
38
|
"""Update this serializable from a bytes instance."""
|
|
36
39
|
|
|
37
40
|
del timestamp_ns
|
|
38
41
|
|
|
39
|
-
self.data = data
|
|
42
|
+
self.data = bytes(data)
|
|
40
43
|
self.size = len(self.data)
|
|
41
44
|
return self.size
|
|
@@ -7,6 +7,9 @@ primitive prefix to determine the size of the chunk portion.
|
|
|
7
7
|
from typing import BinaryIO as _BinaryIO
|
|
8
8
|
from typing import TypeVar
|
|
9
9
|
|
|
10
|
+
# third-party
|
|
11
|
+
from vcorelib.io import BinaryMessage
|
|
12
|
+
|
|
10
13
|
# internal
|
|
11
14
|
from runtimepy.primitives import Primitivelike, UnsignedInt, create
|
|
12
15
|
from runtimepy.primitives.byte_order import (
|
|
@@ -44,7 +47,7 @@ class PrefixedChunk(Serializable):
|
|
|
44
47
|
"""Get this chunk as a string."""
|
|
45
48
|
return str(self.chunk)
|
|
46
49
|
|
|
47
|
-
def update(self, data:
|
|
50
|
+
def update(self, data: BinaryMessage, timestamp_ns: int = None) -> int:
|
|
48
51
|
"""Update this serializable from a bytes instance."""
|
|
49
52
|
|
|
50
53
|
size = self.chunk.update(data, timestamp_ns=timestamp_ns)
|
|
@@ -14,6 +14,9 @@ from typing import TypeVar as _TypeVar
|
|
|
14
14
|
from typing import Union as _Union
|
|
15
15
|
from typing import cast as _cast
|
|
16
16
|
|
|
17
|
+
# third-party
|
|
18
|
+
from vcorelib.io import BinaryMessage
|
|
19
|
+
|
|
17
20
|
# internal
|
|
18
21
|
from runtimepy.primitives.byte_order import (
|
|
19
22
|
DEFAULT_BYTE_ORDER as _DEFAULT_BYTE_ORDER,
|
|
@@ -134,7 +137,7 @@ class PrimitiveType(_Generic[T]):
|
|
|
134
137
|
return _pack(byte_order.fmt + self.format, value)
|
|
135
138
|
|
|
136
139
|
def decode(
|
|
137
|
-
self, data:
|
|
140
|
+
self, data: BinaryMessage, byte_order: _ByteOrder = _DEFAULT_BYTE_ORDER
|
|
138
141
|
) -> PythonPrimitive:
|
|
139
142
|
"""Decode primitive based on this type."""
|
|
140
143
|
return _unpack(byte_order.fmt + self.format, data)[0] # type: ignore
|
|
@@ -31,9 +31,15 @@ class IntegerBounds(NamedTuple):
|
|
|
31
31
|
return max(self.min, min(val, self.max))
|
|
32
32
|
|
|
33
33
|
@staticmethod
|
|
34
|
-
def
|
|
34
|
+
def create_bit(bit_count: int, signed: bool) -> "IntegerBounds":
|
|
35
35
|
"""Compute maximum and minimum values given size and signedness."""
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
return IntegerBounds(
|
|
38
|
+
0 if not signed else -1 * (2 ** (bit_count - 1)),
|
|
39
|
+
(2 ** (bit_count if not signed else bit_count - 1)) - 1,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def create(byte_count: int, signed: bool) -> "IntegerBounds":
|
|
44
|
+
"""Compute maximum and minimum values given size and signedness."""
|
|
45
|
+
return IntegerBounds.create_bit(8 * byte_count, signed)
|
runtimepy/registry/__init__.py
CHANGED
|
@@ -20,6 +20,7 @@ from vcorelib.io.types import JsonValue as _JsonValue
|
|
|
20
20
|
from runtimepy.registry.item import RegistryItem as _RegistryItem
|
|
21
21
|
from runtimepy.registry.name import NameRegistry as _NameRegistry
|
|
22
22
|
from runtimepy.registry.name import RegistryKey as _RegistryKey
|
|
23
|
+
from runtimepy.registry.name import is_registry_key as _is_registry_key
|
|
23
24
|
from runtimepy.schemas import RuntimepyDictCodec as _RuntimepyDictCodec
|
|
24
25
|
|
|
25
26
|
T = _TypeVar("T", bound=_RegistryItem)
|
|
@@ -66,6 +67,15 @@ class Registry(_RuntimepyDictCodec, _Generic[T]):
|
|
|
66
67
|
for name, item in self.items.items()
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
def register_from_other(self, other: "Registry[T]") -> None:
|
|
71
|
+
"""Register missing elements from another registry."""
|
|
72
|
+
|
|
73
|
+
for name, instance in other.items.items():
|
|
74
|
+
if name in self.items:
|
|
75
|
+
assert self.items[name].id == instance.id, (name, instance)
|
|
76
|
+
else:
|
|
77
|
+
assert self.register(name, instance), (name, instance)
|
|
78
|
+
|
|
69
79
|
def register(self, name: str, item: T) -> bool:
|
|
70
80
|
"""Attempt to register a new item."""
|
|
71
81
|
|
|
@@ -100,6 +110,16 @@ class Registry(_RuntimepyDictCodec, _Generic[T]):
|
|
|
100
110
|
result = self.items[name]
|
|
101
111
|
return result
|
|
102
112
|
|
|
113
|
+
def registry_normalize(self, key: _RegistryKey | T) -> T:
|
|
114
|
+
"""Attempt to get an item from a registry key."""
|
|
115
|
+
|
|
116
|
+
if _is_registry_key(key):
|
|
117
|
+
result: T = self[_cast(str, key)]
|
|
118
|
+
else:
|
|
119
|
+
result = _cast(T, key)
|
|
120
|
+
|
|
121
|
+
return result
|
|
122
|
+
|
|
103
123
|
def __getitem__(self, key: _RegistryKey) -> T:
|
|
104
124
|
"""Get a registry item."""
|
|
105
125
|
|
runtimepy/registry/name.py
CHANGED
|
@@ -3,6 +3,7 @@ A simple name-to-identifier registry interface.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
# built-in
|
|
6
|
+
from typing import Any as _Any
|
|
6
7
|
from typing import MutableMapping as _MutableMapping
|
|
7
8
|
from typing import Optional as _Optional
|
|
8
9
|
from typing import Union as _Union
|
|
@@ -15,6 +16,11 @@ KeyToName = _MutableMapping[int, str]
|
|
|
15
16
|
NameToKey = _MutableMapping[str, int]
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
def is_registry_key(data: _Any) -> bool:
|
|
20
|
+
"""Determine if this data is a registry key."""
|
|
21
|
+
return isinstance(data, (int, str))
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
class NameRegistry(_TwoWayNameMapping[int]):
|
|
19
25
|
"""A simple class for keeping track of name-to-identifier mappings."""
|
|
20
26
|
|
runtimepy/requirements.txt
CHANGED
runtimepy/ui/controls.py
CHANGED
|
@@ -7,8 +7,11 @@ import math
|
|
|
7
7
|
from typing import Optional
|
|
8
8
|
|
|
9
9
|
# internal
|
|
10
|
-
from runtimepy.
|
|
10
|
+
from runtimepy.primitives.types.bounds import IntegerBounds
|
|
11
11
|
|
|
12
|
+
Literal = int | float | bool
|
|
13
|
+
Default = Optional[Literal]
|
|
14
|
+
Controls = dict[str, Literal | dict[str, Literal]]
|
|
12
15
|
DEFAULT_STEPS = 64.0
|
|
13
16
|
|
|
14
17
|
|
|
@@ -30,6 +33,22 @@ def make_slider(
|
|
|
30
33
|
return result
|
|
31
34
|
|
|
32
35
|
|
|
36
|
+
def bit_slider(width: int, signed: bool) -> Controls:
|
|
37
|
+
"""Make a slider for an unsigned integer width."""
|
|
38
|
+
bounds = IntegerBounds.create_bit(width, signed)
|
|
39
|
+
return make_slider(bounds.min, bounds.max, 2**width - 1)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def signed_slider(width: int) -> Controls:
|
|
43
|
+
"""Make a slider for an unsigned integer width."""
|
|
44
|
+
return bit_slider(width, True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def unsigned_slider(width: int) -> Controls:
|
|
48
|
+
"""Make a slider for an unsigned integer width."""
|
|
49
|
+
return bit_slider(width, False)
|
|
50
|
+
|
|
51
|
+
|
|
33
52
|
CANONICAL: dict[str, Controls] = {
|
|
34
53
|
"phase": make_slider(-math.pi, math.pi, 90, default=0.0),
|
|
35
54
|
"amplitude": make_slider(0.0, 2.0, 100.0, default=1.0),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: runtimepy
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.15.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,10 +17,10 @@ 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:
|
|
21
|
-
Requires-Dist: svgen>=0.7.12
|
|
22
|
-
Requires-Dist: vcorelib>=3.6.0
|
|
20
|
+
Requires-Dist: vcorelib>=3.6.2
|
|
23
21
|
Requires-Dist: websockets
|
|
22
|
+
Requires-Dist: svgen>=0.8.0
|
|
23
|
+
Requires-Dist: aiofiles
|
|
24
24
|
Requires-Dist: psutil
|
|
25
25
|
Provides-Extra: test
|
|
26
26
|
Requires-Dist: pylint; extra == "test"
|
|
@@ -51,11 +51,11 @@ Dynamic: requires-python
|
|
|
51
51
|
=====================================
|
|
52
52
|
generator=datazen
|
|
53
53
|
version=3.2.3
|
|
54
|
-
hash=
|
|
54
|
+
hash=21dc494ffe783ac9edf7769c4d5aa21e
|
|
55
55
|
=====================================
|
|
56
56
|
-->
|
|
57
57
|
|
|
58
|
-
# runtimepy ([5.
|
|
58
|
+
# runtimepy ([5.15.1](https://pypi.org/project/runtimepy/))
|
|
59
59
|
|
|
60
60
|
[](https://pypi.org/project/runtimepy/)
|
|
61
61
|

|