oep-client-python 0.0.43__py3-none-any.whl → 0.0.44__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.43"
5
+ __version__ = "0.0.44"
@@ -144,7 +144,7 @@ def checker_sources_sha256():
144
144
  for name in CHECKER_SOURCES}
145
145
 
146
146
 
147
- REVIEWED_CORE_SHA256 = '699f7eb6333b6eb6678ddcf27074c03544f0f0a6ee0ef6ccdf02edd3757f962e' # oep-spec 364827b docs/oep-core.ja.md
147
+ REVIEWED_CORE_SHA256 = '699f7eb6333b6eb6678ddcf27074c03544f0f0a6ee0ef6ccdf02edd3757f962e' # oep-spec docs/oep-core.ja.md
148
148
 
149
149
 
150
150
  def require_reviewed_contract(registry, spec=None):
@@ -8,7 +8,7 @@ import struct
8
8
  from . import ops, require, tlvs
9
9
  from .. import conformance as _helpers
10
10
 
11
- REVIEWED_CORE_SHA256 = '699f7eb6333b6eb6678ddcf27074c03544f0f0a6ee0ef6ccdf02edd3757f962e' # oep-spec 364827b docs/oep-core.ja.md
11
+ REVIEWED_CORE_SHA256 = '699f7eb6333b6eb6678ddcf27074c03544f0f0a6ee0ef6ccdf02edd3757f962e' # oep-spec docs/oep-core.ja.md
12
12
 
13
13
 
14
14
  class CoreSmokeChecks:
@@ -6,7 +6,7 @@ import struct
6
6
 
7
7
  from . import ops, require, tlvs
8
8
 
