diff options
40 files changed, 188 insertions, 227 deletions
diff --git a/docs/advanced.rst b/docs/advanced.rst index 6278893..8003611 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -46,7 +46,7 @@ it would accept ``pus`` as an alias (so long as it was unique): return None elif len(matches) == 1: return click.Group.get_command(self, ctx, matches[0]) - ctx.fail('Too many matches: %s' % ', '.join(sorted(matches))) + ctx.fail(f"Too many matches: {', '.join(sorted(matches))}") And it can then be used like this: @@ -92,7 +92,7 @@ it's good to know that the system works this way. @click.option('--url', callback=open_url) def cli(url, fp=None): if fp is not None: - click.echo('%s: %s' % (url, fp.code)) + click.echo(f"{url}: {fp.code}") In this case the callback returns the URL unchanged but also passes a second ``fp`` value to the callback. What's more recommended is to pass @@ -116,7 +116,7 @@ the information in a wrapper however: @click.option('--url', callback=open_url) def cli(url): if url is not None: - click.echo('%s: %s' % (url.url, url.fp.code)) + click.echo(f"{url.url}: {url.fp.code}") Token Normalization @@ -140,7 +140,7 @@ function that converts the token to lowercase: @click.command(context_settings=CONTEXT_SETTINGS) @click.option('--name', default='Pete') def cli(name): - click.echo('Name: %s' % name) + click.echo(f"Name: {name}") And how it works on the command line: @@ -171,7 +171,7 @@ Example: @cli.command() @click.option('--count', default=1) def test(count): - click.echo('Count: %d' % count) + click.echo(f'Count: {count}') @cli.command() @click.option('--count', default=1) @@ -300,7 +300,7 @@ In the end you end up with something like this: """A fake wrapper around Python's timeit.""" cmdline = ['echo', 'python', '-mtimeit'] + list(timeit_args) if verbose: - click.echo('Invoking: %s' % ' '.join(cmdline)) + click.echo(f"Invoking: {' '.join(cmdline)}") call(cmdline) And what it looks like: @@ -396,7 +396,7 @@ method can be used to find this out. @click.pass_context def cli(ctx, port): source = ctx.get_parameter_source("port") - click.echo("Port came from {}".format(source)) + click.echo(f"Port came from {source}") .. click:run:: diff --git a/docs/arguments.rst b/docs/arguments.rst index 6ae3538..e5765c9 100644 --- a/docs/arguments.rst +++ b/docs/arguments.rst @@ -55,7 +55,7 @@ Example: def copy(src, dst): """Move file SRC to DST.""" for fn in src: - click.echo('move %s to folder %s' % (fn, dst)) + click.echo(f"move {fn} to folder {dst}") And what it looks like: diff --git a/docs/bashcomplete.rst b/docs/bashcomplete.rst index b2bb1b6..bc0ba7d 100644 --- a/docs/bashcomplete.rst +++ b/docs/bashcomplete.rst @@ -50,8 +50,8 @@ suggestions: @click.command() @click.argument("envvar", type=click.STRING, autocompletion=get_env_vars) def cmd1(envvar): - click.echo('Environment variable: %s' % envvar) - click.echo('Value: %s' % os.environ[envvar]) + click.echo(f"Environment variable: {envvar}") + click.echo(f"Value: {os.environ[envvar]}") Completion help strings @@ -79,7 +79,7 @@ suggestions with help strings: @click.command() @click.argument("color", type=click.STRING, autocompletion=get_colors) def cmd1(color): - click.echo('Chosen color is %s' % color) + click.echo(f"Chosen color is {color}") Activation diff --git a/docs/commands.rst b/docs/commands.rst index da26ac0..2bb9111 100644 --- a/docs/commands.rst +++ b/docs/commands.rst @@ -25,7 +25,7 @@ when an inner command runs: @click.group() @click.option('--debug/--no-debug', default=False) def cli(debug): - click.echo('Debug mode is %s' % ('on' if debug else 'off')) + click.echo(f"Debug mode is {'on' if debug else 'off'}") @cli.command() # @cli, not @click! def sync(): @@ -96,7 +96,7 @@ script like this: @cli.command() @click.pass_context def sync(ctx): - click.echo('Debug is %s' % (ctx.obj['DEBUG'] and 'on' or 'off')) + click.echo(f"Debug is {'on' if ctx.obj['DEBUG'] else 'off'}") if __name__ == '__main__': cli(obj={}) @@ -166,7 +166,7 @@ Example: if ctx.invoked_subcommand is None: click.echo('I was invoked without subcommand') else: - click.echo('I am about to invoke %s' % ctx.invoked_subcommand) + click.echo(f"I am about to invoke {ctx.invoked_subcommand}") @cli.command() def sync(): @@ -466,7 +466,7 @@ Example usage: @cli.command() @click.option('--port', default=8000) def runserver(port): - click.echo('Serving on http://127.0.0.1:%d/' % port) + click.echo(f"Serving on http://127.0.0.1:{port}/") if __name__ == '__main__': cli(default_map={ @@ -512,7 +512,7 @@ This example does the same as the previous example: @cli.command() @click.option('--port', default=8000) def runserver(port): - click.echo('Serving on http://127.0.0.1:%d/' % port) + click.echo(f"Serving on http://127.0.0.1:{port}/") if __name__ == '__main__': cli() diff --git a/docs/documentation.rst b/docs/documentation.rst index 982ad42..181c5b3 100644 --- a/docs/documentation.rst +++ b/docs/documentation.rst @@ -24,7 +24,7 @@ Simple example: def hello(count, name): """This script prints hello NAME COUNT times.""" for x in range(count): - click.echo('Hello %s!' % name) + click.echo(f"Hello {name}!") And what it looks like: @@ -173,7 +173,7 @@ desired. This can be customized at all levels: def hello(count, name): """This script prints hello <name> <int> times.""" for x in range(count): - click.echo('Hello %s!' % name) + click.echo(f"Hello {name}!") Example: diff --git a/docs/index.rst b/docs/index.rst index 7fac849..683f1ef 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -36,7 +36,7 @@ What does it look like? Here is an example of a simple Click program: def hello(count, name): """Simple program that greets NAME for a total of COUNT times.""" for x in range(count): - click.echo('Hello %s!' % name) + click.echo(f"Hello {name}!") if __name__ == '__main__': hello() diff --git a/docs/options.rst b/docs/options.rst index 4942c8a..41653aa 100644 --- a/docs/options.rst +++ b/docs/options.rst @@ -85,7 +85,7 @@ simply pass in `required=True` as an argument to the decorator. @click.option('--from', '-f', 'from_') @click.option('--to', '-t') def reserved_param_name(from_, to): - click.echo('from %s to %s' % (from_, to)) + click.echo(f"from {from_} to {to}") And on the command line: @@ -121,7 +121,8 @@ the ``nargs`` parameter. The values are then stored as a tuple. @click.command() @click.option('--pos', nargs=2, type=float) def findme(pos): - click.echo('%s / %s' % pos) + a, b = pos + click.echo(f"{a} / {b}") And on the command line: @@ -146,7 +147,8 @@ the tuple. For this you can directly specify a tuple as type: @click.command() @click.option('--item', type=(str, int)) def putitem(item): - click.echo('name=%s id=%d' % item) + name, id = item + click.echo(f"name={name} id={id}") And on the command line: @@ -163,7 +165,8 @@ used. The above example is thus equivalent to this: @click.command() @click.option('--item', nargs=2, type=click.Tuple([str, int])) def putitem(item): - click.echo('name=%s id=%d' % item) + name, id = item + click.echo(f"name={name} id={id}") .. _multiple-options: @@ -212,7 +215,7 @@ for instance: @click.command() @click.option('-v', '--verbose', count=True) def log(verbose): - click.echo('Verbosity: %s' % verbose) + click.echo(f"Verbosity: {verbose}") And on the command line: @@ -281,7 +284,7 @@ can alternatively split the parameters through ``;`` instead: @click.command() @click.option('/debug;/no-debug') def log(debug): - click.echo('debug=%s' % debug) + click.echo(f"debug={debug}") if __name__ == '__main__': log() @@ -402,7 +405,7 @@ Example: @click.command() @click.option('--name', prompt=True) def hello(name): - click.echo('Hello %s!' % name) + click.echo(f"Hello {name}!") And what it looks like: @@ -419,7 +422,7 @@ a different one: @click.command() @click.option('--name', prompt='Your name please') def hello(name): - click.echo('Hello %s!' % name) + click.echo(f"Hello {name}!") What it looks like: @@ -443,7 +446,7 @@ useful for password input: @click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True) def encrypt(password): - click.echo('Encrypting password to %s' % password.encode('rot13')) + click.echo(f"Encrypting password to {password.encode('rot13')}") What it looks like: @@ -459,7 +462,7 @@ replaced with the :func:`password_option` decorator: @click.command() @click.password_option() def encrypt(password): - click.echo('Encrypting password to %s' % password.encode('rot13')) + click.echo(f"Encrypting password to {password.encode('rot13')}") Dynamic Defaults for Prompts ---------------------------- @@ -625,7 +628,7 @@ Example usage: @click.command() @click.option('--username') def greet(username): - click.echo('Hello %s!' % username) + click.echo(f'Hello {username}!') if __name__ == '__main__': greet(auto_envvar_prefix='GREETER') @@ -650,12 +653,12 @@ Example: @click.group() @click.option('--debug/--no-debug') def cli(debug): - click.echo('Debug mode is %s' % ('on' if debug else 'off')) + click.echo(f"Debug mode is {'on' if debug else 'off'}") @cli.command() @click.option('--username') def greet(username): - click.echo('Hello %s!' % username) + click.echo(f"Hello {username}!") if __name__ == '__main__': cli(auto_envvar_prefix='GREETER') @@ -677,7 +680,7 @@ Example usage: @click.command() @click.option('--username', envvar='USERNAME') def greet(username): - click.echo('Hello %s!' % username) + click.echo(f"Hello {username}!") if __name__ == '__main__': greet() @@ -726,7 +729,7 @@ And from the command line: .. click:run:: import os - invoke(perform, env={'PATHS': './foo/bar%s./test' % os.path.pathsep}) + invoke(perform, env={"PATHS": f"./foo/bar{os.path.pathsep}./test"}) Other Prefix Characters ----------------------- @@ -742,7 +745,7 @@ POSIX semantics. However in certain situations this can be useful: @click.command() @click.option('+w/-w') def chmod(w): - click.echo('writable=%s' % w) + click.echo(f"writable={w}") if __name__ == '__main__': chmod() @@ -762,7 +765,7 @@ boolean flag you need to separate it with ``;`` instead of ``/``: @click.command() @click.option('/debug;/no-debug') def log(debug): - click.echo('debug=%s' % debug) + click.echo(f"debug={debug}") if __name__ == '__main__': log() @@ -834,7 +837,8 @@ Example: @click.command() @click.option('--rolls', callback=validate_rolls, default='1d6') def roll(rolls): - click.echo('Rolling a %d-sided dice %d time(s)' % rolls) + sides, times = rolls + click.echo(f"Rolling a {sides}-sided dice {times} time(s)") if __name__ == '__main__': roll() diff --git a/docs/quickstart.rst b/docs/quickstart.rst index c8cb2d9..51f7f22 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -240,7 +240,7 @@ To add parameters, use the :func:`option` and :func:`argument` decorators: @click.argument('name') def hello(count, name): for x in range(count): - click.echo('Hello %s!' % name) + click.echo(f"Hello {name}!") What it looks like: diff --git a/docs/testing.rst b/docs/testing.rst index 52a888d..57acaf2 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -30,7 +30,7 @@ data, exit code, and optional exception attached: @click.command() @click.argument('name') def hello(name): - click.echo('Hello %s!' % name) + click.echo(f'Hello {name}!') .. code-block:: python :caption: test_hello.py @@ -54,7 +54,7 @@ For subcommand testing, a subcommand name must be specified in the `args` parame @click.group() @click.option('--debug/--no-debug', default=False) def cli(debug): - click.echo('Debug mode is %s' % ('on' if debug else 'off')) + click.echo(f"Debug mode is {'on' if debug else 'off'}") @cli.command() def sync(): @@ -126,7 +126,7 @@ stream (stdin). This is very useful for testing prompts, for instance: @click.command() @click.option('--foo', prompt=True) def prompt(foo): - click.echo('foo=%s' % foo) + click.echo(f"foo={foo}") .. code-block:: python :caption: test_prompt.py diff --git a/docs/utils.rst b/docs/utils.rst index 902e5fd..7dd8dbb 100644 --- a/docs/utils.rst +++ b/docs/utils.rst @@ -112,15 +112,14 @@ Example: @click.command() def less(): - click.echo_via_pager('\n'.join('Line %d' % idx - for idx in range(200))) + click.echo_via_pager("\n".join(f"Line {idx}" for idx in range(200))) If you want to use the pager for a lot of text, especially if generating everything in advance would take a lot of time, you can pass a generator (or generator function) instead of a string: .. click:example:: def _generate_output(): for idx in range(50000): - yield "Line %d\n" % idx + yield f"Line {idx}\n" @click.command() def less(): @@ -264,7 +263,7 @@ context of a full Unicode string. Example:: - click.echo('Path: %s' % click.format_filename(b'foo.txt')) + click.echo(f"Path: {click.format_filename(b'foo.txt')}") Standard Streams @@ -349,7 +348,7 @@ Example usage:: rv = {} for section in parser.sections(): for key, value in parser.items(section): - rv['%s.%s' % (section, key)] = value + rv[f"{section}.{key}"] = value return rv @@ -396,7 +395,7 @@ loop. So code like this will render correctly:: with click.progressbar([1, 2, 3]) as bar: for x in bar: - print('sleep({})...'.format(x)) + print(f"sleep({x})...") time.sleep(x) Another useful feature is to associate a label with the progress bar which diff --git a/examples/aliases/aliases.py b/examples/aliases/aliases.py index c01672b..c3da657 100644 --- a/examples/aliases/aliases.py +++ b/examples/aliases/aliases.py @@ -65,7 +65,7 @@ class AliasedGroup(click.Group): return None elif len(matches) == 1: return click.Group.get_command(self, ctx, matches[0]) - ctx.fail("Too many matches: {}".format(", ".join(sorted(matches)))) + ctx.fail(f"Too many matches: {', '.join(sorted(matches))}") def read_config(ctx, param, value): diff --git a/examples/bashcompletion/bashcompletion.py b/examples/bashcompletion/bashcompletion.py index 592bf19..3f8c9df 100644 --- a/examples/bashcompletion/bashcompletion.py +++ b/examples/bashcompletion/bashcompletion.py @@ -19,7 +19,7 @@ def get_env_vars(ctx, args, incomplete): @click.argument("envvar", type=click.STRING, autocompletion=get_env_vars) def cmd1(envvar): click.echo(f"Environment variable: {envvar}") - click.echo("Value: {}".format(os.environ[envvar])) + click.echo(f"Value: {os.environ[envvar]}") @click.group(help="A group that holds a subcommand") diff --git a/examples/complex/complex/commands/cmd_init.py b/examples/complex/complex/commands/cmd_init.py index c2cf770..8802458 100644 --- a/examples/complex/complex/commands/cmd_init.py +++ b/examples/complex/complex/commands/cmd_init.py @@ -10,4 +10,4 @@ def cli(ctx, path): """Initializes a repository.""" if path is None: path = ctx.home - ctx.log("Initialized the repository in %s", click.format_filename(path)) + ctx.log(f"Initialized the repository in {click.format_filename(path)}") diff --git a/examples/imagepipe/imagepipe.py b/examples/imagepipe/imagepipe.py index 95f5c42..57432fa 100644 --- a/examples/imagepipe/imagepipe.py +++ b/examples/imagepipe/imagepipe.py @@ -230,9 +230,8 @@ def smoothen_cmd(images, iterations): """Applies a smoothening filter.""" for image in images: click.echo( - "Smoothening '{}' {} time{}".format( - image.filename, iterations, "s" if iterations != 1 else "" - ) + f"Smoothening {image.filename!r} {iterations}" + f" time{'s' if iterations != 1 else ''}" ) for _ in range(iterations): image = copy_filename(image.filter(ImageFilter.BLUR), image) diff --git a/examples/repo/repo.py b/examples/repo/repo.py index ff44d55..b773f3a 100644 --- a/examples/repo/repo.py +++ b/examples/repo/repo.py @@ -78,7 +78,7 @@ def clone(repo, src, dest, shallow, rev): """ if dest is None: dest = posixpath.split(src)[-1] or "." - click.echo("Cloning repo {} to {}".format(src, os.path.abspath(dest))) + click.echo(f"Cloning repo {src} to {os.path.basename(dest)}") repo.home = dest if shallow: click.echo("Making shallow checkout") diff --git a/examples/termui/termui.py b/examples/termui/termui.py index b772f13..f4886b1 100644 --- a/examples/termui/termui.py +++ b/examples/termui/termui.py @@ -24,7 +24,7 @@ def pager(): """Demonstrates using the pager.""" lines = [] for x in range(200): - lines.append("{}. Hello World!".format(click.style(str(x), fg="green"))) + lines.append(f"{click.style(str(x), fg='green')}. Hello World!") click.echo_via_pager("\n".join(lines)) diff --git a/examples/validation/validation.py b/examples/validation/validation.py index 6f87eb0..3f78df0 100644 --- a/examples/validation/validation.py +++ b/examples/validation/validation.py @@ -17,8 +17,7 @@ class URL(click.ParamType): value = urlparse.urlparse(value) if value.scheme not in ("http", "https"): self.fail( - "invalid URL scheme ({}). Only HTTP URLs are" - " allowed".format(value.scheme), + f"invalid URL scheme ({value.scheme}). Only HTTP URLs are allowed", param, ctx, ) diff --git a/src/click/_bashcomplete.py b/src/click/_bashcomplete.py index 1c865f6..b9e4900 100644 --- a/src/click/_bashcomplete.py +++ b/src/click/_bashcomplete.py @@ -345,7 +345,7 @@ def do_complete_fish(cli, prog_name): for item in get_choices(cli, prog_name, args, incomplete): if item[1]: - echo("{arg}\t{desc}".format(arg=item[0], desc=item[1])) + echo(f"{item[0]}\t{item[1]}") else: echo(item[0]) diff --git a/src/click/_compat.py b/src/click/_compat.py index 96b0dd8..85568ca 100644 --- a/src/click/_compat.py +++ b/src/click/_compat.py @@ -64,7 +64,7 @@ class _NonClosingTextIOWrapper(io.TextIOWrapper): errors, force_readable=False, force_writable=False, - **extra + **extra, ): self._stream = stream = _FixupStream(stream, force_readable, force_writable) super().__init__(stream, encoding, errors, **extra) @@ -415,7 +415,7 @@ def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False while True: tmp_filename = os.path.join( os.path.dirname(filename), - ".__atomic-write{:08x}".format(random.randrange(1 << 32)), + f".__atomic-write{random.randrange(1 << 32):08x}", ) try: fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) diff --git a/src/click/_termui_impl.py b/src/click/_termui_impl.py index 84e3fc5..f03aa85 100644 --- a/src/click/_termui_impl.py +++ b/src/click/_termui_impl.py @@ -173,7 +173,7 @@ class ProgressBar: return pos def format_pct(self): - return "{: 4}%".format(int(self.pct * 100))[1:] + return f"{int(self.pct * 100): 4}%"[1:] def format_bar(self): if self.length_known: @@ -352,10 +352,7 @@ def pager(generator, color=None): fd, filename = tempfile.mkstemp() os.close(fd) try: - if ( - hasattr(os, "system") - and os.system("more {}".format(shlex.quote(filename))) == 0 - ): + if hasattr(os, "system") and os.system(f"more {shlex.quote(filename)}") == 0: return _pipepager(generator, "more", color) return _nullpager(stdout, generator, color) finally: @@ -374,7 +371,7 @@ def _pipepager(generator, cmd, color): # condition that cmd_detail = cmd.rsplit("/", 1)[-1].split() if color is None and cmd_detail[0] == "less": - less_flags = "{}{}".format(os.environ.get("LESS", ""), " ".join(cmd_detail[1:])) + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" if not less_flags: env["LESS"] = "-R" color = True @@ -424,7 +421,7 @@ def _tempfilepager(generator, cmd, color): with open_stream(filename, "wb")[0] as f: f.write(text.encode(encoding)) try: - os.system("{} {}".format(shlex.quote(cmd), shlex.quote(filename))) + os.system(f"{shlex.quote(cmd)} {shlex.quote(filename)}") finally: os.unlink(filename) @@ -469,7 +466,7 @@ class Editor: environ = None try: c = subprocess.Popen( - "{} {}".format(shlex.quote(editor), shlex.quote(filename)), + f"{shlex.quote(editor)} {shlex.quote(filename)}", env=environ, shell=True, ) @@ -546,16 +543,16 @@ def open_url(url, wait=False, locate=False): elif WIN: if locate: url = _unquote_file(url) - args = "explorer /select,{}".format(shlex.quote(url)) + args = f"explorer /select,{shlex.quote(url)}" else: - args = 'start {} "" {}'.format("/WAIT" if wait else "", shlex.quote(url)) + args = f"start {'/WAIT' if wait else ''} \"\" {shlex.quote(url)}" return os.system(args) elif CYGWIN: if locate: url = _unquote_file(url) - args = "cygstart {}".format(shlex.quote(os.path.dirname(url))) + args = f"cygstart {shlex.quote(os.path.dirname(url))}" else: - args = "cygstart {} {}".format("-w" if wait else "", shlex.quote(url)) + args = f"cygstart {'-w' if wait else ''} {shlex.quote(url)}" return os.system(args) try: diff --git a/src/click/_textwrap.py b/src/click/_textwrap.py index 6959087..7a052b7 100644 --- a/src/click/_textwrap.py +++ b/src/click/_textwrap.py @@ -33,5 +33,5 @@ class TextWrapper(textwrap.TextWrapper): indent = self.initial_indent if idx > 0: indent = self.subsequent_indent - rv.append(indent + line) + rv.append(f"{indent}{line}") return "\n".join(rv) diff --git a/src/click/_unicodefun.py b/src/click/_unicodefun.py index 57545e0..7f3f234 100644 --- a/src/click/_unicodefun.py +++ b/src/click/_unicodefun.py @@ -55,9 +55,9 @@ def _verify_python3_env(): ) else: extra += ( - "This system lists a couple of UTF-8 supporting locales" - " that you can pick from. The following suitable" - " locales were discovered: {}".format(", ".join(sorted(good_locales))) + "This system lists some UTF-8 supporting locales that" + " you can pick from. The following suitable locales" + f" were discovered: {', '.join(sorted(good_locales))}" ) bad_locale = None @@ -71,12 +71,12 @@ def _verify_python3_env(): "\n\nClick discovered that you exported a UTF-8 locale" " but the locale system could not pick up from it" " because it does not exist. The exported locale is" - " '{}' but it is not supported".format(bad_locale) + f" {bad_locale!r} but it is not supported" ) raise RuntimeError( "Click will abort further execution because Python 3 was" " configured to use ASCII as encoding for the environment." " Consult https://click.palletsprojects.com/python3/ for" - " mitigation steps.{}".format(extra) + f" mitigation steps.{extra}" ) diff --git a/src/click/_winconsole.py b/src/click/_winconsole.py index c46081f..923fdba 100644 --- a/src/click/_winconsole.py +++ b/src/click/_winconsole.py @@ -213,9 +213,7 @@ class ConsoleStream: return self.buffer.isatty() def __repr__(self): - return "<ConsoleStream name={!r} encoding={!r}>".format( - self.name, self.encoding - ) + return f"<ConsoleStream name={self.name!r} encoding={self.encoding!r}>" class WindowsChunkedWriter: diff --git a/src/click/core.py b/src/click/core.py index 78b9ce4..e4061aa 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -36,12 +36,12 @@ SUBCOMMAND_METAVAR = "COMMAND [ARGS]..." SUBCOMMANDS_METAVAR = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." DEPRECATED_HELP_NOTICE = " (DEPRECATED)" -DEPRECATED_INVOKE_NOTICE = "DeprecationWarning: The command %(name)s is deprecated." +DEPRECATED_INVOKE_NOTICE = "DeprecationWarning: The command {name} is deprecated." def _maybe_show_deprecated_notice(cmd): if cmd.deprecated: - echo(style(DEPRECATED_INVOKE_NOTICE % {"name": cmd.name}, fg="red"), err=True) + echo(style(DEPRECATED_INVOKE_NOTICE.format(name=cmd.name), fg="red"), err=True) def fast_exit(code): @@ -56,7 +56,7 @@ def fast_exit(code): def _bashcomplete(cmd, prog_name, complete_var=None): """Internal handler for the bash completion support.""" if complete_var is None: - complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) + complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").upper() complete_instr = os.environ.get(complete_var) if not complete_instr: return @@ -81,17 +81,11 @@ def _check_multicommand(base_command, cmd_name, cmd, register=False): " that is in chain mode. This is not supported." ) raise RuntimeError( - "{}. Command '{}' is set to chain and '{}' was added as" - " subcommand but it in itself is a multi command. ('{}' is a {}" - " within a chained {} named '{}').".format( - hint, - base_command.name, - cmd_name, - cmd_name, - cmd.__class__.__name__, - base_command.__class__.__name__, - base_command.name, - ) + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." ) @@ -159,8 +153,8 @@ class ParameterSource: """ if value not in cls.VALUES: raise ValueError( - "Invalid ParameterSource value: '{}'. Valid " - "values are: {}".format(value, ",".join(cls.VALUES)) + f"Invalid ParameterSource value: {value!r}. Valid" + f" values are: {','.join(cls.VALUES)}" ) @@ -381,8 +375,8 @@ class Context: and parent.auto_envvar_prefix is not None and self.info_name is not None ): - auto_envvar_prefix = "{}_{}".format( - parent.auto_envvar_prefix, self.info_name.upper() + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" ) else: auto_envvar_prefix = auto_envvar_prefix.upper() @@ -1088,9 +1082,9 @@ class Command(BaseCommand): if args and not ctx.allow_extra_args and not ctx.resilient_parsing: ctx.fail( - "Got unexpected extra argument{} ({})".format( - "s" if len(args) != 1 else "", " ".join(map(make_str, args)) - ) + "Got unexpected extra" + f" argument{'s' if len(args) != 1 else ''}" + f" ({' '.join(map(make_str, args))})" ) ctx.args = args @@ -1598,8 +1592,8 @@ class Parameter: if self.nargs <= 1: raise TypeError( "Attempted to invoke composite type but nargs has" - " been set to {}. This is not supported; nargs" - " needs to be set to a fixed value > 1.".format(self.nargs) + f" been set to {self.nargs}. This is not supported;" + " nargs needs to be set to a fixed value > 1." ) if self.multiple: return tuple(self.type(x or (), self, ctx) for x in value or ()) @@ -1863,8 +1857,9 @@ class Option(Parameter): if not opts and not secondary_opts: raise TypeError( - "No options defined but a name was passed ({}). Did you" - " mean to declare an argument instead of an option?".format(name) + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead of an" + " option?" ) return name, opts, secondary_opts @@ -1924,13 +1919,12 @@ class Option(Parameter): if self.allow_from_autoenv and ctx.auto_envvar_prefix is not None: envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" if envvar is not None: - extra.append( - "env var: {}".format( - ", ".join(str(d) for d in envvar) - if isinstance(envvar, (list, tuple)) - else envvar - ) + var_str = ( + ", ".join(str(d) for d in envvar) + if isinstance(envvar, (list, tuple)) + else envvar ) + extra.append(f"env var: {var_str}") if self.default is not None and (self.show_default or ctx.show_default): if isinstance(self.show_default, str): default_string = f"({self.show_default})" @@ -1945,7 +1939,8 @@ class Option(Parameter): if self.required: extra.append("required") if extra: - help = "{}[{}]".format(f"{help} " if help else "", "; ".join(extra)) + extra_str = ";".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" return ("; " if any_prefix_is_slash else " / ").join(rv), help @@ -2061,7 +2056,7 @@ class Argument(Parameter): else: raise TypeError( "Arguments take exactly one parameter declaration, got" - " {}".format(len(decls)) + f" {len(decls)}." ) return name, [arg], [] diff --git a/src/click/decorators.py b/src/click/decorators.py index e0596c8..3013305 100644 --- a/src/click/decorators.py +++ b/src/click/decorators.py @@ -66,7 +66,8 @@ def make_pass_decorator(object_type, ensure=False): if obj is None: raise RuntimeError( "Managed to invoke callback without a context" - " object of type '{}' existing".format(object_type.__name__) + f" object of type {object_type.__name__!r}" + " existing." ) return ctx.invoke(f, obj, *args, **kwargs) @@ -96,7 +97,7 @@ def _make_command(f, name, attrs, cls): name=name or f.__name__.lower().replace("_", "-"), callback=f, params=params, - **attrs + **attrs, ) diff --git a/src/click/exceptions.py b/src/click/exceptions.py index 2776a02..25b02bb 100644 --- a/src/click/exceptions.py +++ b/src/click/exceptions.py @@ -53,8 +53,9 @@ class UsageError(ClickException): color = None hint = "" if self.cmd is not None and self.cmd.get_help_option(self.ctx) is not None: - hint = "Try '{} {}' for help.\n".format( - self.ctx.command_path, self.ctx.help_option_names[0] + hint = ( + f"Try '{self.ctx.command_path}" + f" {self.ctx.help_option_names[0]}' for help.\n" ) if self.ctx is not None: color = self.ctx.color @@ -137,12 +138,8 @@ class MissingParameter(BadParameter): else: msg = msg_extra - return "Missing {}{}{}{}".format( - param_type, - f" {param_hint}" if param_hint else "", - ". " if msg else ".", - msg or "", - ) + hint_str = f" {param_hint}" if param_hint else "" + return f"Missing {param_type}{hint_str}.{' ' if msg else ''}{msg or ''}" def __str__(self): if self.message is None: @@ -170,10 +167,10 @@ class NoSuchOption(UsageError): bits = [self.message] if self.possibilities: if len(self.possibilities) == 1: - bits.append("Did you mean {}?".format(self.possibilities[0])) + bits.append(f"Did you mean {self.possibilities[0]}?") else: possibilities = sorted(self.possibilities) - bits.append("(Possible options: {})".format(", ".join(possibilities))) + bits.append(f"(Possible options: {', '.join(possibilities)})") return " ".join(bits) diff --git a/src/click/formatting.py b/src/click/formatting.py index 5a8b81c..a298c2e 100644 --- a/src/click/formatting.py +++ b/src/click/formatting.py @@ -134,7 +134,7 @@ class HelpFormatter: :param args: whitespace separated list of arguments. :param prefix: the prefix for the first line. """ - usage_prefix = "{:>{w}}{} ".format(prefix, prog, w=self.current_indent) + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " text_width = self.width - self.current_indent if text_width >= (term_len(usage_prefix) + 20): @@ -163,7 +163,7 @@ class HelpFormatter: def write_heading(self, heading): """Writes a heading into the buffer.""" - self.write("{:>{w}}{}:\n".format("", heading, w=self.current_indent)) + self.write(f"{'':>{self.current_indent}}{heading}:\n") def write_paragraph(self): """Writes a paragraph into the buffer.""" @@ -204,7 +204,7 @@ class HelpFormatter: first_col = min(widths[0], col_max) + col_spacing for first, second in iter_rows(rows, len(widths)): - self.write("{:>{w}}{}".format("", first, w=self.current_indent)) + self.write(f"{'':>{self.current_indent}}{first}") if not second: self.write("\n") continue @@ -219,14 +219,10 @@ class HelpFormatter: lines = wrapped_text.splitlines() if lines: - self.write("{}\n".format(lines[0])) + self.write(f"{lines[0]}\n") for line in lines[1:]: - self.write( - "{:>{w}}{}\n".format( - "", line, w=first_col + self.current_indent - ) - ) + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") if len(lines) > 1: # separate long help from next option diff --git a/src/click/parser.py b/src/click/parser.py index ae486d0..158abb0 100644 --- a/src/click/parser.py +++ b/src/click/parser.py @@ -100,7 +100,7 @@ def normalize_opt(opt, ctx): if ctx is None or ctx.token_normalize_func is None: return opt prefix, opt = split_opt(opt) - return prefix + ctx.token_normalize_func(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" def split_arg_string(string): @@ -361,7 +361,7 @@ class OptionParser: unknown_options = [] for ch in arg[1:]: - opt = normalize_opt(prefix + ch, self.ctx) + opt = normalize_opt(f"{prefix}{ch}", self.ctx) option = self._short_opt.get(opt) i += 1 @@ -399,7 +399,7 @@ class OptionParser: # to the state as new larg. This way there is basic combinatorics # that can be achieved while still ignoring unknown arguments. if self.ignore_unknown_options and unknown_options: - state.largs.append("{}{}".format(prefix, "".join(unknown_options))) + state.largs.append(f"{prefix}{''.join(unknown_options)}") def _process_opts(self, arg, state): explicit_value = None diff --git a/src/click/termui.py b/src/click/termui.py index b9c91c7..a1bdf2a 100644 --- a/src/click/termui.py +++ b/src/click/termui.py @@ -56,10 +56,10 @@ def _build_prompt( ): prompt = text if type is not None and show_choices and isinstance(type, Choice): - prompt += " ({})".format(", ".join(map(str, type.choices))) + prompt += f" ({', '.join(map(str, type.choices))})" if default is not None and show_default: - prompt = "{} [{}]".format(prompt, _format_default(default)) - return prompt + suffix + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" def _format_default(default): @@ -502,24 +502,24 @@ def style( bits = [] if fg: try: - bits.append("\033[{}m".format(_ansi_colors[fg])) + bits.append(f"\033[{_ansi_colors[fg]}m") except KeyError: - raise TypeError(f"Unknown color '{fg}'") + raise TypeError(f"Unknown color {fg!r}") if bg: try: - bits.append("\033[{}m".format(_ansi_colors[bg] + 10)) + bits.append(f"\033[{_ansi_colors[bg] + 10}m") except KeyError: - raise TypeError(f"Unknown color '{bg}'") + raise TypeError(f"Unknown color {bg!r}") if bold is not None: - bits.append("\033[{}m".format(1 if bold else 22)) + bits.append(f"\033[{1 if bold else 22}m") if dim is not None: - bits.append("\033[{}m".format(2 if dim else 22)) + bits.append(f"\033[{2 if dim else 22}m") if underline is not None: - bits.append("\033[{}m".format(4 if underline else 24)) + bits.append(f"\033[{4 if underline else 24}m") if blink is not None: - bits.append("\033[{}m".format(5 if blink else 25)) + bits.append(f"\033[{5 if blink else 25}m") if reverse is not None: - bits.append("\033[{}m".format(7 if reverse else 27)) + bits.append(f"\033[{7 if reverse else 27}m") bits.append(text) if reset: bits.append(_ansi_reset_all) diff --git a/src/click/testing.py b/src/click/testing.py index 717d2e4..fd6bf61 100644 --- a/src/click/testing.py +++ b/src/click/testing.py @@ -99,9 +99,8 @@ class Result: ) def __repr__(self): - return "<{} {}>".format( - type(self).__name__, repr(self.exception) if self.exception else "okay" - ) + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" class CliRunner: @@ -196,7 +195,7 @@ class CliRunner: return val def hidden_input(prompt=None): - sys.stdout.write("{}\n".format(prompt or "")) + sys.stdout.write(f"{prompt or ''}\n") sys.stdout.flush() return input.readline().rstrip("\r\n") diff --git a/src/click/types.py b/src/click/types.py index 7aae2fe..93cf701 100644 --- a/src/click/types.py +++ b/src/click/types.py @@ -157,10 +157,11 @@ class Choice(ParamType): self.case_sensitive = case_sensitive def get_metavar(self, param): - return "[{}]".format("|".join(self.choices)) + return f"[{'|'.join(self.choices)}]" def get_missing_message(self, param): - return "Choose from:\n\t{}.".format(",\n\t".join(self.choices)) + choice_str = ",\n\t".join(self.choices) + return f"Choose from:\n\t{choice_str}" def convert(self, value, param, ctx): # Match through normalization and case sensitivity @@ -188,15 +189,13 @@ class Choice(ParamType): return normed_choices[normed_value] self.fail( - "invalid choice: {}. (choose from {})".format( - value, ", ".join(self.choices) - ), + f"invalid choice: {value}. (choose from {', '.join(self.choices)})", param, ctx, ) def __repr__(self): - return "Choice('{}')".format(list(self.choices)) + return f"Choice({list(self.choices)})" class DateTime(ParamType): @@ -226,7 +225,7 @@ class DateTime(ParamType): self.formats = formats or ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"] def get_metavar(self, param): - return "[{}]".format("|".join(self.formats)) + return f"[{'|'.join(self.formats)}]" def _try_to_convert_date(self, value, format): try: @@ -242,9 +241,7 @@ class DateTime(ParamType): return dtime self.fail( - "invalid datetime format: {}. (choose from {})".format( - value, ", ".join(self.formats) - ) + f"invalid datetime format: {value}. (choose from {', '.join(self.formats)})" ) def __repr__(self): @@ -295,25 +292,19 @@ class IntRange(IntParamType): ): if self.min is None: self.fail( - "{} is bigger than the maximum valid value {}.".format( - rv, self.max - ), + f"{rv} is bigger than the maximum valid value {self.max}.", param, ctx, ) elif self.max is None: self.fail( - "{} is smaller than the minimum valid value {}.".format( - rv, self.min - ), + f"{rv} is smaller than the minimum valid value {self.min}.", param, ctx, ) else: self.fail( - "{} is not in the valid range of {} to {}.".format( - rv, self.min, self.max - ), + f"{rv} is not in the valid range of {self.min} to {self.max}.", param, ctx, ) @@ -367,25 +358,19 @@ class FloatRange(FloatParamType): ): if self.min is None: self.fail( - "{} is bigger than the maximum valid value {}.".format( - rv, self.max - ), + f"{rv} is bigger than the maximum valid value {self.max}.", param, ctx, ) elif self.max is None: self.fail( - "{} is smaller than the minimum valid value {}.".format( - rv, self.min - ), + f"{rv} is smaller than the minimum valid value {self.min}.", param, ctx, ) else: self.fail( - "{} is not in the valid range of {} to {}.".format( - rv, self.min, self.max - ), + f"{rv} is not in the valid range of {self.min} to {self.max}.", param, ctx, ) @@ -506,9 +491,7 @@ class File(ParamType): return f except OSError as e: # noqa: B014 self.fail( - "Could not open file: {}: {}".format( - filename_to_ui(value), get_strerror(e) - ), + f"Could not open file: {filename_to_ui(value)}: {get_strerror(e)}", param, ctx, ) @@ -600,40 +583,32 @@ class Path(ParamType): if not self.exists: return self.coerce_path_result(rv) self.fail( - "{} '{}' does not exist.".format( - self.path_type, filename_to_ui(value) - ), + f"{self.path_type} {filename_to_ui(value)!r} does not exist.", param, ctx, ) if not self.file_okay and stat.S_ISREG(st.st_mode): self.fail( - "{} '{}' is a file.".format(self.path_type, filename_to_ui(value)), + f"{self.path_type} {filename_to_ui(value)!r} is a file.", param, ctx, ) if not self.dir_okay and stat.S_ISDIR(st.st_mode): self.fail( - "{} '{}' is a directory.".format( - self.path_type, filename_to_ui(value) - ), + f"{self.path_type} {filename_to_ui(value)!r} is a directory.", param, ctx, ) if self.writable and not os.access(value, os.W_OK): self.fail( - "{} '{}' is not writable.".format( - self.path_type, filename_to_ui(value) - ), + f"{self.path_type} {filename_to_ui(value)!r} is not writable.", param, ctx, ) if self.readable and not os.access(value, os.R_OK): self.fail( - "{} '{}' is not readable.".format( - self.path_type, filename_to_ui(value) - ), + f"{self.path_type} {filename_to_ui(value)!r} is not readable.", param, ctx, ) @@ -660,7 +635,7 @@ class Tuple(CompositeParamType): @property def name(self): - return "<{}>".format(" ".join(ty.name for ty in self.types)) + return f"<{' '.join(ty.name for ty in self.types)}>" @property def arity(self): diff --git a/src/click/utils.py b/src/click/utils.py index b18c83d..ffd26b3 100644 --- a/src/click/utils.py +++ b/src/click/utils.py @@ -408,7 +408,7 @@ def get_app_dir(app_name, roaming=True, force_posix=False): folder = os.path.expanduser("~") return os.path.join(folder, app_name) if force_posix: - return os.path.join(os.path.expanduser("~/.{}".format(_posixify(app_name)))) + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) if sys.platform == "darwin": return os.path.join( os.path.expanduser("~/Library/Application Support"), app_name diff --git a/tests/test_arguments.py b/tests/test_arguments.py index 4970486..c5fee42 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -10,7 +10,7 @@ def test_nargs_star(runner): @click.argument("src", nargs=-1) @click.argument("dst") def copy(src, dst): - click.echo("src={}".format("|".join(src))) + click.echo(f"src={'|'.join(src)}") click.echo(f"dst={dst}") result = runner.invoke(copy, ["foo.txt", "bar.txt", "dir"]) @@ -33,7 +33,8 @@ def test_nargs_tup(runner): @click.argument("point", nargs=2, type=click.INT) def copy(name, point): click.echo(f"name={name}") - click.echo("point={0[0]}/{0[1]}".format(point)) + x, y = point + click.echo(f"point={x}/{y}") result = runner.invoke(copy, ["peter", "1", "2"]) assert not result.exception @@ -53,7 +54,8 @@ def test_nargs_tup_composite(runner): @click.command() @click.argument("item", **opts) def copy(item): - click.echo("name={0[0]} id={0[1]:d}".format(item)) + name, id = item + click.echo(f"name={name} id={id:d}") result = runner.invoke(copy, ["peter", "1"]) assert not result.exception @@ -187,7 +189,7 @@ def test_empty_nargs(runner): @click.command() @click.argument("arg", nargs=-1) def cmd(arg): - click.echo("arg:{}".format("|".join(arg))) + click.echo(f"arg:{'|'.join(arg)}") result = runner.invoke(cmd, []) assert result.exit_code == 0 @@ -196,7 +198,7 @@ def test_empty_nargs(runner): @click.command() @click.argument("arg", nargs=-1, required=True) def cmd2(arg): - click.echo("arg:{}".format("|".join(arg))) + click.echo(f"arg:{'|'.join(arg)}") result = runner.invoke(cmd2, []) assert result.exit_code == 2 diff --git a/tests/test_basic.py b/tests/test_basic.py index 9f9d71e..c33e3a4 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -108,7 +108,7 @@ def test_int_option(runner): @click.command() @click.option("--foo", default=42) def cli(foo): - click.echo("FOO:[{}]".format(foo * 2)) + click.echo(f"FOO:[{foo * 2}]") result = runner.invoke(cli, []) assert not result.exception @@ -192,7 +192,7 @@ def test_boolean_option(runner): result = runner.invoke(cli, ["--flag"]) assert not result.exception - assert result.output == "{}\n".format(not default) + assert result.output == f"{not default}\n" result = runner.invoke(cli, []) assert not result.exception assert result.output == f"{default}\n" @@ -307,8 +307,8 @@ def test_path_option(runner): @click.command() @click.option("-f", type=click.Path(exists=True)) def showtype(f): - click.echo("is_file={}".format(os.path.isfile(f))) - click.echo("is_dir={}".format(os.path.isdir(f))) + click.echo(f"is_file={os.path.isfile(f)}") + click.echo(f"is_dir={os.path.isdir(f)}") with runner.isolated_filesystem(): result = runner.invoke(showtype, ["-f", "xxx"]) @@ -321,7 +321,7 @@ def test_path_option(runner): @click.command() @click.option("-f", type=click.Path()) def exists(f): - click.echo("exists={}".format(os.path.exists(f))) + click.echo(f"exists={os.path.exists(f)}") with runner.isolated_filesystem(): result = runner.invoke(exists, ["-f", "xxx"]) diff --git a/tests/test_chain.py b/tests/test_chain.py index cf9b198..0462779 100644 --- a/tests/test_chain.py +++ b/tests/test_chain.py @@ -7,9 +7,8 @@ import click def debug(): click.echo( - "{}={}".format( - sys._getframe(1).f_code.co_name, "|".join(click.get_current_context().args) - ) + f"{sys._getframe(1).f_code.co_name}" + f"={'|'.join(click.get_current_context().args)}" ) diff --git a/tests/test_commands.py b/tests/test_commands.py index 1e19746..eace114 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -210,7 +210,7 @@ def test_object_propagation(runner): @cli.command() @click.pass_context def sync(ctx): - click.echo("Debug is {}".format("on" if ctx.obj["DEBUG"] else "off")) + click.echo(f"Debug is {'on' if ctx.obj['DEBUG'] else 'off'}") result = runner.invoke(cli, ["sync"]) assert result.exception is None @@ -264,7 +264,7 @@ def test_unprocessed_options(runner): @click.option("--verbose", "-v", count=True) def cli(verbose, args): click.echo(f"Verbosity: {verbose}") - click.echo("Args: {}".format("|".join(args))) + click.echo(f"Args: {'|'.join(args)}") result = runner.invoke(cli, ["-foo", "-vvvvx", "--muhaha", "x", "y", "-x"]) assert not result.exception diff --git a/tests/test_defaults.py b/tests/test_defaults.py index d55b1f4..0e438eb 100644 --- a/tests/test_defaults.py +++ b/tests/test_defaults.py @@ -32,8 +32,8 @@ def test_nargs_plus_multiple(runner): "--arg", default=((1, 2), (3, 4)), nargs=2, multiple=True, type=click.INT ) def cli(arg): - for item in arg: - click.echo("<{0[0]:d}|{0[1]:d}>".format(item)) + for a, b in arg: + click.echo(f"<{a:d}|{b:d}>") result = runner.invoke(cli, []) assert not result.exception diff --git a/tests/test_options.py b/tests/test_options.py index 95cdad5..1b9b27e 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -44,8 +44,8 @@ def test_nargs_tup_composite_mult(runner): @click.command() @click.option("--item", type=(str, int), multiple=True) def copy(item): - for item in item: - click.echo("name={0[0]} id={0[1]:d}".format(item)) + for name, id in item: + click.echo(f"name={name} id={id:d}") result = runner.invoke(copy, ["--item", "peter", "1", "--item", "max", "2"]) assert not result.exception @@ -421,12 +421,13 @@ def test_option_help_preserve_paragraphs(runner): result = runner.invoke(cmd, ["--help"],) assert result.exit_code == 0 + i = " " * 21 assert ( " -C, --config PATH Configuration file to use.\n" - "{i}\n" - "{i}If not given, the environment variable CONFIG_FILE is\n" - "{i}consulted and used if set. If neither are given, a default\n" - "{i}configuration file is loaded.".format(i=" " * 21) + f"{i}\n" + f"{i}If not given, the environment variable CONFIG_FILE is\n" + f"{i}consulted and used if set. If neither are given, a default\n" + f"{i}configuration file is loaded." ) in result.output diff --git a/tests/test_termui.py b/tests/test_termui.py index 616ab7d..7165023 100644 --- a/tests/test_termui.py +++ b/tests/test_termui.py @@ -247,7 +247,7 @@ def test_file_prompt_default_format(runner, file_kwargs): click.echo(f.name) result = runner.invoke(cli) - assert result.output == "file [{0}]: \n{0}\n".format(__file__) + assert result.output == f"file [{__file__}]: \n{__file__}\n" def test_secho(runner): @@ -354,7 +354,7 @@ def test_getchar_special_key_windows(runner, monkeypatch, special_key_char, key_ click._termui_impl.msvcrt, "getwch", lambda: ordered_inputs.pop() ) monkeypatch.setattr(click.termui, "_getchar", None) - assert click.getchar() == special_key_char + key_char + assert click.getchar() == f"{special_key_char}{key_char}" @pytest.mark.parametrize( diff --git a/tests/test_testing.py b/tests/test_testing.py index 5b2c813..7360473 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -125,7 +125,7 @@ def test_with_color(): assert not result.exception result = runner.invoke(cli, color=True) - assert result.output == "{}\n".format(click.style("hello world", fg="blue")) + assert result.output == f"{click.style('hello world', fg='blue')}\n" assert not result.exception @@ -213,7 +213,7 @@ def test_exit_code_and_output_from_sys_exit(): def test_env(): @click.command() def cli_env(): - click.echo("ENV={}".format(os.environ["TEST_CLICK_ENV"])) + click.echo(f"ENV={os.environ['TEST_CLICK_ENV']}") runner = CliRunner() |
