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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libasterix
3
- Version: 0.36.1
3
+ Version: 0.36.3
4
4
  Summary: Asterix data processing library
5
5
  Author-email: Zoran Bošnjak <zoran.bosnjak@via.si>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "libasterix"
3
- version = "0.36.1"
3
+ version = "0.36.3"
4
4
  authors = [
5
5
  { name="Zoran Bošnjak", email="zoran.bosnjak@via.si" },
6
6
  ]
@@ -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 zip(fspec, cls.cv_items_list):
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 zip(fspec, cls.cv_items_list):
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) # type: ignore
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 zip(flags, cls.cv_items_list):
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: libasterix
3
- Version: 0.36.1
3
+ Version: 0.36.3
4
4
  Summary: Asterix data processing library
5
5
  Author-email: Zoran Bošnjak <zoran.bosnjak@via.si>
6
6
  License-Expression: MIT
@@ -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