Example #1
0
def do_version(self, line):
    """version

    Print shell49 and MicroPython version information.
    """
    db = self.boards.default
    release, machine, version = db.remote_eval(upy_version)
    fmt = "{:>10s} = {}"
    oprint(fmt.format("board", db.name))
    oprint(fmt.format("firmware", version))
    oprint(fmt.format("release", release))
    oprint(fmt.format("machine", machine))
    oprint(fmt.format("shell49", __version__))
Example #2
0
 def _load(self):
     qprint("Loading configuration '{}'".format(self._config_file))
     try:
         with open(self._config_file) as f:
             self._config = literal_eval(f.read())
     except FileNotFoundError:
         oprint("WARNING: configuration '{}' does not exist, creating default".format(self._config_file))
         self._create_default()
         self._modified = True
     except SyntaxError as e:
         eprint("Syntax error in {}: {}".format(self._config_file, e))
         eprint("If the problem persists, manually check the file for "
                "invalid Python syntax or delete it and re-enter the configuration information.")
         sys.exit()
Example #3
0
def do_ls(self, line):
    """ls [-a] [-l] [FILE|DIRECTORY|PATTERN]...
   PATTERN supports * ? [seq] [!seq] Unix filename matching

       List directory contents.
    """
    args = self.line_to_args(line)
    if len(args.filenames) == 0:
        args.filenames = ['.']
    for idx, fn in enumerate(args.filenames):
        if not is_pattern(fn):
            filename = resolve_path(self.cur_dir, fn)
            stat = auto(self.boards, get_stat, filename)
            mode = stat_mode(stat)
            if not mode_exists(mode):
                err = "Cannot access '{}': No such file or directory"
                eprint(err.format(filename))
                continue
            if not mode_isdir(mode):
                if args.long:
                    print_long(filename, stat, oprint)
                else:
                    oprint(filename)
                continue
            if len(args.filenames) > 1:
                if idx > 0:
                    oprint('')
                oprint("%s:" % filename)
            pattern = '*'
        else:  # A pattern was specified
            filename, pattern = validate_pattern(self.boards, self.cur_dir, fn)
            if filename is None:  # An error was printed
                continue
        files = []
        ldir_stat = auto(self.boards, listdir_stat, filename)
        if ldir_stat is None:
            err = "Cannot access '{}': No such file or directory"
            eprint(err.format(filename))
        else:
            for filename, stat in sorted(ldir_stat,
                                         key=lambda entry: entry[0]):
                if is_visible(filename) or args.all:
                    if fnmatch(filename, pattern):
                        if args.long:
                            print_long(filename, stat, oprint)
                        else:
                            files.append(decorated_filename(filename, stat))
        if len(files) > 0:
            print_cols(sorted(files), oprint,
                       shutil.get_terminal_size().columns)
Example #4
0
def do_config(self, line):
    """config    Print option values.
       config [-u] [-d] [--default] OPTION [VALUE]
                 Set/delete OPTION to VALUE.
    """
    default_board = None
    board_id = 'default'
    try:
        default_board = self.boards.default
        board_id = default_board.id
    except BoardError:
        pass

    if line == '':
        # print configuration
        print_config(self.config, board_id, color=printing.MPY_COLOR)
        if default_board:
            oprint("Defaults:")
            keys = self.config.options(board_id)
            print_config(self.config, 'default', exc=keys)
        return

    # parse arguments
    args = self.line_to_args(line)
    if args.default:
        board_id = 'default'
        default_board = None
    value = ' '.join(args.value)
    try:
        # try to convert value to Python object (e.g. for numbers)
        value = literal_eval(value)
    except:
        pass
    if not args.default and not default_board:
        eprint(
            "*** No board connected, use --default to change default configuration"
        )
        return

    # delete / set option value
    if args.delete:
        # delete option
        self.config.remove(board_id, args.option)
    else:
        # set option
        try:
            self.config.set(board_id, args.option, value)
        except ConfigError as e:
            eprint("*** {}".format(e))

    # upload
    if args.upload:
        if not default_board:
            eprint("*** No board connected, cannot upload configuration")
            return
        with NamedTemporaryFile() as temp:
            temp.close()
            f = open(temp.name, 'w')
            now = datetime.now().strftime("%Y-%b-%d %H:%M:%S")
            print("# config.py, created on {}".format(now), file=f)
            for key in default_board.config_options():
                print("{} = {}".format(key,
                                       repr(default_board.get_config(key))),
                      file=f)
            print("mac_table = {}".format(repr(self.config.mac_table())),
                  file=f)
            f.close()
            dst = os.path.join(
                default_board.get_config('remote_dir', '/flash'), 'config.py')
            cp(self.boards, temp.name, dst)
            os.unlink(temp.name)