9
- REVIEWED_INTERFACES = { # oep-spec 364827b interfaces/
9
+ REVIEWED_INTERFACES = { # oep-spec interfaces/
10
10
  'oep-if-fixture.ja.md': '780beb7a3f9adb51fccf3441930e4c04d2bb64ef738e302195cf5a4e7c2a60a6',
11
11
  'oep-if-plan.ja.md': 'da8bd60af53499573c07bc33dbd8c4df93eb61a93b91dc57907f26620ae36bbf',
12
12
  'oep-if-debug.ja.md': '58843357aae5afd31082b068c76c754cbd047446fe4b0aa77b5c22cbedf1f3f8',
oep_client/dump.py CHANGED
@@ -27,7 +27,7 @@ class Capabilities:
27
27
  max_frame: int
28
28
  offers: list[Offer] = field(default_factory=list)
29
29
  requests: dict[str, int] = field(default_factory=dict)
30
- missing: list[str] = field(default_factory=list) # what core §1.2 requires and the probe did not give (C-10)
30
+ missing: list[str] = field(default_factory=list) # what core §1.2 requires and the probe did not give
31
31
 
32
32
 
33
33
  _REQUIRED_CORE_TAGS = {reg.CORE.tlv["describe"][k]: k for k in ("unit_id", "transport", "max_op_ms")}
@@ -44,7 +44,7 @@ CORE_REQUIRED_OPS = ("confirm", "list", "describe", "clock", "open", "end", "kee
44
44
 
45
45
 
46
46
  def required_missing(confirm_payload: bytes, core_describe: list[tuple[int, bytes]]) -> list[str]:
47
- """What every probe must give, as far as a lock-free look on one transport shows it (core §1.2, C-10; oep-spec
47
+ """What every probe must give, as far as a lock-free look on one transport shows it (core §1.2; oep-spec
48
48
  docs/conformance.md section 1): confirm's answer carries TLV transport, naming an entry of fn 0's describe or 0xFF
49
49
  (§7.1); fn 0's describe carries unit_id, transport, max_op_ms (§1.2, §7.5) and ops in core §7.4's form with every
50
50
  required op set (core §11; a probe whose fn 0 ops break the form is not used). -> what is missing (empty: nothing seen missing). The bounds of confirm's values and of
@@ -95,7 +95,7 @@ def _describe_all(call, fn: int, caps: Capabilities) -> bytes:
95
95
  def collect(call, prefix: str = "", exact: bool = False, confirm: tuple[int, int] = (0, 1)) -> Capabilities:
96
96
  """confirm, then fn 0's describe (the core: no name, never listed, core §7.2) and every listed interface's (the
97
97
  ones under `prefix` on label boundaries, `exact`: that name only - list itself returns every one, core §7.2). `confirm`: the revision range the confirm asks for - a host that confirmed already passes the
98
- revision in use (core §7.1, C-15: every later confirm on a transport asks for it alone). fn 0 is shown first, as
98
+ revision in use (core §7.1: every later confirm on a transport asks for it alone). fn 0 is shown first, as
99
99
  an Offer with fn 0 and no name."""
100
100
  p = call(CORE_FN, OP_CONFIRM, m.CONFIRM_REQUEST + bytes(confirm)) # v0 and v1 both answer (0..1)
101
101
  magic, revision = struct.unpack_from("<4sB", p)
oep_client/endpoint.py CHANGED
@@ -629,7 +629,7 @@ class Endpoint(FixtureDrive):
629
629
  """`now_ms`: the clock the timers run on (leases, retries, port_speed), since this boot. `now_ns`: the same clock
630
630
  in ns when it has that resolution (virtual_bench_serve: time.monotonic_ns); without it the probe's clock (core §2.6a)
631
631
  is `now_ms` in ns. confirm's limits are checked against core §7.1 (max_frame 64 or more, window max_frame or
632
- more, max_inflight 1 or more, C-20) and the declared max_op_ms against core §7.5 (1 to max_op_ms_max, C-47):
632
+ more, max_inflight 1 or more) and the declared max_op_ms against core §7.5 (1 to max_op_ms_max):
633
633
  a probe outside them is not built."""
634
634
  if probe.max_frame < reg.MIN_MAX_FRAME or window < probe.max_frame or max_inflight < 1:
635
635
  raise ValueError(f"confirm's limits out of core §7.1's bounds: max_frame {probe.max_frame}, window {window}, "
@@ -639,7 +639,7 @@ class Endpoint(FixtureDrive):
639
639
  self.now = now_ms
640
640
  self._clock_ns = now_ns
641
641
  self._origin_ns = 0 # the probe clock's 0: this boot's start (core §2.6a)
642
- self._last_ns = 0 # the clock never goes back while the boot_id stays (C-31)
642
+ self._last_ns = 0 # the clock never goes back while the boot_id stays
643
643
  self.current_core = None
644
644
  self.boot_id = boot_id
645
645
  self.lease_default_ms = lease_default_ms
@@ -1260,7 +1260,7 @@ class Endpoint(FixtureDrive):
1260
1260
 
1261
1261
  def now_ns(self) -> int:
1262
1262
  """The probe's one clock (core §2.6a): ns since boot, at the resolution of `now_ns` when the endpoint has one
1263
- (else ms). It never decreases while the boot_id is the same (C-31), and starts again at a reboot."""
1263
+ (else ms). It never decreases while the boot_id is the same, and starts again at a reboot."""
1264
1264
  self._last_ns = max(self._last_ns, self._raw_ns() - self._origin_ns)
1265
1265
  return self._last_ns
1266
1266
 
@@ -1306,7 +1306,7 @@ class Endpoint(FixtureDrive):
1306
1306
  self.current_core = Core(self)
1307
1307
  return self.current_core.handle(data, transport)
1308
1308
  if not data or data[0] != m.ROLE_REQUEST or len(data) < REQUEST_HEADER:
1309
- self.discarded += 1 # not a request, or shorter than its header (C-36)
1309
+ self.discarded += 1 # not a request, or shorter than its header
1310
1310
  return None
1311
1311
  if self.restarting:
1312
1312
  self.unanswered += 1 # the restart's answer is out: nothing more (oep-if-restart §2)
@@ -1602,7 +1602,7 @@ class Endpoint(FixtureDrive):
1602
1602
  """The probe restarts: lock, last id, the resend table, connections, streams, captures, subscriptions, the
1603
1603
  revision in use, the port speed, the unsaved config and the plan are gone; the saved config comes back, and the
1604
1604
  clock starts again from 0 (ns since boot, core §2.6a). `boot_id` None
1605
- draws a new one, as from a hardware random source (core §6.5, C-19); passing the current one plays a probe
1605
+ draws a new one, as from a hardware random source (core §6.5); passing the current one plays a probe
1606
1606
  whose only source repeated it - its hosts learn only that their session is gone (no_session, core §6.2)."""
1607
1607
  if boot_id is None:
1608
1608
  boot_id = self.boot_id
@@ -3134,7 +3134,7 @@ class Endpoint(FixtureDrive):
3134
3134
  if address > 0x7F:
3135
3135
  raise Reject(m.MALFORMED) # a 7-bit address (excluded for every revision)
3136
3136
  if address <= 0x07 or address >= 0x78:
3137
- raise unsupported_fixed() # reserved by I2C: general call, 10-bit, ... (△5)
3137
+ raise unsupported_fixed() # reserved by I2C: general call, 10-bit, ...
3138
3138
  if not planned:
3139
3139
  raise unavailable("wrong_state") # before the plan (cause 6)
3140
3140
  if fn in self.target_fail_configure: # taken, not brought up: state 0, the queue, slots
oep_client/frames.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """Length-prefixed frames on a reliable byte stream (USB vendor bulk, HID, TCP): u16 length, then the message (oep-spec
2
2
  oep-core §3). No CRC: a length that cannot be right, or a frame that stops half way, means the boundaries are lost -
3
- FramingLost, and the link resyncs. Not on TCP (transports §5, C-07): a pause inside a frame is normal there and the
3
+ FramingLost, and the link resyncs. Not on TCP (transports §5): a pause inside a frame is normal there and the
4
4
  frame is read on; a stream that keeps its boundaries says so with `keeps_boundaries = True`."""
5
5
 
6
6
  from __future__ import annotations
oep_client/host.py CHANGED
@@ -86,7 +86,7 @@ RESTART_WAIT_S = 10.0 # restart_probe: the wait for a p
86
86
 
87
87
 
88
88
  def check_confirm(max_frame: int, window: int, max_inflight: int) -> str:
89
- """core §7.1 (C-20): max_frame >= min_max_frame (64), window >= max_frame, max_inflight >= 1. -> "" or why not."""
89
+ """core §7.1: max_frame >= min_max_frame (64), window >= max_frame, max_inflight >= 1. -> "" or why not."""
90
90
  if max_frame < reg.MIN_MAX_FRAME or window < max_frame or max_inflight < 1:
91
91
  return (f"confirm answered max_frame {max_frame}, window {window}, max_inflight {max_inflight}: outside core "
92
92
  f"§7.1 (max_frame >= {reg.MIN_MAX_FRAME}, window >= max_frame, max_inflight >= 1); the transport is not used")
@@ -163,7 +163,7 @@ class Unsupported(Rejected):
163
163
 
164
164
  @property
165
165
  def supported(self) -> tuple[int, int] | None:
166
- """confirm's refusal (core §7.1, C-15): (min, max) of the protocol revisions the probe handles (TLV 0x01
166
+ """confirm's refusal (core §7.1): (min, max) of the protocol revisions the probe handles (TLV 0x01
167
167
  supported after tag 0x00); None for any other refusal."""
168
168
  if self.tag is not None:
169
169
  return None
@@ -294,7 +294,7 @@ class Host:
294
294
  before_request: Callable[[], None] | None = None
295
295
  # Called with confirm's limits after every confirm answer (the link's max_frame for the transfer time, core §4.4)
296
296
  on_limits: Callable[[dict], None] | None = None
297
- unusable: str = "" # why this probe is not used (C-20, C-47): set, nothing more is sent
297
+ unusable: str = "" # why this probe is not used: set, nothing more is sent
298
298
  restart_reopened: bool = False # the last restart_probe came back only on its reopen_s (the user's reopen)
299
299
  # The session id kept per probe for the next run (kept_session.KeptSession; link.open_host sets one): None = not kept
300
300
  kept: object | None = None
@@ -438,7 +438,7 @@ class Host:
438
438
  self._boot_id = boot_id
439
439
 
440
440
  def not_usable(self, why: str) -> None:
441
- """Stop using this probe (C-20, C-47): every later request raises NotUsable with `why`."""
441
+ """Stop using this probe: every later request raises NotUsable with `why`."""
442
442
  self.unusable = why
443
443
  raise NotUsable(why)
444
444
 
@@ -484,7 +484,7 @@ class Host:
484
484
 
485
485
  # ---- confirm (§5, §2) -----------------------------------------------------------------------
486
486
  def confirm_range(self) -> tuple[int, int]:
487
- """The revisions a confirm asks for (core §7.1, C-15): the range this client handles before the first confirm,
487
+ """The revisions a confirm asks for (core §7.1): the range this client handles before the first confirm,
488
488
  then min_rev = max_rev = the revision in use, in every later confirm (a resync, probing again) - so a later
489
489
  probe never switches the revision in the middle of a session."""
490
490
  if self.revision:
@@ -499,7 +499,7 @@ class Host:
499
499
  """Ask for a revision in [min_rev, max_rev] (default `confirm_range()`). -> {"revision", "max_frame",
500
500
  "window", "max_inflight", "boot_id", "transport", "tail"}. The boot_id is the probe's for this boot (core §6.5,
501
501
  §7.1): a host without the lock learns of a restart from it. transport: the index (fn 0's describe) of the
502
- transport this confirm came on (core §7.1, C-05; 0xFF from a relaying broker; None when the probe sent none).
502
+ transport this confirm came on (core §7.1; 0xFF from a relaying broker; None when the probe sent none).
503
503
  The answer's fixed part is the same in every revision (core §7.1): a revision outside the range asked is a
504
504
  ProtocolError and nothing of the answer is used. A probe that refuses the ranged confirm as malformed is not v1
505
505
  (revision 0 is recorded and the rejection raised). No revision in the range: rejected unsupported (Unsupported:
@@ -527,7 +527,7 @@ class Host:
527
527
  tail = rd.tail()
528
528
  why = check_confirm(max_frame, window, inflight)
529
529
  if why:
530
- self.not_usable(why) # sends nothing more and reports the values (C-20)
530
+ self.not_usable(why) # sends nothing more and reports the values
531
531
  self.boot_id_seen(boot_id)
532
532
  self.revision = revision
533
533
  where = tail.get(CONFIRM_TRANSPORT)
oep_client/link.py CHANGED
@@ -25,8 +25,8 @@ host as a reboot; read the state before repeating a state-changing request.
25
25
  Frames the probe sends by itself are routed: data pushes and events are kept (`pushes`, `events`) for the clients
26
26
  of the interfaces that sent them (fn 0 sends none, core §10.2). A result shorter than 5
27
27
  bytes, or an event or data frame shorter than its header, is a broken frame; a request role from the probe is dropped
28
- (core §2.4, C-36). The transfer time of the wait counts min_max_frame (64) until a confirm answer came on the
29
- transport, then the latest one's max_frame (core §4.4, N-1).
28
+ (core §2.4). The transfer time of the wait counts min_max_frame (64) until a confirm answer came on the
29
+ transport, then the latest one's max_frame (core §4.4).
30
30
 
31
31
  A serial port is opened exclusively (host guide §6): pyserial's `exclusive=True` (flock, advisory) and, on Linux and
32
32
  macOS, TIOCEXCL, so a second open fails at once (EBUSY) instead of sharing the answers. The port opens with pyserial's
@@ -93,7 +93,7 @@ from . import cobs, host as _host, message as m, registry as reg
93
93
  from .frames import FramingLost, LengthFrames
94
94
 
95
95
  # the link's own confirms (resync §5.1, confirm_raw) ask for the revisions this client handles before the first
96
- # confirm, and for the revision in use after it (core §7.1, C-15) - never 0..0xFF
96
+ # confirm, and for the revision in use after it (core §7.1) - never 0..0xFF
97
97
  _OWN_CONFIRM = m.CONFIRM_REQUEST + bytes([_host.MIN_REVISION, _host.MAX_REVISION])
98
98
 
99
99
  RESYNC_QUIET_S = 0.05 # transports §5: read and discard until the input is this quiet
@@ -121,7 +121,7 @@ def _session_of(message: bytes) -> int:
121
121
 
122
122
 
123
123
  class TransportFailed(TimeoutError):
124
- """core §5.2 (C-38): a request's resend got no answer either. Its outcome is unknown and the requests outstanding
124
+ """core §5.2: a request's resend got no answer either. Its outcome is unknown and the requests outstanding
125
125
  on the transport failed with it; the link sends nothing else there until it has recovered with the §5.1 confirm
126
126
  (done before the next request; ConnectionError when no confirm is answered). After that, read the state before
127
127
  repeating a state-changing request."""
@@ -144,7 +144,7 @@ class PortBusy(OSError):
144
144
  """Another program holds the serial port (it was opened exclusively): only one host at a time on a serial port."""
145
145
 
146
146
 
147
- BASE_BAUD = reg.TIMING["uart_bridge_boot_baud"] # every UART bridge boots at 115200 8N1 (transports §4, C-09)
147
+ BASE_BAUD = reg.TIMING["uart_bridge_boot_baud"] # every UART bridge boots at 115200 8N1 (transports §4)
148
148
  IDLE_MS = reg.TIMING["port_speed_idle_ms"] # a committed rate goes back after this with no good frame (oep-if-link §3)
149
149
  KEEPALIVE_S = 1.0 # raised: a keepalive once the link has been quiet this long (under half of port_speed_idle_ms, §17)
150
150
  OPEN_RETRY_S = (IDLE_MS + reg.TIMING["host_wait_add_ms"]) / 1000 # the confirms at the boot speed (transports §4)
@@ -171,8 +171,7 @@ else:
171
171
 
172
172
  def open_serial(port: str, baud: int = BASE_BAUD):
173
173
  """The port opened exclusively (flock and TIOCEXCL): a second open by anyone fails with PortBusy. 8 data bits, no
174
- parity, 1 stop bit, no flow control, DTR and RTS asserted from the open on and while it stays open (transports §4,
175
- C-09: a UART bridge may wire them to the probe's reset; what a probe does with DTR deasserted is not defined). The
174
+ parity, 1 stop bit, no flow control, DTR and RTS asserted from the open on and while it stays open (transports §4: a UART bridge may wire them to the probe's reset; what a probe does with DTR deasserted is not defined). The
176
175
  driver's low-latency mode on where it has one (the FTDI latency timer 16 -> 1 ms; a pty or a driver without it:
177
176
  ignored)."""
178
177
  try:
@@ -352,15 +351,15 @@ class SerialLink:
352
351
  self.keepalive_frame = None # raised: a keepalive request in the session, once bound (attach_host)
353
352
  self.last_tx = time.monotonic() # when the link last wrote (raised: quiet for KEEPALIVE_S = keepalive)
354
353
  self.last_write: float | None = None # when this host last wrote to the port (None: never; transports §5)
355
- self.max_frame = reg.MIN_MAX_FRAME # min_max_frame until a confirm answer, then its max_frame (§4.4, N-1)
354
+ self.max_frame = reg.MIN_MAX_FRAME # min_max_frame until a confirm answer, then its max_frame (§4.4)
356
355
  self.on_boot_id = lambda boot_id: None # the boot_id of the link's own confirms (resync, recovery)
357
356
  self.on_reopen = lambda: None # the transport closed and opened again (`_reopen`)
358
- self.failed_transport = "" # why: a resend went unanswered (core §5.2, C-38); recover first
357
+ self.failed_transport = "" # why: a resend went unanswered (core §5.2); recover first
359
358
  self.recoveries = 0 # failed-transport recoveries made (a confirm answered)
360
359
  self.wait_add_s = WAIT_ADD_S # the floor's host_wait_add_ms (a test of an in-process virtual bench shortens it)
361
360
  self._req_bound_s: float | None = None # the processing bound of the requests whose answers are awaited now
362
361
  self.tx_len = 0 # the longest frame on the wire of the last write
363
- self.confirm_body = lambda: _OWN_CONFIRM # the link's own confirm: the revision in use once bound (C-15)
362
+ self.confirm_body = lambda: _OWN_CONFIRM # the link's own confirm: the revision in use once bound
364
363
  self.held = lambda: False # a session holds the port (its raw transfer stopped): broken = resend
365
364
  self._corr_n = 0x8000
366
365
  if self.framing == "length":
@@ -399,7 +398,7 @@ class SerialLink:
399
398
  return (self.tx_len + self.max_frame * (1 + NOTIFY_PENDING)) * 10 / self.baud
400
399
 
401
400
  def wait_floor_s(self, bound_s: float | None = None) -> float:
402
- """The least a request's answer is waited for (core §4.4, C-06): the request's processing bound (Host.expecting:
401
+ """The least a request's answer is waited for (core §4.4): the request's processing bound (Host.expecting:
403
402
  Host.op_bound_ms - max_op_ms, fn 0's quick ops' shorter one - or longer when its arguments say so; `bound_s`:
404
403
  the bound of the requests on the wire, `_bound_s`) + host_wait_add_ms + the transfer time; counted
405
404
  from the write, or from the answer before it while several are outstanding (each reply's wait starts when it is
@@ -472,7 +471,7 @@ class SerialLink:
472
471
  dropped (core §2.4). True if `frame` was one of them. Only a result (role 0x02) carries a correlation id;
473
472
  matching anything else by its bytes 1-2 would take a push for a reply whenever its fn happened to equal the id.
474
473
  A result shorter than 5 bytes, or an event / data frame shorter than its header,
475
- is a broken frame (core §2.4, C-36): `_broken`."""
474
+ is a broken frame (core §2.4): `_broken`."""
476
475
  if frame and frame[0] == m.ROLE_RESULT:
477
476
  return len(frame) < RESULT_HEADER and self._broken(frame, "a result shorter than its header")
478
477
  if frame and frame[0] == m.ROLE_DATA:
@@ -488,7 +487,7 @@ class SerialLink:
488
487
  return True
489
488
 
490
489
  def _broken(self, frame: bytes, why: str) -> bool:
491
- """A frame that decoded but cannot be read (C-36): on a length-framed link the boundaries are in doubt (the
490
+ """A frame that decoded but cannot be read: on a length-framed link the boundaries are in doubt (the
492
491
  §5.1 resync follows); on a serial port it is a broken frame like a bad CRC - most likely the awaited answer,
493
492
  resent at once (core §5.1; transports §4: the port carries OEP frames only)."""
494
493
  if self.framing == "length":
@@ -620,7 +619,7 @@ class SerialLink:
620
619
  self.on_reopen() # the subscriptions stayed on the closed one (core §10.3)
621
620
 
622
621
  def _fail_transport(self, e: Exception) -> None:
623
- """core §5.2 (C-38): the resend went unanswered too - the transport failed. Its outcome is unknown, so are the
622
+ """core §5.2: the resend went unanswered too - the transport failed. Its outcome is unknown, so are the
624
623
  requests outstanding with it; nothing else goes out before `recover_transport` (the next request runs it)."""
625
624
  if getattr(self, "_probing", False):
626
625
  raise e # probing: the probe() caller closes the link (transports §3)
@@ -646,7 +645,7 @@ class SerialLink:
646
645
  self.failed_transport = f"a request got no answer and was not sent again ({type(e).__name__}: {e})"
647
646
 
648
647
  def recover_transport(self, tries: int = 3) -> None:
649
- """core §5.2 / §5.1 (C-38), on every kind of frame, COBS included: read and discard until the input is quiet,
648
+ """core §5.2 / §5.1, on every kind of frame, COBS included: read and discard until the input is quiet,
650
649
  wait host_resync_wait_ms since this host's last write, then a confirm until the answer with its own corr comes
651
650
  (other frames read past). A changed boot_id in it goes to the host (a reboot, core §6.5). ConnectionError when
652
651
  no confirm is answered in `tries`: the transport stays failed (close and open it again)."""
@@ -713,7 +712,7 @@ class SerialLink:
713
712
 
714
713
  def send(self, message: bytes) -> bytes:
715
714
  if self.failed_transport:
716
- self.recover_transport() # nothing else goes out before (core §5.2, C-38)
715
+ self.recover_transport() # nothing else goes out before (core §5.2)
717
716
  self._keep_raised()
718
717
  try:
719
718
  reply = self._send(message)
@@ -972,7 +971,7 @@ class SerialLink:
972
971
  wait = min(wait, max(RAISED_WAIT_MIN_S, lease / 4))
973
972
  if self._own and self._req_bound_s is None:
974
973
  return wait # a read of the link's own (pump, a repeated confirm)
975
- return max(wait, self.wait_floor_s(self._req_bound_s)) # never under core §4.4's floor (C-06)
974
+ return max(wait, self.wait_floor_s(self._req_bound_s)) # never under core §4.4's floor
976
975
 
977
976
  def _strike(self, e: Exception) -> None:
978
977
  """A request's answer did not come (`e`): a lost frame (host guide §17.3.2: counted at the boot speed for the
@@ -1211,10 +1210,10 @@ class SerialLink:
1211
1210
  self.lease_s = lambda: hst.lease_ms / 1000 if hst.session is not None and hst.lease_ms else None
1212
1211
  hst.before_request = self._keep_raised # the keepalive before the request's corr is taken (core §4.1)
1213
1212
  self.expected_s = lambda: hst.expect_ms / 1000
1214
- self.confirm_body = hst.confirm_body # the revision in use after the first confirm (core §7.1, C-15)
1215
- self.on_boot_id = hst.boot_id_seen # the link's own confirms (resync, recovery): a reboot shows (C-38)
1213
+ self.confirm_body = hst.confirm_body # the revision in use after the first confirm (core §7.1)
1214
+ self.on_boot_id = hst.boot_id_seen # the link's own confirms (resync, recovery): a reboot shows
1216
1215
  self.on_reopen = hst.transport_reopened # a subscribe again moves the pushes to the new one (core §10.3)
1217
- hst.on_limits = self._limits # every confirm answer: max_frame for the transfer time (N-1)
1216
+ hst.on_limits = self._limits # every confirm answer: max_frame for the transfer time
1218
1217
  hst.link = self
1219
1218
 
1220
1219
  def reopen_after_restart(self, hst, wait_s: float) -> dict:
@@ -1262,7 +1261,7 @@ class SerialLink:
1262
1261
 
1263
1262
  def _limits(self, limits: dict) -> None:
1264
1263
  """confirm's answer on this transport: until the first one the transfer time counts min_max_frame (64), then
1265
- the max_frame of the latest (core §4.4, N-1); a length-framed reader bounds frames by it."""
1264
+ the max_frame of the latest (core §4.4); a length-framed reader bounds frames by it."""
1266
1265
  if limits.get("max_frame"):
1267
1266
  self.max_frame = limits["max_frame"]
1268
1267
  if self.framing == "length":
@@ -2052,7 +2051,7 @@ class SpeedReport:
2052
2051
 
2053
2052
  def _speed_port(hst) -> tuple[int | None, int | None, str]:
2054
2053
  """(the probe's oep.probe.link fn, the port this host's requests come in on - the transport TLV of confirm's answer, core
2055
- §7.1, C-05) when the probe offers oep.probe.link with port_speed set in its ops (oep-if-link §1) and that transport is a
2054
+ §7.1) when the probe offers oep.probe.link with port_speed set in its ops (oep-if-link §1) and that transport is a
2056
2055
  UART bridge; else Nones and why not."""
2057
2056
  from . import core
2058
2057
  try:
@@ -2365,7 +2364,7 @@ def raise_speed(hst, candidates=DEFAULT_CANDIDATES, *, flows=None, verify: bool
2365
2364
  unit = _unit_id(hst)
2366
2365
  if rec.names_a_unit(unit):
2367
2366
  lk.record, lk.record_key = rec, (lk.port_path or "<stream>", unit)
2368
- else: # an x- unit_id names no unit: nothing kept (C-24)
2367
+ else: # an x- unit_id names no unit: nothing kept
2369
2368
  rec = None
2370
2369
  report.why = f"unit_id {unit} names no unit (core §7.5): no speed record"
2371
2370
  run = _Run(flows, verify, frames, wait, port, rec, max(0, int(probation_bytes)), max(0.0, probation_s),
oep_client/pins.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """oep pins: find where a target is wired to a probe whose pins the host chooses - its debug pins and its reset line -
2
- from what worked and what misled on 2026-10-02 (ESP32-P4 probe, CH32V003 target; oep-spec host guide §19, finding pins and docs/target-scan-notes.ja.md).
2
+ from what worked and what misled (ESP32-P4 probe, CH32V003 target).
3
3
 
4
4
  Steps, each optional and each saying what it did:
5
5
 
oep_client/riscv.py CHANGED
@@ -899,7 +899,7 @@ class RiscvDm(Interface, BlockLength):
899
899
 
900
900
  def step(self) -> tuple[bool, int, int]:
901
901
  """One instruction (dcsr.step, one resume, privilege kept). -> (moved, dpc before, dpc after). A hart that did
902
- not come back, and any status but ok, raises StepError (oep-if-debug §4.2, P2-○4) without moved or the dpcs
902
+ not come back, and any status but ok, raises StepError (oep-if-debug §4.2) without moved or the dpcs
903
903
  (0 unless status ok, not read): `step_left` False - the probe halted it with haltreq and restored it (read its
904
904
  dpc with dmi); True (answer TLV step_left) - it could not halt it again: the hart runs and dcsr.step may still
905
905
  be set, so the host halts it and clears dcsr.step. DATA0 is written back first (`restore_data`)."""
@@ -19,7 +19,7 @@ guide §17.4), `passed` true / false / null (the same, for a reader of the older
19
19
  rec.note("/dev/ttyUSB0", "fafe00000003", 921600, passed=True, phase="verify")
20
20
 
21
21
  `link.raise_speed(..., record=True)` (the `oep speed` CLI's default) reads and writes it; the library default is off.
22
- A unit_id starting with `x-` names no unit (core §7.5, C-24: a probe with neither a unique number nor storage): nothing
22
+ A unit_id starting with `x-` names no unit (core §7.5: a probe with neither a unique number nor storage): nothing
23
23
  is kept or found under it, so another unit on the same port inherits nothing.
24
24
  """
25
25
 
oep_client/targets.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """What the host knows about target families, in one table: which wire, the reset vector, how to read whether the reset
2
2
  line (NRST) exists, the line settings to attach with. The probe knows none of it (oep-if-debug: the host knows the
3
- target). `oep pins` and anything else that meets a target by its target_id read it from here, and oep-spec
4
- docs/target-scan-notes.ja.md records where each fact comes from.
3
+ target). `oep pins` and anything else that meets a target by its target_id read it from here; each family's notes
4
+ say what was measured.
5
5
 
6
6
  A family is matched by the target_id an attach reports (scheme 1 = dmi_7f: the u32 at DMI address 0x7F, which on these
7
7
  parts equals the chip's ESIG ID):
@@ -99,7 +99,7 @@ def gpio_clock_bit(port: str) -> int:
99
99
  return 1 << (2 + ord(port) - ord("A"))
100
100
 
101
101
 
102
- # The families met on the OEP benches (oep-spec docs/target-scan-notes.ja.md §2). ids: the top 12 bits of the ESIG ID
102
+ # The families met on the OEP benches. ids: the top 12 bits of the ESIG ID
103
103
  # name the series (CH32V003 0x003..., CH32X035 0x035...).
104
104
  FAMILIES: tuple[Family, ...] = (
105
105
  Family("ch32v00x", "swio", ids=tuple((0xFFF00000, s << 20) for s in (0x002, 0x003, 0x004, 0x005, 0x006, 0x007)),
@@ -114,8 +114,9 @@ FAMILIES: tuple[Family, ...] = (
114
114
  Family("ch32l103", "rvswd", max_speed=1_000_000, idle_clock="low", gpio_ports="ABCD", gpio_pads=16,
115
115
  debug_pads=("PA13", "PA14"),
116
116
  notes="SWCLK resting high resets the debug link; over 1 MHz fails right after a reset; target_id not recorded"),
117
- Family("ch32v203", "rvswd", idle_clock="low", gpio_ports="ABCD", gpio_pads=16, debug_pads=("PA13", "PA14"),
118
- notes="no OEP bench yet; target_id not recorded"),
117
+ Family("ch32v20x", "rvswd", ids=((0xFFF00000, 0x20800000),), idle_clock="low", gpio_ports="ABCD", gpio_pads=16,
118
+ debug_pads=("PA13", "PA14"),
119
+ notes="the CH32V208 recorded (target_id 0x2080051c, CH32V208WBU6); the CH32V203's not yet"),
119
120
  )
120
121
 
121
122
 
@@ -82,7 +82,7 @@ class VirtualProbe:
82
82
  # an interface with plan roles: the probe lists oep.probe.plan too (oep-if-plan), at the next free fn
83
83
  offered.append(_plan(max(o.fn for o in offered) + 1))
84
84
  if core_contract and any(o.fn != 0 for o in offered):
85
- raise ValueError('core-v1 profile cannot expose legacy interfaces')
85
+ raise ValueError('core-v1 profile exposes fn 0 only')
86
86
  self.offered = sorted((o if not fill_ops else self._filled(o) for o in offered), key=lambda o: o.fn)
87
87
  self.requests = 0
88
88
  for o in self.offered:
@@ -196,7 +196,7 @@ _CAPD = reg.FIXTURE_LOGIC.tlv["describe"]
196
196
  _ANAD = reg.FIXTURE_ANALOG.tlv["describe"]
197
197
  _GRPD = reg.FIXTURE_CAPTURE_GROUP.tlv["describe"]
198
198
  CORE_CHIP = reg.CORE.tlv["describe"]["chip"]
199
- UNIT_ID = re.compile(r"[a-z0-9-]{1,32}") # an x- unit_id is not unique (core §7.5, C-24)
199
+ UNIT_ID = re.compile(r"[a-z0-9-]{1,32}") # an x- unit_id is not unique (core §7.5)
200
200
 
201
201
 
202
202
  def _analog_decl(frontends: list[tuple[int, int, int]], max_samples: int, min_hz: int, max_hz: int) -> tuple[bytes, ...]:
@@ -269,7 +269,7 @@ def block_max_length(max_frame: int) -> int:
269
269
 
270
270
 
271
271
  def _transports(kinds: list[tuple[int, int]]) -> tuple[bytes, ...]:
272
- """(kind, interface) per transport, index = position (core §7.5, C-41): a USB CDC names its communication
272
+ """(kind, interface) per transport, index = position (core §7.5): a USB CDC names its communication
273
273
  interface (the first of the function), built-in USB serial the number the hardware presents or 0xFF, vendor bulk
274
274
  and HID their interface; a UART bridge and TCP 0xFF."""
275
275
  for k, itf in kinds:
@@ -712,7 +712,7 @@ def minimal_ops(probe: VirtualProbe) -> VirtualProbe:
712
712
 
713
713
  def with_unit_id(probe: VirtualProbe, unit_id: str) -> VirtualProbe:
714
714
  """The profile with another unit_id in fn 0's describe - an `x-` one is a probe with neither a unique number nor
715
- storage (core §7.5, C-24: hosts key nothing kept across sessions by it). VIRTUAL BENCH ONLY."""
715
+ storage (core §7.5: hosts key nothing kept across sessions by it). VIRTUAL BENCH ONLY."""
716
716
  return _again(probe, [_with(o, (catalog.text(CORE_UNIT_ID, unit_id) if t[0] == CORE_UNIT_ID else t for t in o.tlvs))
717
717
  if o.fn == CORE_FN else o for o in probe.offered])
718
718
 
@@ -171,7 +171,7 @@ def build(a: argparse.Namespace) -> endpoint.Endpoint:
171
171
  if getattr(a, "minimal_ops", False):
172
172
  probe = virtual_bench.minimal_ops(probe) # console / fixture UART at their smallest
173
173
  start = time.monotonic_ns()
174
- # the clock in ns since this start (core §2.6a), and a boot_id from the OS's random source (core §6.5, C-19)
174
+ # the clock in ns since this start (core §2.6a), and a boot_id from the OS's random source (core §6.5)
175
175
  ep = endpoint.Endpoint(probe, lambda: (time.monotonic_ns() - start) // 1_000_000, boot_id=secrets.randbits(32),
176
176
  now_ns=lambda: time.monotonic_ns() - start)
177
177
  wire = min(ep.pairs) if ep.pairs else None
@@ -451,7 +451,7 @@ def serve_tcp(a, ep, console, commands: Commands) -> None:
451
451
  srv.listen(8)
452
452
  port = srv.getsockname()[1]
453
453
  if a.framing == "length":
454
- # the listening socket is a TCP transport of its own (transports §1, C-05): listed in describe, named by confirm
454
+ # the listening socket is a TCP transport of its own (transports §1): listed in describe, named by confirm
455
455
  ep.tcp_index = ep.add_transport(virtual_bench.TRANSPORT["tcp"])
456
456
  if a.announce:
457
457
  commands.responder = announce(a, ep, port)
@@ -1,6 +1,6 @@
1
- """Virtual fn 0 implementation of the pre-freeze core (oep-spec 4681d22).
1
+ """Virtual fn 0 implementation of the core, for the core-v1 profile and the conformance sample models.
2
2
 
3
- Independent of the conformance checker and the legacy interface registry.
3
+ Independent of the conformance checker and of the virtual bench's Endpoint and its interface registry.
4
4
  The core-v1 profile has no resources, subscriptions, interfaces or targets.
5
5
  Explicit sample models may supply an independently defined extension hook.
6
6
  """
@@ -62,8 +62,7 @@ def tail(data, owner=False):
62
62
  class Core:
63
63
  def __init__(self, endpoint, extension=None):
64
64
  self.ep = endpoint
65
- # Only explicit current-contract models supply this hook. Legacy profiles
66
- # and the core-v1 profile continue to expose fn 0 alone.
65
+ # Only explicit sample models supply this hook; the core-v1 profile exposes fn 0 alone.
67
66
  self.extension = extension
68
67
  self.holder, self.last, self.owner = None, None, b''
69
68
  self.lease, self.deadline, self.high = 3000, 0, 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: oep-client-python
3
- Version: 0.0.43
3
+ Version: 0.0.44
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
@@ -31,11 +31,10 @@ Description-Content-Type: text/markdown
31
31
 
32
32
  The host side of Open Embedded Probe (OEP). It speaks the v1 protocol of
33
33
  [oep-spec](https://github.com/Open-Embedded-Probe/oep-spec) (the core `docs/oep-core.ja.md`, `docs/oep-transports.ja.md`
34
- and the interfaces `interfaces/*.ja.md`), v1 before the freeze: until the freeze the spec may still break. The wire numbers come from `oep_client.registry`, a verbatim copy of
35
- oep-spec's generated `generated/oep-v1/oep_v1_registry.py`. This is an experimental stage: breaking changes are expected and
36
- no compatible API is promised.
34
+ and the interfaces `interfaces/*.ja.md`). The wire numbers come from `oep_client.registry`, a verbatim copy of
35
+ oep-spec's generated `generated/oep-v1/oep_v1_registry.py`.
37
36
 
38
- **The spec this implements: the oep-spec commit in `tests/vectors/SPEC_COMMIT`** (no `v0.x` tag yet; oep-spec versioning §2 / §6 - before the
37
+ **The spec this implements: the oep-spec commit in `tests/vectors/SPEC_COMMIT`** (oep-spec versioning §2 / §6: before the
39
38
  freeze, revision 1 alone does not fix the forms, so an implementation names the spec commit it implements). The registry
40
39
  and the shared vectors in `tests/vectors/` are copied from that commit; the history is in [CHANGELOG.md](CHANGELOG.md).
41
40
 
@@ -66,7 +65,7 @@ sets the version in pyproject.toml, uv.lock and `oep_client.__version__` and tur
66
65
  the tests and the build it commits, tags, makes the GitHub Release and publishes to PyPI (Trusted Publishing). Record changes
67
66
  under Unreleased in CHANGELOG.md, (EN) and (JA).
68
67
 
69
- A minimal check: [hardware quickstart](docs/hardware-quickstart.ja.md). See the shared [testing policy](docs/testing-policy.ja.md) and [guide for projects using OEP](docs/testing-consumers.ja.md). The [hardware design](docs/hardware-configuration.ja.md) and [configuration examples](docs/hardware-schema.ja.md) describe the planned format; its offline validator/planner is available; integration with the hardware runner is pending. These working documents are in Japanese.
68
+ A minimal check: [hardware quickstart](docs/hardware-quickstart.ja.md). See the shared [testing policy](docs/testing-policy.ja.md) and [guide for projects using OEP](docs/testing-consumers.ja.md). Equipment configuration: [hardware design](docs/hardware-configuration.ja.md) and [configuration examples](docs/hardware-schema.ja.md) (in Japanese).
70
69
 
71
70
  ## Modules (`oep_client`)
72
71
 
@@ -500,4 +499,3 @@ IP_MULTICAST_IF 127.0.0.1. A different `--unit-id` per job keeps parallel jobs a
500
499
  name too). A container or VM answers only on its own network. tests/test_virtual_bench_announce.py does this with
501
500
  `oep find`, `discovery.find_unit` and `oep://UNIT_ID?via=net` (both engines) - with in-process responders announcing a non-OEP
502
501
  TCP service and a wrong TXT unit_id beside it, which the verify drops - skipped where multicast does not loop back.
503
-
@@ -1,4 +1,4 @@
1
- oep_client/__init__.py,sha256=LxTqckboeTxlWZ5qS1qsENf1WwpuF5eJG3mGUI5GyAc,164
1
+ oep_client/__init__.py,sha256=BKL5jblIAcotJRxILFXHy_ZQK96TtAGpJBG_e8J0FbQ,164
2
2
  oep_client/__main__.py,sha256=fXvhDWRLSEPpHM6eSuBzztNzvDQi-Yqgrvz6MS5iRbg,31431
3
3
  oep_client/acquire.py,sha256=uecNDT1onLMeIxFkHFYgqG7chWWvLrAji93KnIisn0A,100072
4
4
  oep_client/arm.py,sha256=SszSLae8zErD4T-a1uQ6s6o3Lz7pe2SR8d3Qy-wi5rY,15633
@@ -11,42 +11,42 @@ oep_client/console.py,sha256=hDxoaXDCzk6KiOo-Y3RqC4yZuLPkCXOVi886_C4xXaE,12910
11
11
  oep_client/core.py,sha256=o7qJjZc68RS9p91TfV3aLsLcTq-jWBO1atB9kGL_tkA,22188
12
12
  oep_client/decode.py,sha256=6pTFVBT0MLAKedZLVKyd5yT8hjrRw4fdDjnoDiE9XRs,2380
13
13
  oep_client/discovery.py,sha256=oES0_NkR1Hc9E_cgPcfW8qfevQcVuYmayMaHuqufdO8,20180
14
- oep_client/dump.py,sha256=rnPOwbcXKk0ATk2Ka8O8p_XN6lTzmAQAhIHjm-iwT7I,13014
15
- oep_client/endpoint.py,sha256=vFlMsctxyBzrSV0NBvWTVz4jXrP1ayTQg3Zr_9yDkfs,238451
14
+ oep_client/dump.py,sha256=9rfO07q1EOY4aLFZkm_9RO8awjxNQa75DIDeKAoF_ac,12995
15
+ oep_client/endpoint.py,sha256=h-B1E8Db8qfRZUmAe1abMy38Xjy4CifF4_WmBInp_6g,238405
16
16
  oep_client/fixture.py,sha256=bEbW7JNIh6uqOq1enp6hRiZ0Ipu8YdzEzS37WaM3cd8,33977
17
- oep_client/frames.py,sha256=44h0dy4xlW3S3y39k3jwxHoKkI2Ib2fsmHdjlPYF310,4990
17
+ oep_client/frames.py,sha256=FM1AGn5NY_e-r1yKBsDkEEOqNrk5XTrlKA5Mq6Ycqiw,4984
18
18
  oep_client/hardware.py,sha256=RboxkRxkQJ3DbNJEXyyiOFYlLFKGxrlcSwHho8zFC1U,30256
19
19
  oep_client/hid_stream.py,sha256=1dG1C5rSqSWs2f0WpzMOKdFd3oY_mzF7z9SxUztjpQA,14093
20
- oep_client/host.py,sha256=p3BROB3OiADdHAT7pqugEF-BQPME7aHSDpeMT-0q2vs,47933
20
+ oep_client/host.py,sha256=Wv0AKySaRu1ERJKERjnGnzfdKYkmFlQsL-Nh3SF_bbE,47875
21
21
  oep_client/interfaces.py,sha256=p-dQ3dtElTIPSmNFEnUzP_Mys6M43_yUqH1cZA0q5LI,11934
22
22
  oep_client/kept_session.py,sha256=S45NwNjeZry5kc5HAyk_orqXKAYf26MuyjJ2ojT51FQ,8084
23
- oep_client/link.py,sha256=4mKefivvb80pSNXMXebXXb97wgut9K_qihmxyfDEl6I,145569
23
+ oep_client/link.py,sha256=-6N95ruUInNFJnmVOXCr-7XSgXDK-fpkjYJEK5nUFuE,145428
24
24
  oep_client/linktest.py,sha256=zj9Ek28VkjyuIPsiU3iF-UEZmY_xMnNjNL-vK-jOQ3Q,10258
25
25
  oep_client/message.py,sha256=Kw-PwkMCwa8VGUBd1HWTXe8Epe4FwNcBx8262mWx2rk,14152
26
26
  oep_client/names.py,sha256=ohrRvQNURraYyJ-BtjHRwxGt_GLq-t8IO0aOji9Dhe0,3531
27
- oep_client/pins.py,sha256=yY4B5XKkUa9jtZeWM0UuPowhHxYLLxT0RxkpH-ep-mo,53777
27
+ oep_client/pins.py,sha256=c5aNQtj7ZWM1bxYBtByLuWtkWM4JOra2QCbjvlHybmg,53690
28
28
  oep_client/probe_log.py,sha256=gAamfON2M7lMH3xOn4Wpmes_Wp0H4c2EBNbpXjIvCMM,4927
29
29
  oep_client/pytest_conformance.py,sha256=-bcJU2E1UE4xjQ7HZjaIgtp0l65cIibBTNFnaW2tews,2929
30
30
  oep_client/registry.py,sha256=GfLdoZYSc37PBQ2rgXHM4DtFdU0mpnroM42jVofRx44,23309
31
- oep_client/riscv.py,sha256=ywBg1VvvpJydOO-D1UlpuKgNAVV8w1lvWhKc6JXeDlo,60428
31
+ oep_client/riscv.py,sha256=o_YElQuJZoBUzqO7QV9VkWVeD4UE2pUx_ciR_TMHRWI,60419
32
32
  oep_client/rp2350.py,sha256=7OMyj270k3AY1e3-ljicPwOjf9jOlokbT6QNkA0b0yY,4227
33
33
  oep_client/settings.py,sha256=wVRpvAmcvDygVE9PCbo4-7k-tq6pIzKh7VRlmtLO1Fk,26391
34
- oep_client/speed_record.py,sha256=6THUKbN7gQKpfIdUO2551P8mXiAFqbFDky72Xbki7L0,7229
34
+ oep_client/speed_record.py,sha256=hdVx8mCeWqPC3gWrBsOyfzVZcJfN5_CJfpW18WbsBmc,7223
35
35
  oep_client/stimulus.py,sha256=pfX4xLjyG3UWIJRWUHnkg9c1ueL1MeozHj3CnlJ7dpA,6072
36
- oep_client/targets.py,sha256=IBKVso3bbPj61stzoHlFA74-ANgr-dVgwc5ppYh5X68,7176
36
+ oep_client/targets.py,sha256=ixUxbZUfYqOJjZzcaOudwV2wweVwdk0G85dfRiZzMeA,7183
37
37
  oep_client/uiapduino.py,sha256=oafP1SyKPO3cox-2RYbWUZusy4vc6NsEVC7Z-Y1sjWI,6337
38
38
  oep_client/usb_stream.py,sha256=zRGGHkvtOme6lIZ-gkrCe2xKn9hC62JGqmc7pKQDAJI,23540
39
- oep_client/virtual_bench.py,sha256=I1SBbqJ0Dk9zQzGjyYzV9rAUApiLOQVL4vFQzv43a94,52794
39
+ oep_client/virtual_bench.py,sha256=PC6pOoTcm10p0WHUrIO-_xyzPWAyXZimXgQks3IgOYY,52762
40
40
  oep_client/virtual_bench_capture.py,sha256=vwlLPkiWopgQxNGNxCFI84FR_cX0y6XWgszkDcoieiY,110696
41
41
  oep_client/virtual_bench_mdns.py,sha256=cnJNBKg5zTduXUcH-wqN_ZBDGl7DyL-tL3CBn2jro0E,13305
42
42
  oep_client/virtual_bench_serial.py,sha256=EvbdOYeGrM6CRti2b90I0PzpmmherfoJRaAg4v7Iq9Y,13205
43
- oep_client/virtual_bench_serve.py,sha256=jmesv58pfQr3KvwqlX4brIWoZ5iEe2q5IWGdZ2aCG3g,39027
43
+ oep_client/virtual_bench_serve.py,sha256=oNXrESlch-fXpfCg0Y5w3OmKNdtrOVwXkuhZBTPP6PQ,39015
44
44
  oep_client/virtual_bench_trigger.py,sha256=2c3gGOM8wXucTXbc1bTKQ5haX7bAkGJeOryGghrtcRk,23874
45
45
  oep_client/virtual_bench_usb.py,sha256=cnewgbsl30b0PgwkfebwSf3xjKyPg9y8vTd5Jew5r9o,4001
46
- oep_client/virtual_core.py,sha256=cFqqCKBgVU0Wbf0UWBmKx16K3cSriiqU60FK3lfalAQ,10709
46
+ oep_client/virtual_core.py,sha256=F-UxtQIld4eE04_M8j4ANMlQ12jXANzfTnfn59kUWHk,10716
47
47
  oep_client/virtual_fixture_drive.py,sha256=_G3MVqkxpd1SfKPz1XRkYbPzAQvgBlJzVUNhjAhDdz4,21708
48
48
  oep_client/virtual_names.py,sha256=p72ME65R9Jy56xmVYnVCtapK3Id8iFpAdI5xLe2tNZ0,1449
49
- oep_client/conformance/__init__.py,sha256=T_zCvXKQiaUIBPQ3aht5wLSsRNYaXKUNbbRGod0L558,61746
49
+ oep_client/conformance/__init__.py,sha256=o17AgcYob-Ahn7qWewjCo_7jK4o6kMnX-xHwG9V4Kv8,61738
50
50
  oep_client/conformance/allocator.py,sha256=VE2nzIpXZJe4IBfgbRShp69JIwUFtLpxorQ_mO28SlM,6251
51
51
  oep_client/conformance/allocator_model.py,sha256=j6l1E1Hlju1jNeFQ_N0a2mDaegaTeyk6iScqzMpvvTc,1563
52
52
  oep_client/conformance/allocator_sample.py,sha256=xtiXuZa3VDTilrZArIWOiRyOkuXJ98_rY2M65sIVvpo,855
@@ -81,7 +81,7 @@ oep_client/conformance/clock.py,sha256=bDqBjih71zg_mhkgCSryzKI_N8FEoGoGv9jO4PMYD
81
81
  oep_client/conformance/clock_model.py,sha256=jyB8oTVR5sqbzeJCCWxdQBnzNNl4_uITLLYQ-yx8pRU,2568
82
82
  oep_client/conformance/clock_sample.py,sha256=x24mSpQoOamrXrinmnF_Tk4NPk76LwS6ZhfuK2SCwCo,673
83
83
  oep_client/conformance/core_fixed_fields.py,sha256=LRFP9yGOjDHQM1diX1HMdwXh9jMgAOY6xIC-woCikSk,6297
84
- oep_client/conformance/core_smoke.py,sha256=UQeohalc0nxoBRulk68c7V5WVIqJc1XFrfe08EdIPFg,10823
84
+ oep_client/conformance/core_smoke.py,sha256=4vLm1j2yIuvUH5sxWa7yJzNKzRTAFYzRhby9Ef2eZ6Y,10815
85
85
  oep_client/conformance/corr.py,sha256=P6ljdsXpBq-vyEXRWOB1MqACQjT6HRBXgfAxgkyPjl4,6552
86
86
  oep_client/conformance/cut.py,sha256=Oj9aj48g2VSrqFHRNlkY22MzXxQbr13Q8QXUsEMETis,7942
87
87
  oep_client/conformance/cut_model.py,sha256=bHPnK8vKoInKVslW0KlJXRRgpGK-7ktIVGUEXo60X34,4791
@@ -157,7 +157,7 @@ oep_client/conformance/notification_sequence.py,sha256=TGdLjqPkCBtjH6f_oxgPGfl-l
157
157
  oep_client/conformance/notification_sequence_sample.py,sha256=awSniydBvRoy03PCR5Y6xHAVmLWV1wjKwfA2dwI8XCI,494
158
158
  oep_client/conformance/oep_declaration_model.py,sha256=_Zq_eLLkHNGcDfA0tPptWpqT4tZbCsVrdjE2k9lAcco,2947
159
159
  oep_client/conformance/oep_declarations.py,sha256=0DrrDdveGEiSMp5fjy-ZJjR0mjAxv2TQLylZl_hnqfo,7492
160
- oep_client/conformance/oep_smoke.py,sha256=P-FGzXl37oIvBMPrPHDg0fDsX7lq3XAICGXWhD6Fpk8,12496
160
+ oep_client/conformance/oep_smoke.py,sha256=8XjyK4Rx27YLYek_JTJtyS8swGa0x0Pf5dbzb-YlIlg,12488
161
161
  oep_client/conformance/outcome_model.py,sha256=jnKDNvkLBsSFQqQQEqCDt3zliKZx0b5LiLCHafrBv4U,3697
162
162
  oep_client/conformance/outcome_sample.py,sha256=6dbEwddcY0z4jGZsazp_gGI_Vu0em-0rOrGN2BVUMzI,673
163
163
  oep_client/conformance/outcomes.py,sha256=FktfF9aaexnXCgSNDYU6OZeqRuLd3ppFMXE1UrW-H2o,10047
@@ -250,8 +250,8 @@ oep_client/conformance/wire_options_sample.py,sha256=dog-yvUcu693M8b51tA5TnhAnKr
250
250
  oep_client/conformance/writer_lease.py,sha256=5VXS7kt1R4j6B26XdJa6UOqJg-a05ZewC2ynVmyxMTM,7331
251
251
  oep_client/conformance/writer_lease_model.py,sha256=FxhDqqzdFOa_SSHSvjdQFh49Wn3YuZ98ISSlRRxrq9E,1721
252
252
  oep_client/conformance/writer_lease_sample.py,sha256=oowRwYUNAE4f6rEE2HmYlSS9dDWE0TGegkcsqVH8Nak,455
253
- oep_client_python-0.0.43.dist-info/METADATA,sha256=r4CGX-c86d8zyO_orDssPk6E4bV4Szle72c_EfLxae0,55578
254
- oep_client_python-0.0.43.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
255
- oep_client_python-0.0.43.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
256
- oep_client_python-0.0.43.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
257
- oep_client_python-0.0.43.dist-info/RECORD,,
253
+ oep_client_python-0.0.44.dist-info/METADATA,sha256=6_CmjBSUWjX21ppK-I0ujv-7oApIOpmgWnRnqEUofA4,55269
254
+ oep_client_python-0.0.44.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
255
+ oep_client_python-0.0.44.dist-info/entry_points.txt,sha256=XEt39Jz7oQyU9Hfg_tV6eDGofNxWYrjSfslxKP-fh70,135
256
+ oep_client_python-0.0.44.dist-info/licenses/LICENSE,sha256=ntlalztb3L1OaNAxmQdHlubu5fVhjMc9oRZi3PeQhXg,1076
257
+ oep_client_python-0.0.44.dist-info/RECORD,,