urkit 0.4.3__tar.gz → 0.4.4__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.
- {urkit-0.4.3 → urkit-0.4.4}/PKG-INFO +1 -1
- {urkit-0.4.3 → urkit-0.4.4}/pyproject.toml +1 -1
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/__init__.py +1 -1
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/teach.py +2 -4
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/terminal.py +56 -36
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit.egg-info/PKG-INFO +1 -1
- {urkit-0.4.3 → urkit-0.4.4}/README.md +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/setup.cfg +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/__main__.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/__init__.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/colors.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/connection_monitor.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/init.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/cli/points.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/config.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/connection.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/exceptions.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/geometry.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/gripper/__init__.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/gripper/base.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/gripper/digital.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/gripper/presets.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/gripper/robotiq.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/gripper/robotiq_preamble.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/io.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/motion.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/points.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/robot.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit/telemetry.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit.egg-info/SOURCES.txt +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit.egg-info/dependency_links.txt +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit.egg-info/entry_points.txt +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit.egg-info/requires.txt +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/src/urkit.egg-info/top_level.txt +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_exceptions.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_geometry.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_gripper.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_gripper_factory.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_gripper_presets.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_move_sequence.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_points.py +0 -0
- {urkit-0.4.3 → urkit-0.4.4}/tests/test_robot_integration.py +0 -0
|
@@ -442,13 +442,11 @@ def _draw_help() -> None:
|
|
|
442
442
|
|
|
443
443
|
# Raw terminal shared by the main loop, the SIGINT handler, and the
|
|
444
444
|
# exit path. All terminal setup goes through the cross-platform shim.
|
|
445
|
-
|
|
446
|
-
# (echo on, canonical off); submenus and prompts use echo=False.
|
|
447
|
-
_raw_terminal = RawTerminal(echo=True)
|
|
445
|
+
_raw_terminal = RawTerminal()
|
|
448
446
|
|
|
449
447
|
|
|
450
448
|
def _configure_terminal() -> None:
|
|
451
|
-
"""Enter raw terminal mode (no canonical, echo
|
|
449
|
+
"""Enter raw terminal mode (no canonical, no echo)."""
|
|
452
450
|
_raw_terminal.enable()
|
|
453
451
|
|
|
454
452
|
|
|
@@ -9,8 +9,8 @@ The CLIs need three things from the platform:
|
|
|
9
9
|
3. On Windows only: ANSI escape processing on stdout so colors and
|
|
10
10
|
cursor codes render.
|
|
11
11
|
|
|
12
|
-
Unix backend: termios +
|
|
13
|
-
|
|
12
|
+
Unix backend: termios + select, the same syscalls the CLIs used to
|
|
13
|
+
issue directly.
|
|
14
14
|
|
|
15
15
|
Windows backend: msvcrt with console input mode changed via kernel32.
|
|
16
16
|
The console does not emit ANSI sequences for special keys, so the
|
|
@@ -38,7 +38,6 @@ if sys.platform == "win32":
|
|
|
38
38
|
else:
|
|
39
39
|
import select
|
|
40
40
|
import termios
|
|
41
|
-
import tty
|
|
42
41
|
|
|
43
42
|
if sys.platform == "win32":
|
|
44
43
|
# CDLL is used instead of WinDLL because ctypes.WinDLL is only
|
|
@@ -78,18 +77,35 @@ if sys.platform == "win32":
|
|
|
78
77
|
0x53: "\x1b[3~", # Delete
|
|
79
78
|
}
|
|
80
79
|
|
|
80
|
+
_WIN_ERROR_TEXT = {
|
|
81
|
+
5: "access denied",
|
|
82
|
+
6: "invalid handle",
|
|
83
|
+
87: "invalid parameter",
|
|
84
|
+
1225: "session disconnected",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
def _win_error_detail() -> str:
|
|
88
|
+
code = ctypes.get_last_error()
|
|
89
|
+
return f"Win32 error {code} ({_WIN_ERROR_TEXT.get(code, 'unknown')})"
|
|
90
|
+
|
|
81
91
|
def _console_mode(handle: int) -> int:
|
|
82
92
|
mode = ctypes.c_uint32()
|
|
83
93
|
if not _kernel32.GetConsoleMode(handle, ctypes.byref(mode)):
|
|
84
94
|
raise OSError(
|
|
85
|
-
"GetConsoleMode failed (stdin is
|
|
86
|
-
"
|
|
95
|
+
f"GetConsoleMode failed ({_win_error_detail()}). stdin is "
|
|
96
|
+
"not a usable console handle; run urkit from an "
|
|
97
|
+
"interactive shell such as cmd or PowerShell."
|
|
87
98
|
)
|
|
88
99
|
return mode.value
|
|
89
100
|
|
|
90
|
-
def _set_console_mode(handle: int, mode: int) -> None:
|
|
101
|
+
def _set_console_mode(handle: int, mode: int, context: str) -> None:
|
|
91
102
|
if not _kernel32.SetConsoleMode(handle, mode):
|
|
92
|
-
raise OSError(
|
|
103
|
+
raise OSError(
|
|
104
|
+
f"SetConsoleMode failed while {context} "
|
|
105
|
+
f"({_win_error_detail()}, requested mode "
|
|
106
|
+
f"0x{mode:08x}). The Windows console refused the "
|
|
107
|
+
"terminal mode change."
|
|
108
|
+
)
|
|
93
109
|
|
|
94
110
|
def _enable_ansi_output() -> None:
|
|
95
111
|
"""Enable ANSI escape processing on stdout.
|
|
@@ -102,7 +118,9 @@ if sys.platform == "win32":
|
|
|
102
118
|
handle = _kernel32.GetStdHandle(_STD_OUTPUT_HANDLE)
|
|
103
119
|
mode = _console_mode(handle)
|
|
104
120
|
_set_console_mode(
|
|
105
|
-
handle,
|
|
121
|
+
handle,
|
|
122
|
+
mode | _ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
|
123
|
+
"enabling ANSI output",
|
|
106
124
|
)
|
|
107
125
|
except OSError:
|
|
108
126
|
pass
|
|
@@ -136,15 +154,7 @@ class RawTerminal:
|
|
|
136
154
|
raw.disable() # idempotent, safe to call multiple times
|
|
137
155
|
"""
|
|
138
156
|
|
|
139
|
-
def __init__(self
|
|
140
|
-
"""Args:
|
|
141
|
-
echo: Keep terminal echo enabled (cbreak semantics).
|
|
142
|
-
The main teach loop uses echo=True to match the
|
|
143
|
-
pre-shim behavior; menus and input prompts use the
|
|
144
|
-
default echo=False because they display characters
|
|
145
|
-
themselves.
|
|
146
|
-
"""
|
|
147
|
-
self._echo = echo
|
|
157
|
+
def __init__(self) -> None:
|
|
148
158
|
self._enabled = False
|
|
149
159
|
self._old_settings: list[Any] | None = None
|
|
150
160
|
self._old_mode: int | None = None
|
|
@@ -156,29 +166,37 @@ class RawTerminal:
|
|
|
156
166
|
return
|
|
157
167
|
if sys.platform == "win32":
|
|
158
168
|
self._stdin_handle = _kernel32.GetStdHandle(_STD_INPUT_HANDLE)
|
|
169
|
+
if not self._stdin_handle:
|
|
170
|
+
raise OSError(
|
|
171
|
+
"stdin is not attached to a Windows console; run "
|
|
172
|
+
"urkit from an interactive shell such as cmd or "
|
|
173
|
+
"PowerShell."
|
|
174
|
+
)
|
|
159
175
|
self._old_mode = _console_mode(self._stdin_handle)
|
|
160
|
-
# Disable processed input
|
|
161
|
-
# as raw byte 0x03 (handled by the CLIs) instead
|
|
162
|
-
# KeyboardInterrupt, which would skip terminal restore.
|
|
163
|
-
# Echo is
|
|
164
|
-
|
|
165
|
-
|
|
176
|
+
# Disable processed input, line input, and echo. Ctrl+C
|
|
177
|
+
# arrives as raw byte 0x03 (handled by the CLIs) instead
|
|
178
|
+
# of KeyboardInterrupt, which would skip terminal restore.
|
|
179
|
+
# Echo is always off: some consoles refuse raw mode with
|
|
180
|
+
# echo still enabled, and the CLIs render input themselves.
|
|
181
|
+
_set_console_mode(
|
|
182
|
+
self._stdin_handle,
|
|
183
|
+
self._old_mode
|
|
184
|
+
& ~(
|
|
185
|
+
_ENABLE_PROCESSED_INPUT
|
|
186
|
+
| _ENABLE_LINE_INPUT
|
|
187
|
+
| _ENABLE_ECHO_INPUT
|
|
188
|
+
),
|
|
189
|
+
"entering raw mode",
|
|
166
190
|
)
|
|
167
|
-
if not self._echo:
|
|
168
|
-
mode &= ~_ENABLE_ECHO_INPUT
|
|
169
|
-
_set_console_mode(self._stdin_handle, mode)
|
|
170
191
|
_enable_ansi_output()
|
|
171
192
|
else:
|
|
172
193
|
self._old_settings = termios.tcgetattr(sys.stdin)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
settings = termios.tcgetattr(sys.stdin)
|
|
180
|
-
settings[3] = settings[3] & ~(termios.ICANON | termios.ECHO)
|
|
181
|
-
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
|
|
194
|
+
# No canonical mode, no echo; ISIG stays on so Ctrl+C
|
|
195
|
+
# still raises KeyboardInterrupt. Same state as the
|
|
196
|
+
# pre-shim menus and input prompts.
|
|
197
|
+
settings = termios.tcgetattr(sys.stdin)
|
|
198
|
+
settings[3] = settings[3] & ~(termios.ICANON | termios.ECHO)
|
|
199
|
+
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
|
|
182
200
|
self._enabled = True
|
|
183
201
|
|
|
184
202
|
def disable(self) -> None:
|
|
@@ -188,7 +206,9 @@ class RawTerminal:
|
|
|
188
206
|
if sys.platform == "win32":
|
|
189
207
|
if self._stdin_handle is None or self._old_mode is None:
|
|
190
208
|
raise RuntimeError("RawTerminal disabled before enable()")
|
|
191
|
-
_set_console_mode(
|
|
209
|
+
_set_console_mode(
|
|
210
|
+
self._stdin_handle, self._old_mode, "restoring terminal"
|
|
211
|
+
)
|
|
192
212
|
else:
|
|
193
213
|
if self._old_settings is None:
|
|
194
214
|
raise RuntimeError("RawTerminal disabled before enable()")
|
|
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
|