PyOpenocdClient 0.1.1__tar.gz → 0.1.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.
- {pyopenocdclient-0.1.1/src/PyOpenocdClient.egg-info → pyopenocdclient-0.1.2}/PKG-INFO +1 -1
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/pyproject.toml +1 -1
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2/src/PyOpenocdClient.egg-info}/PKG-INFO +1 -1
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/baseclient.py +57 -7
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/client.py +19 -10
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/LICENSE +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/README.md +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/setup.cfg +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/PyOpenocdClient.egg-info/SOURCES.txt +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/PyOpenocdClient.egg-info/dependency_links.txt +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/PyOpenocdClient.egg-info/top_level.txt +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/__init__.py +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/bp_parser.py +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/errors.py +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/types.py +0 -0
- {pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/py_openocd_client/wp_parser.py +0 -0
|
@@ -94,10 +94,35 @@ class _PyOpenocdBaseClient:
|
|
|
94
94
|
raise ValueError("Timeout must be greater than zero")
|
|
95
95
|
self._default_recv_timeout = timeout
|
|
96
96
|
|
|
97
|
-
def
|
|
97
|
+
def _check_connection_before_command(self) -> None:
|
|
98
98
|
assert self._socket is not None
|
|
99
99
|
rd, _, _ = select.select([self._socket], [], [], 0) # Don't block, just poll
|
|
100
|
-
|
|
100
|
+
|
|
101
|
+
if len(rd) == 0:
|
|
102
|
+
# The socket is not ready for recv() now, which is the expected state.
|
|
103
|
+
# Success.
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
# The socket is ready for recv(). This is unexpected at this point
|
|
107
|
+
# and always means an error. Try receive from the socket to find out
|
|
108
|
+
# what happened:
|
|
109
|
+
try:
|
|
110
|
+
recvd_data = self._socket.recv(128)
|
|
111
|
+
except OSError as e:
|
|
112
|
+
# This is unlikely to happen: It would mean that the socket is ready
|
|
113
|
+
# for recv() but then recv() failed.
|
|
114
|
+
raise OcdConnectionError(
|
|
115
|
+
"Connection to OpenOCD broken for an unknown reason"
|
|
116
|
+
) from e
|
|
117
|
+
|
|
118
|
+
if len(recvd_data) == 0:
|
|
119
|
+
# Empty received data means that the connection got closed by OpenOCD
|
|
120
|
+
# in the meanwhile.
|
|
121
|
+
raise OcdConnectionError("Connection closed by OpenOCD")
|
|
122
|
+
else:
|
|
123
|
+
# It looks like OpenOCD sent us some extra, unsolicited bytes (without us
|
|
124
|
+
# sending any command to OpenOCD). This is a violation of the communication
|
|
125
|
+
# protocol.
|
|
101
126
|
raise OcdConnectionError(
|
|
102
127
|
"Received unexpected bytes from OpenOCD before "
|
|
103
128
|
"the command was even sent."
|
|
@@ -107,12 +132,27 @@ class _PyOpenocdBaseClient:
|
|
|
107
132
|
assert self.is_connected()
|
|
108
133
|
assert self._socket is not None
|
|
109
134
|
|
|
110
|
-
#
|
|
111
|
-
|
|
135
|
+
# Perform basic connection check before sending a command.
|
|
136
|
+
# Note that this is merely a safety/correctness check which itself
|
|
137
|
+
# does not guarantee that the subsequent send() and recv() calls
|
|
138
|
+
# will succeed.
|
|
139
|
+
self._check_connection_before_command()
|
|
112
140
|
|
|
113
141
|
data = raw_cmd.encode(self.CHARSET) + self.COMMAND_DELIMITER
|
|
114
|
-
|
|
115
|
-
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
self._socket.settimeout(self.SEND_TIMEOUT)
|
|
145
|
+
except OSError as e:
|
|
146
|
+
raise OcdConnectionError(
|
|
147
|
+
"Could not send a command to OpenOCD, failed to set socket timeout"
|
|
148
|
+
) from e
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
self._socket.send(data)
|
|
152
|
+
except OSError as e:
|
|
153
|
+
raise OcdConnectionError(
|
|
154
|
+
"Could not send a command to OpenOCD, socket error occurred"
|
|
155
|
+
) from e
|
|
116
156
|
|
|
117
157
|
def _do_recv_response(self, raw_cmd: str, timeout: Optional[float] = None) -> str:
|
|
118
158
|
assert self.is_connected()
|
|
@@ -123,7 +163,13 @@ class _PyOpenocdBaseClient:
|
|
|
123
163
|
timeout if timeout is not None else self._default_recv_timeout
|
|
124
164
|
)
|
|
125
165
|
|
|
126
|
-
|
|
166
|
+
try:
|
|
167
|
+
self._socket.settimeout(self.RECV_POLL_TIMEOUT)
|
|
168
|
+
except OSError as e:
|
|
169
|
+
raise OcdConnectionError(
|
|
170
|
+
"Could not receive a response from OpenOCD, "
|
|
171
|
+
"failed to set socket timeout"
|
|
172
|
+
) from e
|
|
127
173
|
|
|
128
174
|
time_start = time.time()
|
|
129
175
|
while time.time() < (time_start + effective_timeout):
|
|
@@ -131,6 +177,10 @@ class _PyOpenocdBaseClient:
|
|
|
131
177
|
d = self._socket.recv(self.RECV_BLOCK_SIZE)
|
|
132
178
|
except socket.timeout:
|
|
133
179
|
continue
|
|
180
|
+
except OSError as e:
|
|
181
|
+
raise OcdConnectionError(
|
|
182
|
+
"Could not receive a response from OpenOCD, socket error occurred"
|
|
183
|
+
) from e
|
|
134
184
|
|
|
135
185
|
if d == b"":
|
|
136
186
|
raise OcdConnectionError("Connection closed by OpenOCD")
|
|
@@ -211,25 +211,34 @@ class PyOpenocdClient:
|
|
|
211
211
|
raw_cmd = cmd
|
|
212
212
|
|
|
213
213
|
raw_cmd = "set CMD_RETCODE [ catch { " + raw_cmd + " } CMD_OUTPUT ] ; "
|
|
214
|
-
|
|
214
|
+
|
|
215
|
+
# Older OpenOCD versions - prior to 93f16eed4(*) - incorrectly trimmed trailing
|
|
216
|
+
# whitespace from the string passed to the return command. Work around this bug
|
|
217
|
+
# by wrapping the string by non-whitespace characters.
|
|
218
|
+
# (*): https://review.openocd.org/c/openocd/+/9084
|
|
219
|
+
raw_cmd += 'return "<$CMD_RETCODE,$CMD_OUTPUT>" ; '
|
|
215
220
|
|
|
216
221
|
raw_result = self.raw_cmd(raw_cmd, timeout=timeout)
|
|
217
222
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
def is_expected_raw_result(s: str) -> bool:
|
|
224
|
+
return (
|
|
225
|
+
s.startswith("<")
|
|
226
|
+
and s.endswith(">")
|
|
227
|
+
and re.match(r"^<-?\d+,", s) is not None
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if not is_expected_raw_result(raw_result):
|
|
225
231
|
msg = (
|
|
226
232
|
"Received unexpected response from OpenOCD. "
|
|
227
233
|
"It looks like OpenOCD misbehaves. "
|
|
228
234
|
)
|
|
229
235
|
raise OcdInvalidResponseError(msg, raw_cmd, raw_result)
|
|
230
236
|
|
|
231
|
-
|
|
232
|
-
|
|
237
|
+
# Remove leading "<" and trailing ">"
|
|
238
|
+
raw_result = raw_result[1:-1]
|
|
239
|
+
raw_result_parts = raw_result.split(",", maxsplit=1)
|
|
240
|
+
assert len(raw_result_parts) == 2
|
|
241
|
+
|
|
233
242
|
retcode = int(raw_result_parts[0], 10)
|
|
234
243
|
out = raw_result_parts[1] if len(raw_result_parts) == 2 else ""
|
|
235
244
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyopenocdclient-0.1.1 → pyopenocdclient-0.1.2}/src/PyOpenocdClient.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|