replx 1.10__tar.gz → 1.10.2__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 (152) hide show
  1. {replx-1.10/replx.egg-info → replx-1.10.2}/PKG-INFO +1 -1
  2. {replx-1.10 → replx-1.10.2}/replx/__init__.py +1 -1
  3. {replx-1.10 → replx-1.10.2}/replx/cli/agent/client/core.py +41 -0
  4. {replx-1.10 → replx-1.10.2}/replx/cli/commands/wifi.py +21 -2
  5. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/updater.py +4 -7
  6. {replx-1.10 → replx-1.10.2/replx.egg-info}/PKG-INFO +1 -1
  7. {replx-1.10 → replx-1.10.2}/LICENSE +0 -0
  8. {replx-1.10 → replx-1.10.2}/README.md +0 -0
  9. {replx-1.10 → replx-1.10.2}/pyproject.toml +0 -0
  10. {replx-1.10 → replx-1.10.2}/replx/__main__.py +0 -0
  11. {replx-1.10 → replx-1.10.2}/replx/cli/__init__.py +0 -0
  12. {replx-1.10 → replx-1.10.2}/replx/cli/agent/__init__.py +0 -0
  13. {replx-1.10 → replx-1.10.2}/replx/cli/agent/client/__init__.py +0 -0
  14. {replx-1.10 → replx-1.10.2}/replx/cli/agent/client/session.py +0 -0
  15. {replx-1.10 → replx-1.10.2}/replx/cli/agent/protocol.py +0 -0
  16. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/__init__.py +0 -0
  17. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/__main__.py +0 -0
  18. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/command_dispatcher.py +0 -0
  19. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/connection_manager.py +0 -0
  20. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/core.py +0 -0
  21. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/__init__.py +0 -0
  22. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/exec.py +0 -0
  23. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/filesystem.py +0 -0
  24. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/i2c.py +0 -0
  25. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/repl.py +0 -0
  26. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/session.py +0 -0
  27. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/spi.py +0 -0
  28. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/transfer.py +0 -0
  29. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/handlers/uart.py +0 -0
  30. {replx-1.10 → replx-1.10.2}/replx/cli/agent/server/session_manager.py +0 -0
  31. {replx-1.10 → replx-1.10.2}/replx/cli/app.py +0 -0
  32. {replx-1.10 → replx-1.10.2}/replx/cli/commands/__init__.py +0 -0
  33. {replx-1.10 → replx-1.10.2}/replx/cli/commands/_common.py +0 -0
  34. {replx-1.10 → replx-1.10.2}/replx/cli/commands/adc.py +0 -0
  35. {replx-1.10 → replx-1.10.2}/replx/cli/commands/device.py +0 -0
  36. {replx-1.10 → replx-1.10.2}/replx/cli/commands/exec.py +0 -0
  37. {replx-1.10 → replx-1.10.2}/replx/cli/commands/file.py +0 -0
  38. {replx-1.10 → replx-1.10.2}/replx/cli/commands/firmware.py +0 -0
  39. {replx-1.10 → replx-1.10.2}/replx/cli/commands/gpio.py +0 -0
  40. {replx-1.10 → replx-1.10.2}/replx/cli/commands/i2c.py +0 -0
  41. {replx-1.10 → replx-1.10.2}/replx/cli/commands/package.py +0 -0
  42. {replx-1.10 → replx-1.10.2}/replx/cli/commands/pwm.py +0 -0
  43. {replx-1.10 → replx-1.10.2}/replx/cli/commands/spi.py +0 -0
  44. {replx-1.10 → replx-1.10.2}/replx/cli/commands/uart.py +0 -0
  45. {replx-1.10 → replx-1.10.2}/replx/cli/commands/utility.py +0 -0
  46. {replx-1.10 → replx-1.10.2}/replx/cli/config.py +0 -0
  47. {replx-1.10 → replx-1.10.2}/replx/cli/connection.py +0 -0
  48. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/__init__.py +0 -0
  49. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/compiler.py +0 -0
  50. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/environment.py +0 -0
  51. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/output.py +0 -0
  52. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/registry.py +0 -0
  53. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/scanner.py +0 -0
  54. {replx-1.10 → replx-1.10.2}/replx/cli/helpers/store.py +0 -0
  55. {replx-1.10 → replx-1.10.2}/replx/commands.py +0 -0
  56. {replx-1.10 → replx-1.10.2}/replx/protocol/__init__.py +0 -0
  57. {replx-1.10 → replx-1.10.2}/replx/protocol/repl.py +0 -0
  58. {replx-1.10 → replx-1.10.2}/replx/protocol/storage.py +0 -0
  59. {replx-1.10 → replx-1.10.2}/replx/terminal.py +0 -0
  60. {replx-1.10 → replx-1.10.2}/replx/transport/__init__.py +0 -0
  61. {replx-1.10 → replx-1.10.2}/replx/transport/serial.py +0 -0
  62. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/_thread.pyi +0 -0
  63. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/aioble/__init__.pyi +0 -0
  64. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/array.pyi +0 -0
  65. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/asyncio/__init__.pyi +0 -0
  66. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/binascii.pyi +0 -0
  67. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/bluetooth.pyi +0 -0
  68. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/builtins.pyi +0 -0
  69. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/cmath.pyi +0 -0
  70. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/collections.pyi +0 -0
  71. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/cryptolib.pyi +0 -0
  72. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/deflate.pyi +0 -0
  73. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/errno.pyi +0 -0
  74. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/framebuf.pyi +0 -0
  75. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/gc.pyi +0 -0
  76. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/hashlib.pyi +0 -0
  77. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/heapq.pyi +0 -0
  78. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/io.pyi +0 -0
  79. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/json.pyi +0 -0
  80. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/lwip.pyi +0 -0
  81. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/machine.pyi +0 -0
  82. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/math.pyi +0 -0
  83. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/micropython.pyi +0 -0
  84. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/mip/__init__.pyi +0 -0
  85. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/network.pyi +0 -0
  86. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/ntptime.pyi +0 -0
  87. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/os.pyi +0 -0
  88. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/platform.pyi +0 -0
  89. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/random.pyi +0 -0
  90. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/re.pyi +0 -0
  91. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/requests/__init__.pyi +0 -0
  92. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/select.pyi +0 -0
  93. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/socket.pyi +0 -0
  94. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/ssl.pyi +0 -0
  95. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/struct.pyi +0 -0
  96. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/sys.pyi +0 -0
  97. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/time.pyi +0 -0
  98. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/tls.pyi +0 -0
  99. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/uasyncio.pyi +0 -0
  100. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/uctypes.pyi +0 -0
  101. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/urequests.pyi +0 -0
  102. {replx-1.10 → replx-1.10.2}/replx/typehints/comm/vfs.pyi +0 -0
  103. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/binascii.pyi +0 -0
  104. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/digi/__init__.pyi +0 -0
  105. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/digi/ble.pyi +0 -0
  106. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/errno.pyi +0 -0
  107. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/hashlib.pyi +0 -0
  108. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/io.pyi +0 -0
  109. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/json.pyi +0 -0
  110. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/machine.pyi +0 -0
  111. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/math.pyi +0 -0
  112. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/micropython.pyi +0 -0
  113. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/network.pyi +0 -0
  114. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/os.pyi +0 -0
  115. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/select.pyi +0 -0
  116. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/socket.pyi +0 -0
  117. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/ssl.pyi +0 -0
  118. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/struct.pyi +0 -0
  119. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/sys.pyi +0 -0
  120. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/time.pyi +0 -0
  121. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/ubinascii.pyi +0 -0
  122. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/ucryptolib.pyi +0 -0
  123. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/uerrno.pyi +0 -0
  124. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/uhashlib.pyi +0 -0
  125. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/uio.pyi +0 -0
  126. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/ujson.pyi +0 -0
  127. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/umachine.pyi +0 -0
  128. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/uos.pyi +0 -0
  129. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/uselect.pyi +0 -0
  130. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/usocket.pyi +0 -0
  131. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/ussl.pyi +0 -0
  132. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/ustruct.pyi +0 -0
  133. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/utime.pyi +0 -0
  134. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/xbee/__init__.pyi +0 -0
  135. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/xbee/modem_status.pyi +0 -0
  136. {replx-1.10 → replx-1.10.2}/replx/typehints/comm_separate/EFR32MG/xbee/relay.pyi +0 -0
  137. {replx-1.10 → replx-1.10.2}/replx/typehints/core/ESP32/aioespnow.pyi +0 -0
  138. {replx-1.10 → replx-1.10.2}/replx/typehints/core/ESP32/esp.pyi +0 -0
  139. {replx-1.10 → replx-1.10.2}/replx/typehints/core/ESP32/esp32.pyi +0 -0
  140. {replx-1.10 → replx-1.10.2}/replx/typehints/core/ESP32/espnow.pyi +0 -0
  141. {replx-1.10 → replx-1.10.2}/replx/typehints/core/MIMXRT1062DVJ6A/mimxrt.pyi +0 -0
  142. {replx-1.10 → replx-1.10.2}/replx/typehints/core/RP2350/rp2.pyi +0 -0
  143. {replx-1.10 → replx-1.10.2}/replx/utils/__init__.py +0 -0
  144. {replx-1.10 → replx-1.10.2}/replx/utils/constants.py +0 -0
  145. {replx-1.10 → replx-1.10.2}/replx/utils/device_info.py +0 -0
  146. {replx-1.10 → replx-1.10.2}/replx/utils/exceptions.py +0 -0
  147. {replx-1.10 → replx-1.10.2}/replx.egg-info/SOURCES.txt +0 -0
  148. {replx-1.10 → replx-1.10.2}/replx.egg-info/dependency_links.txt +0 -0
  149. {replx-1.10 → replx-1.10.2}/replx.egg-info/entry_points.txt +0 -0
  150. {replx-1.10 → replx-1.10.2}/replx.egg-info/requires.txt +0 -0
  151. {replx-1.10 → replx-1.10.2}/replx.egg-info/top_level.txt +0 -0
  152. {replx-1.10 → replx-1.10.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: replx
3
- Version: 1.10
3
+ Version: 1.10.2
4
4
  Summary: replx is a fast, modern MicroPython CLI: turbo REPL, robust file sync (put/get), project install, mpy-cross integration, and smart port discovery.
5
5
  Author-email: "chanmin.park" <devcamp@gmail.com>
6
6
  License-Expression: MIT
@@ -1,5 +1,5 @@
1
1
  __all__ = ["__version__", "get_version", "__description__"]
2
- __version__ = "1.10"
2
+ __version__ = "1.10.2"
3
3
  __description__ = "Fast, modern MicroPython CLI with REPL, file sync, install, and smart port detection."
4
4
  __author__ = "PlanX Lab Development Team"
5
5
 
@@ -35,6 +35,44 @@ class AgentClient:
35
35
  self.sock.close()
36
36
  self.sock = None
37
37
 
38
+ def _release_device_port_safe(self) -> None:
39
+ """Best-effort release of the bound device port on the agent.
40
+
41
+ Used when the client detects the device is unresponsive (e.g. cable
42
+ unplugged, board hung) so that subsequent commands won't operate on
43
+ a stale serial connection that the agent still believes is active.
44
+ """
45
+ if not self.device_port:
46
+ return
47
+ try:
48
+ request = AgentProtocol.create_request(
49
+ 'disconnect_port',
50
+ ppid=self._ppid,
51
+ port=self.device_port,
52
+ )
53
+ data = AgentProtocol.encode_message(request)
54
+ try:
55
+ self.sock.sendto(data, (AGENT_HOST, self.agent_port))
56
+ except Exception:
57
+ return
58
+ # Drain any matching response briefly; ignore errors.
59
+ deadline = time.time() + 1.0
60
+ seq = request.get('seq')
61
+ try:
62
+ self.sock.settimeout(0.2)
63
+ except Exception:
64
+ pass
65
+ while time.time() < deadline:
66
+ try:
67
+ pkt, _ = self.sock.recvfrom(MAX_UDP_SIZE)
68
+ msg = AgentProtocol.decode_message(pkt)
69
+ if msg and msg.get('seq') == seq and msg.get('type') == 'response':
70
+ break
71
+ except Exception:
72
+ break
73
+ except Exception:
74
+ pass
75
+
38
76
  def send_command(self, command: str, timeout: float = None, max_retries: int = None, **args) -> Dict[str, Any]:
39
77
  if not self.sock:
40
78
  self.connect()
@@ -236,6 +274,9 @@ class AgentClient:
236
274
 
237
275
  # Check for stream reception timeout (connection loss detection)
238
276
  if now - last_stream_time > stream_timeout:
277
+ # Release the device port on the agent so subsequent
278
+ # commands don't operate on a stale serial connection.
279
+ self._release_device_port_safe()
239
280
  raise RuntimeError("Connection lost - no data from board for {}s".format(stream_timeout))
240
281
 
241
282
  if now - last_input_time >= input_interval:
@@ -807,12 +807,31 @@ def _wifi_scan(client: AgentClient):
807
807
  code = '''
808
808
  import network
809
809
  import json
810
+ import utime
810
811
 
811
812
  wlan = network.WLAN(network.STA_IF)
812
813
  was_active = wlan.active()
813
- wlan.active(True)
814
+ if not was_active:
815
+ wlan.active(True)
816
+ utime.sleep_ms(300)
817
+ else:
818
+ # Already active: wait until driver is no longer in connecting state
819
+ for _ in range(30):
820
+ if wlan.status() != 1:
821
+ break
822
+ utime.sleep_ms(100)
823
+
824
+ # Retry scan up to 3 times (CYW43 may fail when driver is transitioning)
825
+ aps = None
826
+ for _attempt in range(3):
827
+ try:
828
+ aps = wlan.scan()
829
+ break
830
+ except OSError:
831
+ utime.sleep_ms(500)
832
+ if aps is None:
833
+ aps = []
814
834
 
815
- aps = wlan.scan()
816
835
  results = []
817
836
  for ap in aps:
818
837
  ssid, bssid, channel, rssi, auth, hidden = ap
@@ -43,11 +43,7 @@ class UpdateChecker:
43
43
  return tuple(int(p) for p in parts) or (0,)
44
44
 
45
45
  def _is_newer(latest: str, current: str) -> bool:
46
- try:
47
- from packaging.version import Version
48
- return Version(str(latest)) > Version(str(current))
49
- except Exception:
50
- return _vt(latest) > _vt(current)
46
+ return _vt(latest) > _vt(current)
51
47
 
52
48
  try:
53
49
  with urllib.request.urlopen("https://pypi.org/pypi/replx/json", timeout=3) as resp:
@@ -56,8 +52,9 @@ class UpdateChecker:
56
52
 
57
53
  if _is_newer(latest_version, current_version):
58
54
  if UpdateChecker.is_interactive_tty():
59
- print(f"\n[bright_yellow]New version available: {latest_version}[/bright_yellow]")
60
- print("Run: [bright_blue]pip install --upgrade replx[/bright_blue]\n")
55
+ from .output import OutputHelper
56
+ OutputHelper._console.print(f"\n[bright_yellow]New version available: {latest_version}[/bright_yellow]")
57
+ OutputHelper._console.print("Run: [bright_blue]pip install --upgrade replx[/bright_blue]\n")
61
58
  except Exception:
62
59
  pass
63
60
  finally:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: replx
3
- Version: 1.10
3
+ Version: 1.10.2
4
4
  Summary: replx is a fast, modern MicroPython CLI: turbo REPL, robust file sync (put/get), project install, mpy-cross integration, and smart port discovery.
5
5
  Author-email: "chanmin.park" <devcamp@gmail.com>
6
6
  License-Expression: MIT
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