Пример #1
0
def prompt_user(question, options, default=""):
    options = options.lower()
    default = default.lower()
    assert len(default) < 2 and default in options

    if "?" not in options:
        options += "?"

    prompt_options = ",".join(o.upper() if o == default else o
                              for o in options)
    prompt = "{} [{}]? ".format(question, prompt_options)
    result = ""

    while True:
        result = input(prompt).strip().lower()
        if result == "?":
            for option in PROMPT_HELP:
                click.secho("{} - {}".format(option, PROMPT_HELP[option]),
                            fg="red",
                            bold=True)

        elif len(result) == 1 and result in options:
            return result

        elif result:
            click.echo('invalid response "{}"'.format(result))

        elif default:
            return default
Пример #2
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--log-level", dest="log_level", type=str, choices=["DEBUG", "INFO", "WARNING", "ERROR"], help="set log level, default is INFO")
    parser.add_argument("--no-log-file", dest="no_log_file", action='store_true', default=False, help="don't log to file")
    parser.add_argument("--log-filepath", dest="log_filepath", type=str, help='set log file path, default is "report.log"')
    parser.add_argument("--inpath", required=True, type=str, help='the file or directory path you want to upgrade.')
    parser.add_argument("--backup", type=str, nargs='?', default=None, const=None, help='backup directory, default is the "~/.paddle1to2/".')
    parser.add_argument("--write", action='store_true', default=False, help='modify files in-place.')
    parser.add_argument("--no-confirm", dest="no_confirm", action='store_true', default=False, help='write files in-place without confirm, ignored without --write.')
    parser.add_argument("--refactor", action='append', choices=refactor.__all__, help='this is a debug option. Specify refactor you want to run. If none, all refactors will be run.')
    parser.add_argument("--print-match", action='store_true', default=False, help='this is a debug option. Print matched code and node for each file.')

    args = parser.parse_args()
    if args.refactor:
        args.refactor = set(args.refactor)
    if args.backup is None:
        home = os.path.expanduser('~')
        args.backup = os.path.join(home, '.paddle1to2')
    else:
        args.backup = os.path.expanduser(args.backup)

    if args.log_level:
        logger.setLevel(args.log_level)
    if not args.no_log_file:
        log_to_file(args.log_filepath)
    if not should_convert(args.inpath):
        logger.error("convert abort!")
        sys.exit(1)

    # refactor code via "Query" step by step.
    q = Query(args.inpath)
    for fn in refactor.__all__:
        refactor_func = getattr(refactor, fn)
        if args.refactor and fn not in args.refactor:
            continue
        assert callable(refactor_func), "{} is not callable.".format(fn)
        logger.debug("run refactor: {}".format(fn))
        if args.print_match:
            refactor_func(q, change_spec).filter(filters.print_match)
        else:
            refactor_func(q, change_spec)

    if args.write:
        # backup args.inpath
        backup = backup_inpath(args.inpath, args.backup)
        # print diff to stdout, and modify file in place.
        if utils.is_windows():
            q.execute(write=True, silent=False, need_confirm=not args.no_confirm, backup=backup, in_process=True)
        else:
            q.execute(write=True, silent=False, need_confirm=not args.no_confirm, backup=backup)
    else:
        # print diff to stdout
        if utils.is_windows():
            q.execute(write=False, silent=False, in_process=True)
        else:
            q.execute(write=False, silent=False)
        click.secho('Refactor finished without touching source files, add "--write" to modify source files in-place if everything is ok.', fg="red", bold=True)
Пример #3
0
    def print_hunks(self, filename, hunks):
        auto_yes = False
        result = ""
        # print same filename header only once.
        hunks_header = set()
        for hunk in hunks:
            header = "{} {}".format(hunk[0], hunk[1])
            if self.hunk_processor(filename, hunk) is False:
                continue
            if not self.silent:
                # print header, e.g.
                # --- ./model.py
                # +++ ./model.py
                if header not in hunks_header:
                    for line in hunk[:2]:
                        if line.startswith("---"):
                            click.secho(line, fg="red", bold=True)
                        elif line.startswith("+++"):
                            click.secho(line, fg="green", bold=True)
                hunks_header.add(header)

                # print diff content
                for line in hunk[2:]:
                    if line.startswith("-"):
                        click.secho(line, fg="red")
                    elif line.startswith("+"):
                        click.secho(line, fg="green")
                    else:
                        click.echo(line)
