oep-client-python 0.0.22__tar.gz → 0.0.23__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.
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/CHANGELOG.md +4 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/PKG-INFO +1 -1
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/pyproject.toml +1 -1
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/__init__.py +1 -1
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/link.py +19 -6
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/.gitignore +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/LICENSE +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/README.ja.md +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/README.md +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/__main__.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/arm.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/capture.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/catalog.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/ch32_flash.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/cobs.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/config.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/console.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/core.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/decode.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/dump.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/endpoint.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/fake.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/fake_capture.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/fake_serial.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/fake_serve.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/fixture.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/frames.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/hid_stream.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/host.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/interfaces.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/message.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/names.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/registry.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/riscv.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/rp2350.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/uiapduino.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/src/oep_client/usb_stream.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_capabilities.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_capture.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_cobs.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_config.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_fake_capture.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_fake_spec.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_fixture_targets.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_flash_console.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_hid_stream.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_interfaces.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_link_host.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_link_serial.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_session.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_target_parts.py +0 -0
- {oep_client_python-0.0.22 → oep_client_python-0.0.23}/tests/test_usb_stream.py +0 -0
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.0.23
|
|
6
|
+
- (EN) `link.open_host("tcp://…")` waits 15 s for a reply and does not send a request again by itself (`resend=False`): behind ch32rv's broker, the broker retries towards the probe, and a second copy from the client only raced it (V003 jig, 2026-10-01). `open_host(..., timeout=, resend=)` set both explicitly; serial and USB keep 3 s and one resend.
|
|
7
|
+
- (JA) `link.open_host("tcp://…")` は応答を 15 秒待ち、自分では送り直さない(`resend=False`)。ch32rv のブローカーの後ろでは、ブローカーが probe に送り直すので、client からの 2 通目は競合するだけだった(V003 ジグ、2026-10-01)。`open_host(..., timeout=, resend=)` で明示できる。シリアルと USB は 3 秒と 1 回の送り直しのまま。
|
|
8
|
+
|
|
5
9
|
## 0.0.22
|
|
6
10
|
- (EN) Breaking: the wire follows oep-spec's zero-base rewrite of 2026-10-01 (docs/v1-zero-base-proposal.ja.md §3 / §7; registry synced). Every answer that ended in data or a list now carries its length and may be followed by TLVs: read answers `start flags len data [TLV]` (console, fixture UART; capture `len` u32), gpio read `n n×level`, dmi `done status nvals values`, arm-adi transfer `done status ack nvals values`, run `status stopped dpc elapsed_us nvals values` (stopped 2 = the hart could not be halted: `RunResult.not_halted`), data frames `position len data [TLV]`, events `kind fixed-part [TLV]`. TLVs have a long form (`tag 0xFF len(u16) value` for 255 bytes and more; `message.tlv` / `split_tlvs`, the long form with a short value is `message.BadTlv`). confirm answers the probe's `boot_id`; subscribe's `max_delay_ms` is u32; `rejected unsupported` is always `tag [TLV]` (0x00 = a fixed-part value: `Unsupported.tag` None, `.tlvs`).
|
|
7
11
|
- (JA) 破壊的変更: wire を oep-spec の 2026-10-01 のゼロベース見直し(docs/v1-zero-base-proposal.ja.md §3 / §7。registry を写し直した)に揃えた。データや並びで終わっていた応答はすべて長さを持ち、後ろに TLV を置ける: read の応答 `start flags len data [TLV]`(console、fixture UART。capture の `len` は u32)、gpio read `n n×level`、dmi `done status nvals values`、arm-adi transfer `done status ack nvals values`、run `status stopped dpc elapsed_us nvals values`(stopped 2 = hart を止められなかった: `RunResult.not_halted`)、データフレーム `position len data [TLV]`、出来事 `kind 固定部 [TLV]`。TLV に長い形(255 byte 以上は `tag 0xFF len(u16) value`。`message.tlv` / `split_tlvs`、短い値の長い形は `message.BadTlv`)。confirm は probe の `boot_id` を返す。subscribe の `max_delay_ms` は u32。`rejected unsupported` は常に `tag [TLV]`(0x00 = 固定部の値: `Unsupported.tag` は None、`.tlvs`)。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: oep-client-python
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.23
|
|
4
4
|
Summary: Open Embedded Probe (OEP) v1 host: serial / USB / TCP transports, the session rules, the standard interfaces, and a fake probe
|
|
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
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "oep-client-python"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.23"
|
|
8
8
|
description = "Open Embedded Probe (OEP) v1 host: serial / USB / TCP transports, the session rules, the standard interfaces, and a fake probe"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -122,6 +122,7 @@ class SerialLink:
|
|
|
122
122
|
self.stream = stream
|
|
123
123
|
self.framing = framing
|
|
124
124
|
self.timeout = timeout
|
|
125
|
+
self.resend = True # a lost reply: the request once more with the same corr (core §5.2)
|
|
125
126
|
self.retries = 0
|
|
126
127
|
self.corrupt = 0
|
|
127
128
|
self.stale = 0 # replies that answered another request
|
|
@@ -284,7 +285,7 @@ class SerialLink:
|
|
|
284
285
|
if isinstance(e, cobs.CorruptFrame):
|
|
285
286
|
self.corrupt += 1
|
|
286
287
|
self._recover()
|
|
287
|
-
if attempt or (message[0] & m.ROLE_SESSION and self.ended_blind):
|
|
288
|
+
if attempt or not self.resend or (message[0] & m.ROLE_SESSION and self.ended_blind):
|
|
288
289
|
raise
|
|
289
290
|
# sent once more with the same corr, state-changing ones too: the probe keeps the lock holder's recent
|
|
290
291
|
# results and answers a repeat from them instead of running it twice (v1-open-proposals §4). A result
|
|
@@ -303,7 +304,7 @@ class SerialLink:
|
|
|
303
304
|
try:
|
|
304
305
|
return self._exchange_once(messages, max_inflight, window_bytes, replies)
|
|
305
306
|
except (cobs.CorruptFrame, TimeoutError, FramingLost):
|
|
306
|
-
if self.ended_blind:
|
|
307
|
+
if self.ended_blind or not self.resend:
|
|
307
308
|
raise
|
|
308
309
|
self.retries += 1
|
|
309
310
|
rest = messages[len(replies):]
|
|
@@ -433,19 +434,29 @@ def _open_usb_stream(kind: str, vid: int, pid: int, serial: str | None):
|
|
|
433
434
|
return UsbBulkStream.open(vid, pid, serial)
|
|
434
435
|
|
|
435
436
|
|
|
436
|
-
|
|
437
|
+
TCP_TIMEOUT = 15.0 # behind a broker: outlast its own 3 s retry towards the probe, and never send again ourselves
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def open_host(target: str, timeout: float | None = None, resend: bool | None = None):
|
|
437
441
|
"""A Host on `target`, with the link's pipelining bound to the probe's limits (core confirm): Host.pipeline and
|
|
438
442
|
everything built on it (flash, capture reads) then keep several requests in flight.
|
|
439
443
|
|
|
440
444
|
target: a serial port path (COM3 on Windows); tcp://HOST:PORT for a local broker (length frames); usb[:VID:PID[:SERIAL]]
|
|
441
445
|
(hex) for the probe's USB device, vendor bulk then HID (oep-core §3.3); usb:UNIT_ID for the OEP probe whose USB
|
|
442
|
-
serial is that unit id, whatever its VID:PID.
|
|
446
|
+
serial is that unit id, whatever its VID:PID.
|
|
447
|
+
|
|
448
|
+
timeout: seconds to wait for a reply (default 3; TCP 15). resend: send a request once more with the same corr when
|
|
449
|
+
its reply was lost (default on; off for TCP, where a broker retries towards the probe itself and a second copy from
|
|
450
|
+
here would only race it - a lost reply is then raised to the caller)."""
|
|
443
451
|
from . import host
|
|
444
452
|
if target.startswith("tcp://"):
|
|
445
453
|
addr, _, port = target[len("tcp://"):].rpartition(":")
|
|
446
|
-
lk = SerialLink.on_stream(TcpStream(addr or "127.0.0.1", int(port)), "length",
|
|
454
|
+
lk = SerialLink.on_stream(TcpStream(addr or "127.0.0.1", int(port)), "length",
|
|
455
|
+
TCP_TIMEOUT if timeout is None else timeout)
|
|
456
|
+
lk.resend = False if resend is None else resend
|
|
447
457
|
lk.transport = "tcp"
|
|
448
458
|
elif target == "usb" or target.startswith("usb:"):
|
|
459
|
+
timeout = 3.0 if timeout is None else timeout
|
|
449
460
|
parts = target.split(":")[1:]
|
|
450
461
|
if len(parts) == 1: # usb:UNIT_ID (any length: a VID comes with its PID)
|
|
451
462
|
vid, pid = find_usb(parts[0])
|
|
@@ -454,8 +465,10 @@ def open_host(target: str, timeout: float = 3.0):
|
|
|
454
465
|
pid = int(parts[1], 16) if len(parts) > 1 else USB_PID
|
|
455
466
|
return open_usb_host(vid, pid, parts[2] if len(parts) > 2 else None, timeout)
|
|
456
467
|
else:
|
|
457
|
-
lk = SerialLink(target, timeout)
|
|
468
|
+
lk = SerialLink(target, 3.0 if timeout is None else timeout)
|
|
458
469
|
lk.transport = "serial"
|
|
470
|
+
if resend is not None:
|
|
471
|
+
lk.resend = resend
|
|
459
472
|
hst = host.Host(lk.send)
|
|
460
473
|
lk.attach_host(hst)
|
|
461
474
|
return hst
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|