Skip to content

tools/pyboard.py: Add filesystem commands to ls/cat/cp/rm remote files. #4917

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 104 additions & 4 deletions tools/pyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,8 @@ def eval(self, expression):
ret = ret.strip()
return ret

def exec_(self, command):
ret, ret_err = self.exec_raw(command)
def exec_(self, command, data_consumer=None):
ret, ret_err = self.exec_raw(command, data_consumer=data_consumer)
if ret_err:
raise PyboardError('exception', ret, ret_err)
return ret
Expand All @@ -378,6 +378,52 @@ def get_time(self):
t = str(self.eval('pyb.RTC().datetime()'), encoding='utf8')[1:-1].split(', ')
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_"
# but for Python3 we want to provide the nicer version "exec"
setattr(Pyboard, "exec", Pyboard.exec_)
Expand All @@ -390,6 +436,54 @@ def execfile(filename, device='/dev/ttyACM0', baudrate=115200, user='micro', pas
pyb.exit_raw_repl()
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():
import argparse
cmd_parser = argparse.ArgumentParser(description='Run scripts on the pyboard.')
Expand All @@ -400,6 +494,7 @@ def main():
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('--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')
args = cmd_parser.parse_args()

Expand All @@ -411,7 +506,7 @@ def main():
sys.exit(1)

# 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
# this will do a soft-reset of the board
try:
Expand All @@ -436,6 +531,11 @@ def execbuffer(buf):
stdout_write_bytes(ret_err)
sys.exit(1)

# do filesystem commands, if given
if args.filesystem:
filesystem_command(pyb, args.files)
args.files.clear()

# run the command, if given
if args.command is not None:
execbuffer(args.command.encode('utf-8'))
Expand All @@ -450,7 +550,7 @@ def execbuffer(buf):
pyb.exit_raw_repl()

# 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:
ret, ret_err = pyb.follow(timeout=None, data_consumer=stdout_write_bytes)
except PyboardError as er:
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy