oep-client-python 0.0.15__tar.gz → 0.0.17__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.
Files changed (54) hide show
  1. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/CHANGELOG.md +8 -0
  2. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/PKG-INFO +1 -1
  3. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/pyproject.toml +1 -1
  4. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/__init__.py +1 -1
  5. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/endpoint.py +16 -3
  6. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_fake_capture.py +18 -0
  7. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/.gitignore +0 -0
  8. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/LICENSE +0 -0
  9. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/README.ja.md +0 -0
  10. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/README.md +0 -0
  11. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/__main__.py +0 -0
  12. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/arm.py +0 -0
  13. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/capture.py +0 -0
  14. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/catalog.py +0 -0
  15. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/ch32_flash.py +0 -0
  16. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/cobs.py +0 -0
  17. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/config.py +0 -0
  18. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/console.py +0 -0
  19. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/core.py +0 -0
  20. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/decode.py +0 -0
  21. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/dump.py +0 -0
  22. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/esp32_targets.py +0 -0
  23. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/fake.py +0 -0
  24. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/fake_capture.py +0 -0
  25. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/fake_serial.py +0 -0
  26. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/fake_serve.py +0 -0
  27. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/fixture.py +0 -0
  28. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/frames.py +0 -0
  29. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/hid_stream.py +0 -0
  30. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/host.py +0 -0
  31. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/interfaces.py +0 -0
  32. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/link.py +0 -0
  33. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/message.py +0 -0
  34. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/names.py +0 -0
  35. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/registry.py +0 -0
  36. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/riscv.py +0 -0
  37. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/rp2350.py +0 -0
  38. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/target.py +0 -0
  39. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/uiapduino.py +0 -0
  40. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/src/oep_client/usb_stream.py +0 -0
  41. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_capabilities.py +0 -0
  42. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_capture.py +0 -0
  43. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_cobs.py +0 -0
  44. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_config.py +0 -0
  45. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_esp32_targets.py +0 -0
  46. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_fake_spec.py +0 -0
  47. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_flash_console.py +0 -0
  48. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_hid_stream.py +0 -0
  49. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_interfaces.py +0 -0
  50. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_link_host.py +0 -0
  51. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_link_serial.py +0 -0
  52. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_session.py +0 -0
  53. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_target_parts.py +0 -0
  54. {oep_client_python-0.0.15 → oep_client_python-0.0.17}/tests/test_usb_stream.py +0 -0
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.0.17
6
+ - (EN) The fake's analog shares its pins with nothing (oep-if-capture §1.2): a plan that puts a logic capture, a fixture or a wire on an analog channel, or the analog on a pin another fn / a slot / a connection uses, is rejected unavailable, whichever comes second. A logic capture still listens on anything else.
7
+ - (JA) 偽の probe のアナログは、ピンを誰とも共有しない(oep-if-capture §1.2)。アナログのチャネルにロジックのキャプチャ、fixture、線を載せる plan も、ほかの fn・スロット・接続が使うピンにアナログを載せる plan も、後から来た方を rejected unavailable で断る。ロジックのキャプチャは、それ以外ではどのピンでも聞ける。
8
+
9
+ ## 0.0.16
10
+ - (EN) No user-facing changes recorded.
11
+ - (JA) ユーザー向け変更の記録はありません。
12
+
5
13
  ## 0.0.15
6
14
  - (EN) `CaptureGroup.wait()` keeps the lock alive while it waits too (`keepalive_s`).
7
15
  - (JA) `CaptureGroup.wait()` も、待つ間ロックを保つ(`keepalive_s`)。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: oep-client-python
3
- Version: 0.0.15
3
+ Version: 0.0.17
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.15"
7
+ version = "0.0.17"
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"
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.0.15"
5
+ __version__ = "0.0.17"
@@ -518,7 +518,7 @@ class Endpoint:
518
518
  def _held(self, fn: int | None = None, pair: tuple[int, int] | None = None) -> set[int]:
519
519
  """Channels something holds (core §8.1): the plan, the slots' pairs, the live connections' pairs - except
520
520
  wire `fn`'s own connection on `pair` (attaching there again, or scanning through it)."""