Example #5
0
def print_bytes(byte_str):
    """Prints a string or converts bytes to a string and then prints."""
    if isinstance(byte_str, str):
        oprint(byte_str)
    else:
        oprint(str(byte_str, encoding='utf8'))
Example #6
0
def main():
    """The main program."""

    if sys.version_info.major < 3:
        v = sys.version_info
        eprint("Shell49 requires Python 3.6 (not {}.{}.{})".format(
            v.major, v.minor, v.micro))
        return

    default_config = os.getenv('SHELL49_CONFIG_FILE') or '~/.shell49_rc.py'
    default_editor = os.getenv('SHELL49_EDITOR') or os.getenv(
        'VISUAL') or os.getenv('EDITOR') or 'vi'
    default_nocolor = 'win32' in sys.platform
    default_debug = False
    default_quiet = False

    parser = argparse.ArgumentParser(
        prog="shell49",
        usage="%(prog)s [options] [cmd]",
        description="Remote Shell for MicroPython boards.",
        epilog=("""
Environment variables:
  SHELL49_CONFIG_FILE   configuration file (Default: '{}')
  SHELL49_EDITOR        editor (Default: {})
""".format(default_config, default_editor)),
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument(
        "-c",
        "--config",
        dest="config",
        help="Set path of the configuration file (default: '%s')" %
        default_config,
        default=default_config)
    parser.add_argument("-e",
                        "--editor",
                        dest="editor",
                        help="Set the editor to use (default: '%s')" %
                        default_editor,
                        default=default_editor)
    parser.add_argument("-d",
                        "--debug",
                        dest="debug",
                        action="store_true",
                        help="Enable debug features (default %s)" %
                        default_debug,
                        default=default_debug)
    parser.add_argument("-n",
                        "--nocolor",
                        dest="nocolor",
                        action="store_true",
                        help="Turn off colorized output (default: %s)" %
                        default_nocolor,
                        default=default_nocolor)
    parser.add_argument("--quiet",
                        dest="quiet",
                        action="store_true",
                        help="Turn off some output (default: %s)" %
                        default_quiet,
                        default=False)
    parser.add_argument(
        "-a",
        "--no_auto_connect",
        dest="auto_connect",
        action="store_false",
        help="Do not automatically connect to board connected to serial port",
        default=True)
    parser.add_argument('-V',
                        '--version',
                        dest='version',
                        action='store_true',
                        help='Report the version and exit.',
                        default=False)
    parser.add_argument("-f",
                        "--file",
                        dest="filename",
                        help="File of commands to process (non-interactive).")
    parser.add_argument("cmd",
                        nargs=argparse.REMAINDER,
                        help="Optional command to execute and quit.")
    args = parser.parse_args(sys.argv[1:])

    debug(args.debug)
    quiet(args.quiet or args.cmd or args.filename)
    if args.nocolor: nocolor()

    dprint("config = %s" % args.config)
    dprint("editor = %s" % args.editor)
    dprint("debug = %s" % args.debug)
    dprint("quiet = %s" % args.quiet)
    dprint("nocolor = %s" % args.nocolor)
    dprint("auto_connect = %s" % args.auto_connect)
    dprint("version = %s" % __version__)
    dprint("cmd = [%s]" % ', '.join(args.cmd))

    if args.version:
        print(__version__)
        return

    cmd_line = ' '.join(args.cmd)
    if not args.filename and cmd_line == '':
        oprint(
            "Welcome to shell49 version {}. Type 'help' for information; Control-D to exit."
            .format(__version__))

    args.config = os.path.expanduser(args.config)
    args.config = os.path.normpath(args.config)

    with Config(args.config) as config:
        boards = ActiveBoards(config)

        # connect to board ...
        try:
            if args.auto_connect:
                boards.connect_serial(config.get('default', 'port'))
        except (ConnectionError, BoardError) as err:
            eprint(err)
        except KeyboardInterrupt:
            pass

        # start command shell
        attach_commands()
        if args.filename:
            with open(args.filename) as cmd_file:
                shell = Shell(boards, args.editor, stdin=cmd_file)
                shell.cmdloop('')
        else:
            if boards.num_boards() == 0:
                eprint(
                    "No MicroPython boards connected - use the connect command to add one."
                )
            shell = Shell(boards, args.editor)
            try:
                shell.cmdloop(cmd_line)
            except KeyboardInterrupt:
                qprint("Bye")
    print(printing.NO_COLOR)