oep-client-python 0.0.47__py3-none-any.whl → 0.0.48__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.
oep_client/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.0.47"
5
+ __version__ = "0.0.48"
oep_client/acquire.py CHANGED
@@ -1655,14 +1655,14 @@ class _Spool:
1655
1655
  p, nxt = ready[k][0], ready[j][1]
1656
1656
  x = self.segs[p]
1657
1657
  samples = sum(self.segs.pop(q).samples for q, _ in ready[k:j + 1])
1658
- if self.cur is not None and (self.cur["samples"] % 8 or any(self.cur["samples"] % d for d in self.ds)):
1658
+ if self.cur is not None and any(self.cur["samples"] % d for d in self.ds):
1659
1659
  self._close(follows=True) # a grid restart (format 1) is not a loss: the next part follows on
1660
1660
  self._open(p, x)
1661
1661
  data = bytes(self.pending[p - self.at:nxt - self.at])
1662
1662
  cols = _segment_columns(self.cap, data, samples, len(self.names), self.cfg)
1663
- for col, f, ev in zip(cols, self.cur["files"], self.cur["events"]):
1664
- if isinstance(col, bytes):
1665
- f.write(col[:(samples + 7) // 8])
1663
+ for j, (col, f, ev) in enumerate(zip(cols, self.cur["files"], self.cur["events"])):
1664
+ if isinstance(col, bytes): # joined bit by bit: a segment need not end on a whole byte
1665
+ self.cur["carry"][j] = _write_bits(f, self.cur["carry"][j], col, samples)
1666
1666
  else:
1667
1667
  ev[0].append(col[0] + self.cur["samples"] // col[4])
1668
1668
  ev[1].append(col[1])
@@ -1693,7 +1693,7 @@ class _Spool:
1693
1693
  k = len(self.parts)
1694
1694
  files = [open(os.path.join(self.dir, f"p{k}-{j}.bits"), "wb") for j in range(len(self.names))]
1695
1695
  self.cur = {"tick0": tick0, "meta": _seg_meta(seg) if seg is not None else {}, "samples": 0, "files": files,
1696
- "events": [[[], [], [], None] for _ in self.names]}
1696
+ "events": [[[], [], [], None] for _ in self.names], "carry": [None] * len(self.names)}
1697
1697
  self._follows = False
1698
1698
 
1699
1699
  _last_samples, _last_end, _follows = 0, None, False
@@ -1705,6 +1705,7 @@ class _Spool:
1705
1705
  cur, n = self.cur, self.cur["samples"]
1706
1706
  chans = []
1707
1707
  for role, (name, ch, f, ev) in enumerate(zip(self.names, self.ids, cur["files"], cur["events"])):
1708
+ _flush_bits(f, cur["carry"][role])
1708
1709
  f.close()
1709
1710
  d = self.cfg.event_d.get(role) if self.blocks else None
1710
1711
  if d is not None:
@@ -1791,7 +1792,7 @@ def _stream_parts(cap, cfg, got, names, ids, req: Request) -> tuple[list, list]:
1791
1792
  chans = from_interleaved(data, names, cfg.width, cfg.positions, samples)
1792
1793
  else:
1793
1794
  chans = _from_blocks(cap, data, names, samples, cfg)
1794
- restart = acc is not None and (acc_samples % 8 or any(acc_samples % d for d in ds))
1795
+ restart = acc is not None and any(acc_samples % d for d in ds)
1795
1796
  if acc is None or restart: # a grid restart (format 1) is not a loss: the next part follows on
1796
1797
  if acc is not None:
1797
1798
  parts.append(_part(_built(acc, acc_samples, ids), acc_meta, tick0))
@@ -1865,10 +1866,41 @@ def _samples_at_once(run, names, ids, cfg, samples: int) -> list:
1865
1866
  for name, ch, bits in zip(names, ids, packed)]
1866
1867
 
1867
1868
 
1869
+ def _write_bits(f, carry, col: bytes, samples: int):
1870
+ """Append `samples` bits of `col` (sample i at bit i % 8 of byte i // 8) to file `f` after the `carry` bits not
1871
+ yet written (None: none): whole bytes go to the file, the bits left over (fewer than 8) come back as the carry."""
1872
+ if carry is None and samples % 8 == 0:
1873
+ f.write(col[:samples // 8])
1874
+ return None
1875
+ import numpy as np
1876
+ bits = np.unpackbits(np.frombuffer(col, np.uint8, (samples + 7) // 8), bitorder="little")[:samples]
1877
+ if carry is not None:
1878
+ bits = np.concatenate([carry, bits])
1879
+ whole = len(bits) // 8 * 8
1880
+ f.write(np.packbits(bits[:whole], bitorder="little").tobytes())
1881
+ return bits[whole:] if whole < len(bits) else None
1882
+
1883
+
1884
+ def _flush_bits(f, carry) -> None:
1885
+ """The last carry of _write_bits: its bits in one byte, the rest 0."""
1886
+ if carry is not None and len(carry):
1887
+ import numpy as np
1888
+ f.write(np.packbits(carry, bitorder="little").tobytes())
1889
+
1890
+
1891
+ def _join_bits(pieces) -> bytes:
1892
+ """Pieces (bits, n) joined bit by bit: n need not be a multiple of 8."""
1893
+ if all(n % 8 == 0 for _, n in pieces[:-1]):
1894
+ return b"".join(b[:(n + 7) // 8] for b, n in pieces)
1895
+ import numpy as np
1896
+ return np.packbits(np.concatenate([np.unpackbits(np.frombuffer(b, np.uint8, (n + 7) // 8), bitorder="little")[:n]
1897
+ for b, n in pieces]), bitorder="little").tobytes()
1898
+
1899
+
1868
1900
  class _Acc:
1869
- """One channel of a part being joined from its segments (bits: whole bytes, the part's samples so far a multiple
1870
- of 8; events: quanta offset by the samples so far, a multiple of D). A segment that follows on carries the level
1871
- before it as its start (§1.3), so its changes join the part's as they are."""
1901
+ """One channel of a part being joined from its segments (bits: joined bit by bit; events: quanta offset by the
1902
+ samples so far, a multiple of D). A segment that follows on carries the level before it as its start (§1.3), so
1903
+ its changes join the part's as they are."""
1872
1904
  def __init__(self, c):
1873
1905
  self.first, self.pieces = c, []
1874
1906
  self.start = getattr(c, "start_level", None)
@@ -1894,8 +1926,7 @@ def _built(acc: list, samples: int, ids) -> list:
1894
1926
  ct += c_
1895
1927
  out.append(changes(c.name, ks, lv, ct, -(-samples // c.step), c.step, 0, a.start, pin=ch))
1896
1928
  else:
1897
- out.append(Bits(c.name, b"".join(b for b, _ in a.pieces)[:(samples + 7) // 8], samples, 1, 0,
1898
- {"pin": ch}))
1929
+ out.append(Bits(c.name, _join_bits(a.pieces)[:(samples + 7) // 8], samples, 1, 0, {"pin": ch}))
1899
1930
  return out
1900
1931
 
1901
1932
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: oep-client-python
3
- Version: 0.0.47
3
+ Version: 0.0.48
4
4
  Summary: Open Embedded Probe (OEP) v1 host: serial / USB / TCP transports, the session rules, the standard interfaces, and a virtual bench
5
5
  Project-URL: Homepage, https://github.com/Open-Embedded-Probe/oep-client-python
6
6
  Project-URL: Repository, https://github.com/Open-Embedded-Probe/oep-client-python
@@ -1,6 +1,6 @@
1
- oep_client/__init__.py,sha256=SJtIdmZwlVWpTrZFXfUmNy4LSawSb5TuRDhPAnsFzcI,164
1
+ oep_client/__init__.py,sha256=6oSvhMIWGGzIF7vHRn0zjXVkFRa6spDeH9YGkw-8pZU,164
2
2
  oep_client/__main__.py,sha256=kbXBtEmFdhRXbVqXEbWCO-_5aDa-KyqMcW2HLZb5fjc,31510
3
- oep_client/acquire.py,sha256=js4hRYX2kG7JVfQuLgO6fveRF9t1nOjz7PozuRbkUU0,102529
3
+ oep_client/acquire.py,sha256=_-cH4JxePvym2REq7ElaBcNSuREt8DbsDwAkYM0xSw0,104034
4
4
  oep_client/arm.py,sha256=SszSLae8zErD4T-a1uQ6s6o3Lz7pe2SR8d3Qy-wi5rY,15633
5
5
  oep_client/capture.py,sha256=fvLqs4Ltot4pyOdQiCWIzf_v1j_iduCxU4rrX6oWfg8,76245
6
6
  oep_client/capture_blocks.py,sha256=dPrrZ8K-ISF80w6UumKVst5XNt0IjUk9lxbVvFnUEqg,20836
@@ -255,8 +255,8 @@ oep_client/conformance/wire_options_sample.py,sha256=dog-yvUcu693M8b51tA5TnhAnKr
255
255
  oep_client/conformance/writer_lease.py,sha256=5wDd4XIJWFPFlRY91wHlJs5U7ANp3xPpGgU2Eki7e8g,7331
256
256
  oep_client/conformance/writer_lease_model.py,sha256=FxhDqqzdFOa_SSHSvjdQFh49Wn3YuZ98ISSlRRxrq9E,1721
257
257
  oep_client/conformance/writer_lease_sample.py,sha256=oowRwYUNAE4f6rEE2HmYlSS9dDWE0TGegkcsqVH8Nak,455
258
- oep_client_python-0.0.47.dist-info/METADATA,sha256=e38LWsb7vSB_jpzlmyLWSQeBrHvSb9dREoKRv8V0nKQ,55269
259
- oep_client_python-0.0.47.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
260
- oep_client_python-0.0.47.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
261
- oep_client_python-0.0.47.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
262
- oep_client_python-0.0.47.dist-info/RECORD,,
258
+ oep_client_python-0.0.48.dist-info/METADATA,sha256=dmN1zicxaqz2IlW815qXtU6KXYYqPebwgAs00ikR0v0,55269
259
+ oep_client_python-0.0.48.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
260
+ oep_client_python-0.0.48.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
261
+ oep_client_python-0.0.48.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
262
+ oep_client_python-0.0.48.dist-info/RECORD,,