8000 tools/mpremote: Improve error output. · anight/micropython@dd6f78f · GitHub
[go: up one dir, main page]

Skip to content

Commit dd6f78f

Browse files
jimmodpgeorge
authored andcommitted
tools/mpremote: Improve error output.
Makes the filesystem command give standard error messages rather than just printing the exception from the device. Makes the distinction between CommandError and TransportError clearer. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 6f8157d commit dd6f78f

File tree

3 files changed

+71
-56
lines changed

3 files changed

+71
-56
lines changed

tools/mpremote/mpremote/commands.py

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ def do_connect(state, args=None):
6363
msg = er.args[0]
6464
if msg.startswith("failed to access"):
6565
msg += " (it may be in use by another program)"
66-
print(msg)
67-
sys.exit(1)
66+
raise CommandError(msg)
6867

6968

7069
def do_disconnect(state, _args=None):
@@ -322,47 +321,56 @@ def do_filesystem(state, args):
322321
if command == "ls" and not paths:
323322
paths = [""]
324323

325-
# Handle each path sequentially.
326-
for path in paths:
327-
if verbose:
328-
if command == "cp":
329-
print("{} {} {}".format(command, path, cp_dest))
330-
else:
331-
print("{} :{}".format(command, path))
332-
333-
if command == "cat":
334-
state.transport.fs_printfile(path)
335-
elif command == "ls":
336-
for result in state.transport.fs_listdir(path):
337-
print(
338-
"{:12} {}{}".format(
339-
result.st_size, result.name, "/" if result.st_mode & 0x4000 else ""
324+
try:
325+
# Handle each path sequentially.
326+
for path in paths:
327+
if verbose:
328+
if command == "cp":
329+
print("{} {} {}".format(command, path, cp_dest))
330+
else:
331+
print("{} :{}".format(command, path))
332+
333+
if command == "cat":
334+
state.transport.fs_printfile(path)
335+
elif command == "ls":
336+
for result in state.transport.fs_listdir(path):
337+
print(
338+
"{:12} {}{}".format(
339+
result.st_size, result.name, "/" if result.st_mode & 0x4000 else ""
340+
)
340341
)
341-
)
342-
elif command == "mkdir":
343-
state.transport.fs_mkdir(path)
344-
elif command == "rm":
345-
state.transport.fs_rmfile(path)
346-
elif command == "rmdir":
347-
state.transport.fs_rmdir(path)
348-
elif command == "touch":
349-
state.transport.fs_touchfile(path)
350-
elif command.endswith("sum") and command[-4].isdigit():
351-
digest = state.transport.fs_hashfile(path, command[:-3])
352-
print(digest.hex())
353-
elif command == "cp":
354-
if args.recursive:
355-
do_filesystem_recursive_cp(state, path, cp_dest, len(paths) > 1)
356-
else:
357-
do_filesystem_cp(state, path, cp_dest, len(paths) > 1)
342+
elif command == "mkdir":
343+
state.transport.fs_mkdir(path)
344+
elif command == "rm":
345+
state.transport.fs_rmfile(path)
346+
elif command == "rmdir":
347+
state.transport.fs_rmdir(path)
348+
elif command == "touch":
349+
state.transport.fs_touchfile(path)
350+
elif command.endswith("sum") and command[-4].isdigit():
351+
digest = state.transport.fs_hashfile(path, command[:-3])
352+
print(digest.hex())
353+
elif command == "cp":
354+
if args.recursive:
355+
do_filesystem_recursive_cp(state, path, cp_dest, len(paths) > 1)
356+
else:
357+
do_filesystem_cp(state, path, cp_dest, len(paths) > 1)
358+
except FileNotFoundError as er:
359+
raise CommandError("{}: {}: No such file or directory.".format(command, er.args[0]))
360+
except IsADirectoryError as er:
361+
raise CommandError("{}: {}: Is a directory.".format(command, er.args[0]))
362+
except FileExistsError as er:
363+
raise CommandError("{}: {}: File exists.".format(command, er.args[0]))
364+
except TransportError as er:
365+
raise CommandError("Error with transport:\n{}".format(er.args[0]))
358366

359367

360368
def do_edit(state, args):
361369
state.ensure_raw_repl()
362370
state.did_action()
363371

364372
if not os.getenv("EDITOR"):
365-
raise TransportError("edit: $EDITOR not set")
373+
raise CommandError("edit: $EDITOR not set")
366374
for src in args.files:
367375
src = src.lstrip(":")
368376
dest_fd, dest = tempfile.mkstemp(suffix=os.path.basename(src))
@@ -393,8 +401,7 @@ def _do_execbuffer(state, buf, follow):
393401
stdout_write_bytes(ret_err)
394402
sys.exit(1)
395403
except TransportError as er:
396-
print(er)
397-
sys.exit(1)
404+
raise CommandError(er.args[0])
398405
except KeyboardInterrupt:
399406
sys.exit(1)
400407

tools/mpremote/mpremote/transport.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,27 @@ class TransportError(Exception):
4242
pass
4343

4444

45+
class TransportExecError(TransportError):
46+
def __init__(self, status_code, error_output):
47+
self.status_code = status_code
48+
self.error_output = error_output
49+
super().__init__(error_output)
50+
51+
4552
listdir_result = namedtuple("dir_result", ["name", "st_mode", "st_ino", "st_size"])
4653

4754

4855
# Takes a Transport error (containing the text of an OSError traceback) and
4956
# raises it as the corresponding OSError-derived exception.
5057
def _convert_filesystem_error(e, info):
51-
if len(e.args) >= 3:
52-
if b"OSError" in e.args[2] and b"ENOENT" in e.args[2]:
53-
return FileNotFoundError(info)
54-
if b"OSError" in e.args[2] and b"EISDIR" in e.args[2]:
55-
return IsADirectoryError(info)
56-
if b"OSError" in e.args[2] and b"EEXIST" in e.args[2]:
57-
return FileExistsError(info)
58+
if "OSError" in e.error_output and "ENOENT" in e.error_output:
59+
return FileNotFoundError(info)
60+
if "OSError" in e.error_output and "EISDIR" in e.error_output:
61+
return IsADirectoryError(info)
62+
if "OSError" in e.error_output and "EEXIST" in e.error_output:
63+
return FileExistsError(info)
64+
if "OSError" in e.error_output and "ENODEV" in e.error_output:
65+
return FileNotFoundError(info)
5866
return e
5967

6068

@@ -72,7 +80,7 @@ def repr_consumer(b):
7280
buf.extend(b"[")
7381
self.exec(cmd, data_consumer=repr_consumer)
7482
buf.extend(b"]")
75-
except TransportError as e:
83+
except TransportExecError as e:
7684
raise _convert_filesystem_error(e, src) from None
7785

7886
return [
@@ -84,7 +92,7 @@ def fs_stat(self, src):
8492
try:
8593
self.exec("import os")
8694
return os.stat_result(self.eval("os.stat(%s)" % ("'%s'" % src)))
87-
except TransportError as e:
95+
except TransportExecError as e:
8896
raise _convert_filesystem_error(e, src) from None
8997

9098
def fs_exists(self, src):
@@ -109,7 +117,7 @@ def fs_printfile(self, src, chunk_size=256):
109117
)
110118
try:
111119
self.exec(cmd, data_consumer=stdout_write_bytes)
112-
except TransportError as e:
120+
except TransportExecError as e:
113121
raise _convert_filesystem_error(e, src) from None
114122

115123
def fs_readfile(self, src, chunk_size=256, progress_callback=None):
@@ -128,7 +136,7 @@ def fs_readfile(self, src, chunk_size=256, progress_callback=None):
128136
if progress_callback:
129137
progress_callback(len(contents), src_size)
130138
self.exec("f.close()")
131-
except TransportError as e:
139+
except TransportExecError as e:
132140
raise _convert_filesystem_error(e, src) from None
133141

134142
return contents
@@ -148,37 +156,37 @@ def fs_writefile(self, dest, data, chunk_size=256, progress_callback=None):
148156
if progress_callback:
149157
progress_callback(written, src_size)
150158
self.exec("f.close()")
151-
except TransportError as e:
159+
except TransportExecError as e:
152160
raise _convert_filesystem_error(e, dest) from None
153161

154162
def fs_mkdir(self, path):
155163
try:
156164
self.exec("import os\nos.mkdir('%s')" % path)
157-
except TransportError as e:
165+
except TransportExecError as e:
158166
raise _convert_filesystem_error(e, path) from None
159167

160168
def fs_rmdir(self, path):
161169
try:
162170
self.exec("import os\nos.rmdir('%s')" % path)
163-
except TransportError as e:
171+
except TransportExecError as e:
164172
raise _convert_filesystem_error(e, path) from None
165173

166174
def fs_rmfile(self, path):
167175
try:
168176
self.exec("import os\nos.remove('%s')" % path)
169-
except TransportError as e:
177+
except TransportExecError as e:
170178
raise _convert_filesystem_error(e, path) from None
171179

172180
def fs_touchfile(self, path):
173181
try:
174182
self.exec("f=open('%s','a')\nf.close()" % path)
175-
except TransportError as e:
183+
except TransportExecError as e:
176184
raise _convert_filesystem_error(e, path) from None
177185

178186
def fs_hashfile(self, path, algo, chunk_size=256):
179187
try:
180188
self.exec("import hashlib\nh = hashlib.{algo}()".format(algo=algo))
181-
except TransportError:
189+
except TransportExecError:
182190
# hashlib (or hashlib.{algo}) not available on device. Do the hash locally.
183191
data = self.fs_readfile(path, chunk_size=chunk_size)
184192
return getattr(hashlib, algo)(data).digest()

tools/mpremote/mpremote/transport_serial.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import ast, io, os, re, struct, sys, time
3939
from errno import EPERM
4040
from .console import VT_ENABLED
41-
from .transport import TransportError, Transport
41+
from .transport import TransportError, TransportExecError, Transport
4242

4343

4444
class SerialTransport(Transport):
@@ -267,7 +267,7 @@ def eval(self, expression, parse=True):
267267
def exec(self, command, data_consumer=None):
268268
ret, ret_err = self.exec_raw(command, data_consumer=data_consumer)
269269
if ret_err:
270-
raise TransportError("exception", ret, ret_err)
270+
raise TransportExecError(ret, ret_err.decode())
271271
return ret
272272

273273
def execfile(self, filename):

0 commit comments

Comments
 (0)
0