Пример #4
0
def print_tree(
    node,
    results=None,
    filename=None,
    indent=0,
    recurse=-1,
):
    filename = filename or Filename("")
    tab = INDENT_STR * indent
    if filename and indent == 0:
        click.secho(filename, fg="red", bold=True)

    if isinstance(node, Leaf):
        click.echo(
            click.style(tab, fg="black", bold=True) + click.style(
                "[{}] {} {}".format(tok_name[node.type], repr(node.prefix),
                                    repr(node.value)),
                fg="yellow",
            ))
    else:
        click.echo(
            click.style(tab, fg="black", bold=True) + click.style(
                "[{}] {}".format(type_repr(node.type), repr(node.prefix)),
                fg="blue"))

    if node.children:
        if recurse:
            for child in node.children:
                # N.b. do not pass results here since we print them once
                # at the end.
                print_tree(child, indent=indent + 1, recurse=recurse - 1)
        else:
            click.echo(INDENT_STR * (indent + 1) + "...")

    if results is None:
        return

    for key in results:
        if key == "node":
            continue

        value = results[key]
        if isinstance(value, (Leaf, Node)):
            click.secho("results[{}] =".format(repr(key)), fg="red")
            print_tree(value, indent=1, recurse=1)
        else:
            # TODO: Improve display of multi-match here, see
            # test_print_tree_captures test.
            click.secho("results[{}] = {}".format(repr(key), value), fg="red")
Пример #5
0
    def refactor(self, items, *a, **k):
        """Refactor a list of files and directories."""

        for dir_or_file in sorted(items):
            if os.path.isdir(dir_or_file):
                self.refactor_dir(dir_or_file)
            else:
                self.queue_work(Filename(dir_or_file))

        children = []
        if self.in_process:
            self.queue.put(None)
            self.refactor_queue()
        else:
            child_count = max(1, min(self.NUM_PROCESSES, self.queue_count))
            self.log_debug("starting {} processes".format(child_count))
            for i in range(child_count):
                child = multiprocessing.Process(target=self.refactor_queue)
                child.start()
                children.append(child)
                self.queue.put(None)

        results_count = 0

        while True:
            try:
                filename, hunks, exc, new_text = self.results.get_nowait()
                results_count += 1

                if exc:
                    self.log_error("{}: {}".format(type(exc).__name__, exc))
                    if exc.__cause__:
                        self.log_error("  {}: {}".format(
                            type(exc.__cause__).__name__, exc.__cause__))
                    if isinstance(exc, BowlerException) and exc.hunks:
                        diff = "\n".join("\n".join(hunk) for hunk in exc.hunks)
                        self.log_error("Generated transform:\n{}".format(diff))
                    self.exceptions.append(exc)
                else:
                    self.log_debug("results: got {} hunks for {}".format(
                        len(hunks), filename))
                    self.print_hunks(filename, hunks)
                    if hunks and self.write:
                        if self.need_confirm:
                            if click.confirm(
                                    click.style(
                                        '"{}" will be modified in-place, and it has been backed up to "{}". Do you want to continue?'
                                        .format(filename, self.backup),
                                        fg='red',
                                        bold=True)):
                                self.write_result(filename, new_text)
                                if self.print_hint:
                                    click.secho(
                                        '"{}" refactor done! Recover your files from "{}" if anything is wrong.'
                                        .format(filename, self.backup))
                            else:
                                if self.print_hint:
                                    click.secho(
                                        '"{}" refactor cancelled!'.format(
                                            filename),
                                        fg='red',
                                        bold=True)
                        else:
                            self.write_result(filename, new_text)
                            if self.print_hint:
                                click.secho(
                                    '"{}" refactor done! Recover your files from "{}" if anything is wrong.'
                                    .format(filename, self.backup))
                if self.need_confirm:
                    self.semaphore_confirm.release()

            except Empty:
                if self.queue.empty() and results_count == self.queue_count:
                    break

                elif not self.in_process and not any(child.is_alive()
                                                     for child in children):
                    self.log_debug(
                        "child processes stopped without consuming work")
                    break

                else:
                    time.sleep(0.05)

            except BowlerQuit:
                for child in children:
                    child.terminate()
                break

        self.log_debug("all children stopped and all diff hunks processed")