libasterix 0.36.1__tar.gz → 0.36.3__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.
- {libasterix-0.36.1 → libasterix-0.36.3}/PKG-INFO +1 -1
- {libasterix-0.36.1 → libasterix-0.36.3}/pyproject.toml +1 -1
- {libasterix-0.36.1 → libasterix-0.36.3}/src/asterix/base.py +17 -6
- {libasterix-0.36.1 → libasterix-0.36.3}/src/libasterix.egg-info/PKG-INFO +1 -1
- {libasterix-0.36.1 → libasterix-0.36.3}/tests/test_asterix.py +38 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/LICENSE +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/README.md +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/setup.cfg +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/asterix/__init__.py +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/asterix/generated.py +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/asterix/py.typed +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/libasterix.egg-info/SOURCES.txt +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/libasterix.egg-info/dependency_links.txt +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/libasterix.egg-info/requires.txt +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/src/libasterix.egg-info/top_level.txt +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/tests/test_bitstring.py +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/tests/test_mypy.py +0 -0
- {libasterix-0.36.1 → libasterix-0.36.3}/tests/test_raw_datablock.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""
|
|
3
3
|
|
|
4
4
|
import copy
|
|
5
|
-
from itertools import chain, dropwhile
|
|
5
|
+
from itertools import chain, dropwhile, repeat
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from binascii import hexlify, unhexlify
|
|
8
8
|
from typing import *
|
|
@@ -576,7 +576,9 @@ class Spare(ItemBase):
|
|
|
576
576
|
return cls._parse(bs)
|
|
577
577
|
|
|
578
578
|
@classmethod
|
|
579
|
-
def create(cls, arg: int) -> 'Spare':
|
|
579
|
+
def create(cls, arg: Union['Spare', int]) -> 'Spare':
|
|
580
|
+
if isinstance(arg, Spare):
|
|
581
|
+
return arg
|
|
580
582
|
bs = Bits.from_uinteger(arg, cls.cv_bit_offset8, cls.cv_bit_size)
|
|
581
583
|
return cls(bs)
|
|
582
584
|
|
|
@@ -1019,6 +1021,15 @@ class Fspec:
|
|
|
1019
1021
|
(a, b) = s.split_at(n * 8)
|
|
1020
1022
|
return (cls(a), b)
|
|
1021
1023
|
|
|
1024
|
+
@classmethod
|
|
1025
|
+
def iter_complete(cls, flags: Any, items: List[Any]) \
|
|
1026
|
+
-> Iterator[Tuple[bool, Any]]:
|
|
1027
|
+
"""Make sure to visit all FSPEC bits, even after the last defined
|
|
1028
|
+
item. This is important, to let the caller check all FSPEC bits."""
|
|
1029
|
+
|
|
1030
|
+
for (a, b) in zip(flags, chain(items, repeat(None))):
|
|
1031
|
+
yield (a, b)
|
|
1032
|
+
|
|
1022
1033
|
def __iter__(self) -> Iterator[bool]:
|
|
1023
1034
|
n = 0
|
|
1024
1035
|
for flag in self.bs:
|
|
@@ -1087,7 +1098,7 @@ class Compound(Variation):
|
|
|
1087
1098
|
return result
|
|
1088
1099
|
fspec, remaining = result
|
|
1089
1100
|
items = {}
|
|
1090
|
-
for (flag, nsp) in
|
|
1101
|
+
for (flag, nsp) in Fspec.iter_complete(fspec, cls.cv_items_list):
|
|
1091
1102
|
if not flag:
|
|
1092
1103
|
continue
|
|
1093
1104
|
if nsp is None:
|
|
@@ -1287,7 +1298,7 @@ class Record:
|
|
|
1287
1298
|
fspec, remaining = result
|
|
1288
1299
|
items1: Dict[str, NonSpare] = {}
|
|
1289
1300
|
items2: List[Optional[List[Tuple[str, NonSpare]]]] = []
|
|
1290
|
-
for (flag, i) in
|
|
1301
|
+
for (flag, i) in Fspec.iter_complete(fspec, cls.cv_items_list):
|
|
1291
1302
|
if not flag:
|
|
1292
1303
|
continue
|
|
1293
1304
|
if issubclass(i, UapItemSpare):
|
|
@@ -1336,7 +1347,7 @@ class Record:
|
|
|
1336
1347
|
break
|
|
1337
1348
|
elif issubclass(i, UapItem):
|
|
1338
1349
|
nsp = i.cv_non_spare
|
|
1339
|
-
result2 = nsp.parse(remaining)
|
|
1350
|
+
result2 = nsp.parse(remaining)
|
|
1340
1351
|
if isinstance(result2, ValueError):
|
|
1341
1352
|
if pm == ParsingMode.StrictParsing:
|
|
1342
1353
|
return result2
|
|
@@ -1587,7 +1598,7 @@ class Expansion:
|
|
|
1587
1598
|
else:
|
|
1588
1599
|
raise Exception('Unexpected cv_type', a)
|
|
1589
1600
|
items = {}
|
|
1590
|
-
for (flag, nsp) in
|
|
1601
|
+
for (flag, nsp) in Fspec.iter_complete(flags, cls.cv_items_list):
|
|
1591
1602
|
if not flag:
|
|
1592
1603
|
continue
|
|
1593
1604
|
if nsp is None:
|
|
@@ -7,6 +7,7 @@ from typing import *
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
9
|
from . generated import *
|
|
10
|
+
from . import sample_records
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def test_create() -> None:
|
|
@@ -574,6 +575,16 @@ def test_compound0() -> None:
|
|
|
574
575
|
assert isinstance(result, ValueError)
|
|
575
576
|
|
|
576
577
|
|
|
578
|
+
def test_compound_fspec_error() -> None:
|
|
579
|
+
T = Cat_000_1_0.cv_record.spec('092')
|
|
580
|
+
# error: fspec bit is set between 'I1' and 'I2'
|
|
581
|
+
result1 = T.parse(Bits.from_bytes(unhexlify('c01122')))
|
|
582
|
+
assert isinstance(result1, ValueError)
|
|
583
|
+
# error: fspec bit is set after 'I2'
|
|
584
|
+
result2 = T.parse(Bits.from_bytes(unhexlify('a21122')))
|
|
585
|
+
assert isinstance(result2, ValueError)
|
|
586
|
+
|
|
587
|
+
|
|
577
588
|
def test_compound1() -> None:
|
|
578
589
|
T = Cat_000_1_0.cv_record.spec('093')
|
|
579
590
|
with pytest.raises(ValueError):
|
|
@@ -1163,6 +1174,33 @@ def test_empty() -> None:
|
|
|
1163
1174
|
rec2 = Cat_000_1_0.cv_record.create({})
|
|
1164
1175
|
assert rec2.is_empty()
|
|
1165
1176
|
|
|
1177
|
+
|
|
1178
|
+
def _test_roundtrip(num_records: int) -> None:
|
|
1179
|
+
"""For each specification and edition, create a few records,
|
|
1180
|
+
encode, decode, expect the same result."""
|
|
1181
|
+
|
|
1182
|
+
def check(Spec: AstCat, r: Record) -> None:
|
|
1183
|
+
records = list([r] * num_records)
|
|
1184
|
+
bs = b''.join([r.unparse().to_bytes() for r in records])
|
|
1185
|
+
if m_name is None:
|
|
1186
|
+
result = Spec.cv_uap.parse(Bits.from_bytes(bs)) # type: ignore
|
|
1187
|
+
else:
|
|
1188
|
+
result = Spec.cv_uap.parse( # type: ignore
|
|
1189
|
+
m_name, Bits.from_bytes(bs))
|
|
1190
|
+
assert not isinstance(result, ValueError)
|
|
1191
|
+
bs2 = b''.join([r.unparse().to_bytes() for r in result])
|
|
1192
|
+
assert bs2 == bs
|
|
1193
|
+
|
|
1194
|
+
for lst in manifest['CATS'].values(): # type: ignore
|
|
1195
|
+
for Spec in lst:
|
|
1196
|
+
for (m_name, r1, r2) in sample_records(Spec):
|
|
1197
|
+
check(Spec, r1)
|
|
1198
|
+
check(Spec, r2)
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
def test_roundtrip() -> None:
|
|
1202
|
+
_test_roundtrip(5)
|
|
1203
|
+
|
|
1166
1204
|
# python specific tests
|
|
1167
1205
|
|
|
1168
1206
|
|
|
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
|