521
- held = {a[2] for a in self.plan if a[0] not in self.captures} # a capture only listens
521
+ held = {a[2] for a in self.plan if not self._listens(a[0])} # a logic capture only listens
522
522
  held |= {p for s in self.slots.values() for p in s.pair if p != 0xFFFF and not (s.wire_fn == fn and s.pair == pair)}
523
523
  held |= {p for c in self.conns.values() for p in c.pair if p != 0xFFFF and not (c.fn == fn and c.pair == pair)}
524
524
  return held
@@ -799,14 +799,27 @@ class Endpoint:
799
799
  return m.COMPLETED, m.SUCCESS, b""
800
800
  return m.REJECTED, m.UNKNOWN_OPERATION, b""
801
801
 
802
+ def _listens(self, fn: int) -> bool:
803
+ """A logic capture only listens: it shares pins with anything (core §8.1). The analog does not: its pads go to
804
+ their analog function, cutting their digital input and output (oep-if-capture §1.2), as on this library's ESP32s."""
805
+ return fn in self.captures and not self.captures[fn].analog
806
+
802
807
  def _check_plan(self, got: list[tuple[int, int, int]]) -> None:
803
808
  """plan_apply's all-or-nothing check: the roles each fn has, and no pin another fn (or a slot) holds."""
804
809
  named = {fn for fn, _, _ in got}
805
- # a capture only listens: it shares pins with anything, and nothing is kept from a pin by it (core §8.1)
806
- kept = {a for a in self.plan if a[0] not in named and a[0] not in self.captures}
810
+ others = {a for a in self.plan if a[0] not in named}
811
+ kept = {a for a in others if not self._listens(a[0])}
807
812
  slot_pins = {p for s in self.slots.values() for p in s.pair if p != 0xFFFF}
808
813
  slot_pins |= {p for c in self.conns.values() for p in c.pair if p != 0xFFFF} # a live connection's pins too
814
+ analog = {fn for fn, cap in self.captures.items() if cap.analog}
809
815
  for fn, role, ch in got:
816
+ beside = [f for f, _, c in got if c == ch and f != fn] + [a[0] for a in others if a[2] == ch]
817
+ if fn in analog: # the analog shares its pin with nothing: another fn's plan, a slot, a connection
818
+ if role not in self._declared_roles(fn, ch) or beside or ch in slot_pins:
819
+ raise Reject(m.UNAVAILABLE)
820
+ continue
821
+ if any(f in analog for f in beside): # nor may anything come onto an analog pin
822
+ raise Reject(m.UNAVAILABLE)
810
823
  if fn in self.captures:
811
824
  if role not in self._declared_roles(fn, ch):
812
825
  raise Reject(m.UNAVAILABLE)
@@ -160,6 +160,24 @@ def test_a_capture_listens_on_pins_other_interfaces_hold():
160
160
  core.plan_apply(hst, [(gpio, 1, 12)]) # the UART still holds it against drivers
161
161
 
162
162
 
163
+
164
+ def test_an_analog_pin_is_shared_with_nothing():
165
+ """The analog cuts its pads' digital input and output (oep-if-capture §1.2): refused whichever comes second."""
166
+ ep, hst, lc, _ = bench()
167
+ an = c.AnalogCapture(hst)
168
+ gpio = core.find(hst, "oep.fixture.gpio")
169
+ core.plan_apply(hst, [(an.fn, 0, 16)])
170
+ for other in ([(lc.fn, 0, 16)], [(gpio, 1, 16)]): # logic that would read 0, a driver that would not drive
171
+ with pytest.raises(h.Rejected):
172
+ core.plan_apply(hst, other)
173
+ core.plan_apply(hst, [(lc.fn, 0, 17)]) # another pad: fine
174
+ core.plan_release(hst, [an.fn])
175
+ core.plan_apply(hst, [(lc.fn, 0, 16)])
176
+ with pytest.raises(h.Rejected):
177
+ core.plan_apply(hst, [(an.fn, 0, 16)]) # the analog after the logic: refused too
178
+ with pytest.raises(h.Rejected):
179
+ core.plan_apply(hst, [(an.fn, 0, 18), (gpio, 1, 18)]) # in one request as well
180
+
163
181
  def test_fake_serve_streams_over_tcp_to_the_client():
164
182
  """The whole path wireskein takes: open_host, take, plan, configure, subscribe, start, stream, stop, finish."""
165
183
  import subprocess