sltcodec 2.0.0__tar.gz → 2.1.0__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.
- {sltcodec-2.0.0 → sltcodec-2.1.0}/PKG-INFO +2 -1
- {sltcodec-2.0.0 → sltcodec-2.1.0}/README.md +13 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/README_pypi.md +1 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/pyproject.toml +1 -1
- {sltcodec-2.0.0 → sltcodec-2.1.0}/src/sltcodec/types.py +9 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/tests/test_types.py +83 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/.github/workflows/publish_to_pypi.yml +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/.github/workflows/publish_to_testpypi.yml +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/.gitignore +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/.python-version +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/.vscode/launch.json +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/.vscode/settings.json +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/LICENSE +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/bump_major.ps1 +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/bump_minor.ps1 +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/bump_patch.ps1 +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/src/sltcodec/__init__.py +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/src/sltcodec/codec.py +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/tests/test_codec.py +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/tests/test_persistence.py +0 -0
- {sltcodec-2.0.0 → sltcodec-2.1.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sltcodec
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Decode and encode bytearrays according to struct layout definitions using sltcore.
|
|
5
5
|
Project-URL: Homepage, https://github.com/fangface-hub/StructLayoutToolkitCodec
|
|
6
6
|
Project-URL: Documentation, https://readthedocs.org
|
|
@@ -205,6 +205,7 @@ internal implementation details and are omitted from the public method tables.
|
|
|
205
205
|
| --- | --- |
|
|
206
206
|
| `range_check(env=None)` | Evaluate the field's range expression. |
|
|
207
207
|
| `from_value(field_def, value, type_dict=None, is_padding=False)` | Create an instance and resolve matching enum metadata. |
|
|
208
|
+
| `with_value(value, type_dict=None)` | Return a new instance with the given value; keeps `field_def` and `is_padding` and recomputes `enum_item`. |
|
|
208
209
|
| `__lt__(other)` | Compare field instances using field-definition order. |
|
|
209
210
|
|
|
210
211
|
#### `StructDef`
|
|
@@ -61,6 +61,19 @@ Layout persistence uses the explicit names `save_struct_layout` and
|
|
|
61
61
|
`load_struct_layout`. The former `save_type_dict` and `load_type_dict` API is
|
|
62
62
|
not part of the current public interface.
|
|
63
63
|
|
|
64
|
+
`FieldInstance` stays frozen. To change a decoded value, use
|
|
65
|
+
`FieldInstance.with_value(value, type_dict=None)`, which returns a new
|
|
66
|
+
instance instead of mutating the original. It keeps `field_def` and
|
|
67
|
+
`is_padding`, and recomputes `enum_item` from the new value and `type_dict`
|
|
68
|
+
by delegating to `FieldInstance.from_value`.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
updated_field = field_instance.with_value(
|
|
72
|
+
new_value,
|
|
73
|
+
struct_layout.type_dict,
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
64
77
|
## Versioning And Release
|
|
65
78
|
|
|
66
79
|
Version bump scripts are provided for patch, minor, and major releases:
|
|
@@ -188,6 +188,7 @@ internal implementation details and are omitted from the public method tables.
|
|
|
188
188
|
| --- | --- |
|
|
189
189
|
| `range_check(env=None)` | Evaluate the field's range expression. |
|
|
190
190
|
| `from_value(field_def, value, type_dict=None, is_padding=False)` | Create an instance and resolve matching enum metadata. |
|
|
191
|
+
| `with_value(value, type_dict=None)` | Return a new instance with the given value; keeps `field_def` and `is_padding` and recomputes `enum_item`. |
|
|
191
192
|
| `__lt__(other)` | Compare field instances using field-definition order. |
|
|
192
193
|
|
|
193
194
|
#### `StructDef`
|
|
@@ -347,6 +347,15 @@ class FieldInstance:
|
|
|
347
347
|
enum_item=enum_item,
|
|
348
348
|
is_padding=is_padding)
|
|
349
349
|
|
|
350
|
+
def with_value(self,
|
|
351
|
+
value: Any,
|
|
352
|
+
type_dict: "TypeDict | None" = None) -> "FieldInstance":
|
|
353
|
+
"""Return a new FieldInstance with the given value applied."""
|
|
354
|
+
return type(self).from_value(field_def=self.field_def,
|
|
355
|
+
value=value,
|
|
356
|
+
type_dict=type_dict,
|
|
357
|
+
is_padding=self.is_padding)
|
|
358
|
+
|
|
350
359
|
@staticmethod
|
|
351
360
|
def _resolve_enum_def(field_def: FieldDef,
|
|
352
361
|
type_dict: "TypeDict | None") -> EnumDef | None:
|
|
@@ -169,6 +169,89 @@ def test_field_instance_from_value_sets_enum_item_from_field_enum_def():
|
|
|
169
169
|
assert field_instance.enum_item == ("MANUAL", 1)
|
|
170
170
|
|
|
171
171
|
|
|
172
|
+
def _mode_enum_fixture() -> tuple[EnumDef, FieldDef, TypeDict]:
|
|
173
|
+
"""Build an enum-backed field definition and its type dictionary."""
|
|
174
|
+
enum_def = EnumDef(name="Mode", values={"AUTO": 0, "MANUAL": 1})
|
|
175
|
+
field_def = FieldDef(name="mode",
|
|
176
|
+
offset=InfoSize(0, 0),
|
|
177
|
+
size=InfoSize(1, 0),
|
|
178
|
+
type="unsigned int",
|
|
179
|
+
enum_def_name=enum_def.name)
|
|
180
|
+
type_dict = TypeDict(enum_dict={enum_def.name: enum_def})
|
|
181
|
+
return enum_def, field_def, type_dict
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_field_instance_with_value_keeps_original_unchanged():
|
|
185
|
+
"""Test FieldInstance.with_value does not mutate the original."""
|
|
186
|
+
_, field_def, type_dict = _mode_enum_fixture()
|
|
187
|
+
original = FieldInstance.from_value(field_def, 0, type_dict=type_dict)
|
|
188
|
+
|
|
189
|
+
original.with_value(1, type_dict)
|
|
190
|
+
|
|
191
|
+
assert original.value == 0
|
|
192
|
+
assert original.enum_item == ("AUTO", 0)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def test_field_instance_with_value_returns_new_instance():
|
|
196
|
+
"""Test FieldInstance.with_value returns a new instance with the value."""
|
|
197
|
+
_, field_def, type_dict = _mode_enum_fixture()
|
|
198
|
+
original = FieldInstance.from_value(field_def, 0, type_dict=type_dict)
|
|
199
|
+
|
|
200
|
+
updated = original.with_value(1, type_dict)
|
|
201
|
+
|
|
202
|
+
assert updated is not original
|
|
203
|
+
assert updated.value == 1
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def test_field_instance_with_value_preserves_field_def_and_padding():
|
|
207
|
+
"""Test FieldInstance.with_value preserves field_def and is_padding."""
|
|
208
|
+
_, field_def, type_dict = _mode_enum_fixture()
|
|
209
|
+
original = FieldInstance.from_value(field_def,
|
|
210
|
+
0,
|
|
211
|
+
type_dict=type_dict,
|
|
212
|
+
is_padding=True)
|
|
213
|
+
|
|
214
|
+
updated = original.with_value(1, type_dict)
|
|
215
|
+
|
|
216
|
+
assert updated.field_def is original.field_def
|
|
217
|
+
assert updated.is_padding is True
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def test_field_instance_with_value_updates_enum_item():
|
|
221
|
+
"""Test FieldInstance.with_value recomputes a matching enum_item."""
|
|
222
|
+
_, field_def, type_dict = _mode_enum_fixture()
|
|
223
|
+
original = FieldInstance.from_value(field_def, 0, type_dict=type_dict)
|
|
224
|
+
|
|
225
|
+
updated = original.with_value(1, type_dict)
|
|
226
|
+
|
|
227
|
+
assert updated.enum_item == ("MANUAL", 1)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_field_instance_with_value_clears_unmatched_enum_item():
|
|
231
|
+
"""Test FieldInstance.with_value clears enum_item when unmatched."""
|
|
232
|
+
_, field_def, type_dict = _mode_enum_fixture()
|
|
233
|
+
original = FieldInstance.from_value(field_def, 0, type_dict=type_dict)
|
|
234
|
+
|
|
235
|
+
updated = original.with_value(7, type_dict)
|
|
236
|
+
|
|
237
|
+
assert updated.enum_item is None
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def test_field_instance_with_value_without_type_dict():
|
|
241
|
+
"""Test FieldInstance.with_value works for plain fields."""
|
|
242
|
+
field_def = FieldDef(name="count",
|
|
243
|
+
offset=InfoSize(0, 0),
|
|
244
|
+
size=InfoSize(1, 0),
|
|
245
|
+
type="unsigned int")
|
|
246
|
+
original = FieldInstance.from_value(field_def, 1)
|
|
247
|
+
|
|
248
|
+
updated = original.with_value(2)
|
|
249
|
+
|
|
250
|
+
assert updated.value == 2
|
|
251
|
+
assert updated.enum_item is None
|
|
252
|
+
assert original.value == 1
|
|
253
|
+
|
|
254
|
+
|
|
172
255
|
def test_struct_def_metadata_json_round_trip():
|
|
173
256
|
"""Test that StructDef name/description are preserved in JSON."""
|
|
174
257
|
child = FieldDef(name="value",
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|