tools/pyboard.py: Add filesystem commands to ls/cat/cp/rm remote files.
Use "-f" to select filesystem mode, followed by the command to execute. Optionally put ":" at the start of a filename to indicate that it's on the remote device, if it would otherwise be ambiguous. Examples: $ pyboard.py -f ls $ pyboard.py -f cat main.py $ pyboard.py -f cp :main.py . # get from device $ pyboard.py -f cp main.py : # put to device $ pyboard.py -f rm main.py
This commit is contained in:
parent
995f9cfdfc
commit
4d94fae833
110
tools/pyboard.py
110
tools/pyboard.py
@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# The MIT License (MIT)
|
# The MIT License (MIT)
|
||||||
#
|
#
|
||||||
# Copyright (c) 2014-2016 Damien P. George
|
# Copyright (c) 2014-2019 Damien P. George
|
||||||
# Copyright (c) 2017 Paul Sokolovsky
|
# Copyright (c) 2017 Paul Sokolovsky
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -363,8 +363,8 @@ class Pyboard:
|
|||||||
ret = ret.strip()
|
ret = ret.strip()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def exec_(self, command):
|
def exec_(self, command, data_consumer=None):
|
||||||
ret, ret_err = self.exec_raw(command)
|
ret, ret_err = self.exec_raw(command, data_consumer=data_consumer)
|
||||||
if ret_err:
|
if ret_err:
|
||||||
raise PyboardError('exception', ret, ret_err)
|
raise PyboardError('exception', ret, ret_err)
|
||||||
return ret
|
return ret
|
||||||
@ -378,6 +378,52 @@ class Pyboard:
|
|||||||
t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ')
|
t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ')
|
||||||
return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6])
|
return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6])
|
||||||
|
|
||||||
|
def fs_ls(self, src):
|
||||||
|
cmd = "import uos\nfor f in uos.ilistdir(%s):\n" \
|
||||||
|
" print('{:12} {}{}'.format(f[3]if len(f)>3 else 0,f[0],'/'if f[1]&0x4000 else ''))" % \
|
||||||
|
(("'%s'" % src) if src else '')
|
||||||
|
self.exec_(cmd, data_consumer=stdout_write_bytes)
|
||||||
|
|
||||||
|
def fs_cat(self, src, chunk_size=256):
|
||||||
|
cmd = "with open('%s') as f:\n while 1:\n" \
|
||||||
|
" b=f.read(%u)\n if not b:break\n print(b,end='')" % (src, chunk_size)
|
||||||
|
self.exec_(cmd, data_consumer=stdout_write_bytes)
|
||||||
|
|
||||||
|
def fs_get(self, src, dest, chunk_size=256):
|
||||||
|
self.exec_("f=open('%s','rb')\nr=f.read" % src)
|
||||||
|
with open(dest, 'wb') as f:
|
||||||
|
while True:
|
||||||
|
data = bytearray()
|
||||||
|
self.exec_("print(r(%u))" % chunk_size, data_consumer=lambda d:data.extend(d))
|
||||||
|
assert data.endswith(b'\r\n\x04')
|
||||||
|
data = eval(str(data[:-3], 'ascii'))
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
f.write(data)
|
||||||
|
self.exec_("f.close()")
|
||||||
|
|
||||||
|
def fs_put(self, src, dest, chunk_size=256):
|
||||||
|
self.exec_("f=open('%s','wb')\nw=f.write" % dest)
|
||||||
|
with open(src, 'rb') as f:
|
||||||
|
while True:
|
||||||
|
data = f.read(chunk_size)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
if sys.version_info < (3,):
|
||||||
|
self.exec_('w(b' + repr(data) + ')')
|
||||||
|
else:
|
||||||
|
self.exec_('w(' + repr(data) + ')')
|
||||||
|
self.exec_("f.close()")
|
||||||
|
|
||||||
|
def fs_mkdir(self, dir):
|
||||||
|
self.exec_("import uos\nuos.mkdir('%s')" % dir)
|
||||||
|
|
||||||
|
def fs_rmdir(self, dir):
|
||||||
|
self.exec_("import uos\nuos.rmdir('%s')" % dir)
|
||||||
|
|
||||||
|
def fs_rm(self, src):
|
||||||
|
self.exec_("import uos\nuos.remove('%s')" % src)
|
||||||
|
|
||||||
# in Python2 exec is a keyword so one must use "exec_"
|
# in Python2 exec is a keyword so one must use "exec_"
|
||||||
# but for Python3 we want to provide the nicer version "exec"
|
# but for Python3 we want to provide the nicer version "exec"
|
||||||
setattr(Pyboard, "exec", Pyboard.exec_)
|
setattr(Pyboard, "exec", Pyboard.exec_)
|
||||||
@ -390,6 +436,54 @@ def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', pas
|
|||||||
pyb.exit_raw_repl()
|
pyb.exit_raw_repl()
|
||||||
pyb.close()
|
pyb.close()
|
||||||
|
|
||||||
|
def filesystem_command(pyb, args):
|
||||||
|
def fname_remote(src):
|
||||||
|
if src.startswith(':'):
|
||||||
|
src = src[1:]
|
||||||
|
return src
|
||||||
|
def fname_cp_dest(src, dest):
|
||||||
|
src = src.rsplit('/', 1)[-1]
|
||||||
|
if dest is None or dest == '':
|
||||||
|
dest = src
|
||||||
|
elif dest == '.':
|
||||||
|
dest = './' + src
|
||||||
|
elif dest.endswith('/'):
|
||||||
|
dest += src
|
||||||
|
return dest
|
||||||
|
|
||||||
|
cmd = args[0]
|
||||||
|
args = args[1:]
|
||||||
|
try:
|
||||||
|
if cmd == 'cp':
|
||||||
|
srcs = args[:-1]
|
||||||
|
dest = args[-1]
|
||||||
|
if srcs[0].startswith('./') or dest.startswith(':'):
|
||||||
|
op = pyb.fs_put
|
||||||
|
fmt = 'cp %s :%s'
|
||||||
|
dest = fname_remote(dest)
|
||||||
|
else:
|
||||||
|
op = pyb.fs_get
|
||||||
|
fmt = 'cp :%s %s'
|
||||||
|
for src in srcs:
|
||||||
|
src = fname_remote(src)
|
||||||
|
dest2 = fname_cp_dest(src, dest)
|
||||||
|
print(fmt % (src, dest2))
|
||||||
|
op(src, dest2)
|
||||||
|
else:
|
||||||
|
op = {'ls': pyb.fs_ls, 'cat': pyb.fs_cat, 'mkdir': pyb.fs_mkdir,
|
||||||
|
'rmdir': pyb.fs_rmdir, 'rm': pyb.fs_rm}[cmd]
|
||||||
|
if cmd == 'ls' and not args:
|
||||||
|
args = ['']
|
||||||
|
for src in args:
|
||||||
|
src = fname_remote(src)
|
||||||
|
print('%s :%s' % (cmd, src))
|
||||||
|
op(src)
|
||||||
|
except PyboardError as er:
|
||||||
|
print(str(er.args[2], 'ascii'))
|
||||||
|
pyb.exit_raw_repl()
|
||||||
|
pyb.close()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import argparse
|
import argparse
|
||||||
cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')
|
cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')
|
||||||
@ -400,6 +494,7 @@ def main():
|
|||||||
cmd_parser.add_argument('-c', '--command', help='program passed in as string')
|
cmd_parser.add_argument('-c', '--command', help='program passed in as string')
|
||||||
cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available')
|
cmd_parser.add_argument('-w', '--wait', default=0, type=int, help='seconds to wait for USB connected board to become available')
|
||||||
cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]')
|
cmd_parser.add_argument('--follow', action='store_true', help='follow the output after running the scripts [default if no scripts given]')
|
||||||
|
cmd_parser.add_argument('-f', '--filesystem', action='store_true', help='perform a filesystem action')
|
||||||
cmd_parser.add_argument('files', nargs='*', help='input files')
|
cmd_parser.add_argument('files', nargs='*', help='input files')
|
||||||
args = cmd_parser.parse_args()
|
args = cmd_parser.parse_args()
|
||||||
|
|
||||||
@ -411,7 +506,7 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# run any command or file(s)
|
# run any command or file(s)
|
||||||
if args.command is not None or len(args.files):
|
if args.command is not None or args.filesystem or len(args.files):
|
||||||
# we must enter raw-REPL mode to execute commands
|
# we must enter raw-REPL mode to execute commands
|
||||||
# this will do a soft-reset of the board
|
# this will do a soft-reset of the board
|
||||||
try:
|
try:
|
||||||
@ -436,6 +531,11 @@ def main():
|
|||||||
stdout_write_bytes(ret_err)
|
stdout_write_bytes(ret_err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# do filesystem commands, if given
|
||||||
|
if args.filesystem:
|
||||||
|
filesystem_command(pyb, args.files)
|
||||||
|
args.files.clear()
|
||||||
|
|
||||||
# run the command, if given
|
# run the command, if given
|
||||||
if args.command is not None:
|
if args.command is not None:
|
||||||
execbuffer(args.command.encode('utf-8'))
|
execbuffer(args.command.encode('utf-8'))
|
||||||
@ -450,7 +550,7 @@ def main():
|
|||||||
pyb.exit_raw_repl()
|
pyb.exit_raw_repl()
|
||||||
|
|
||||||
# if asked explicitly, or no files given, then follow the output
|
# if asked explicitly, or no files given, then follow the output
|
||||||
if args.follow or (args.command is None and len(args.files) == 0):
|
if args.follow or (args.command is None and not args.filesystem and len(args.files) == 0):
|
||||||
try:
|
try:
|
||||||
ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes)
|
ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes)
|
||||||
except PyboardError as er:
|
except PyboardError as er:
|
||||||
|
Loading…
Reference in New Issue
Block a user