Some manual .format() -> f-strings

This commit is contained in:
Anthony Sottile 2020-01-12 11:13:39 -08:00
parent aefbe71765
commit 9000e9dd41
27 changed files with 133 additions and 173 deletions

View file

@ -1,7 +1,7 @@
import argparse
import functools
import logging
import pipes
import shlex
import sys
from typing import Any
from typing import Dict
@ -25,18 +25,17 @@ check_string_regex = cfgv.check_and(cfgv.check_string, cfgv.check_regex)
def check_type_tag(tag: str) -> None:
if tag not in ALL_TAGS:
raise cfgv.ValidationError(
'Type tag {!r} is not recognized. '
'Try upgrading identify and pre-commit?'.format(tag),
f'Type tag {tag!r} is not recognized. '
f'Try upgrading identify and pre-commit?',
)
def check_min_version(version: str) -> None:
if parse_version(version) > parse_version(C.VERSION):
raise cfgv.ValidationError(
'pre-commit version {} is required but version {} is installed. '
'Perhaps run `pip install --upgrade pre-commit`.'.format(
version, C.VERSION,
),
f'pre-commit version {version} is required but version '
f'{C.VERSION} is installed. '
f'Perhaps run `pip install --upgrade pre-commit`.',
)
@ -142,9 +141,7 @@ def _entry(modname: str) -> str:
runner, so to prevent issues with spaces and backslashes (on Windows)
it must be quoted here.
"""
return '{} -m pre_commit.meta_hooks.{}'.format(
pipes.quote(sys.executable), modname,
)
return f'{shlex.quote(sys.executable)} -m pre_commit.meta_hooks.{modname}'
def warn_unknown_keys_root(
@ -152,9 +149,7 @@ def warn_unknown_keys_root(
orig_keys: Sequence[str],
dct: Dict[str, str],
) -> None:
logger.warning(
'Unexpected key(s) present at root: {}'.format(', '.join(extra)),
)
logger.warning(f'Unexpected key(s) present at root: {", ".join(extra)}')
def warn_unknown_keys_repo(
@ -163,9 +158,7 @@ def warn_unknown_keys_repo(
dct: Dict[str, str],
) -> None:
logger.warning(
'Unexpected key(s) present on {}: {}'.format(
dct['repo'], ', '.join(extra),
),
f'Unexpected key(s) present on {dct["repo"]}: {", ".join(extra)}',
)

View file

@ -80,13 +80,12 @@ def _check_hooks_still_exist_at_rev(
hooks_missing = hooks - {hook['id'] for hook in manifest}
if hooks_missing:
raise RepositoryCannotBeUpdatedError(
'Cannot update because the tip of master is missing these hooks:\n'
'{}'.format(', '.join(sorted(hooks_missing))),
f'Cannot update because the tip of HEAD is missing these hooks:\n'
f'{", ".join(sorted(hooks_missing))}',
)
REV_LINE_RE = re.compile(r'^(\s+)rev:(\s*)([^\s#]+)(.*)(\r?\n)$', re.DOTALL)
REV_LINE_FMT = '{}rev:{}{}{}{}'
def _original_lines(
@ -126,9 +125,7 @@ def _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None:
comment = ''
else:
comment = match.group(4)
lines[idx] = REV_LINE_FMT.format(
match.group(1), match.group(2), new_rev, comment, match.group(5),
)
lines[idx] = f'{match[1]}rev:{match[2]}{new_rev}{comment}{match[5]}'
with open(path, 'w') as f:
f.write(''.join(lines))

View file

@ -89,8 +89,8 @@ def _install_hook_script(
os.remove(legacy_path)
elif os.path.exists(legacy_path):
output.write_line(
'Running in migration mode with existing hooks at {}\n'
'Use -f to use only pre-commit.'.format(legacy_path),
f'Running in migration mode with existing hooks at {legacy_path}\n'
f'Use -f to use only pre-commit.',
)
params = {
@ -110,7 +110,7 @@ def _install_hook_script(
hook_file.write(before + TEMPLATE_START)
for line in to_template.splitlines():
var = line.split()[0]
hook_file.write('{} = {!r}\n'.format(var, params[var]))
hook_file.write(f'{var} = {params[var]!r}\n')
hook_file.write(TEMPLATE_END + after)
make_executable(hook_path)

View file

@ -243,9 +243,10 @@ def _run_hooks(
output.write_line('All changes made by hooks:')
# args.color is a boolean.
# See user_color function in color.py
git_color_opt = 'always' if args.color else 'never'
subprocess.call((
'git', '--no-pager', 'diff', '--no-ext-diff',
'--color={}'.format({True: 'always', False: 'never'}[args.color]),
f'--color={git_color_opt}',
))
return retval
@ -282,8 +283,8 @@ def run(
return 1
if _has_unstaged_config(config_file) and not no_stash:
logger.error(
'Your pre-commit configuration is unstaged.\n'
'`git add {}` to fix this.'.format(config_file),
f'Your pre-commit configuration is unstaged.\n'
f'`git add {config_file}` to fix this.',
)
return 1
@ -308,9 +309,7 @@ def run(
if args.hook and not hooks:
output.write_line(
'No hook with id `{}` in stage `{}`'.format(
args.hook, args.hook_stage,
),
f'No hook with id `{args.hook}` in stage `{args.hook_stage}`',
)
return 1

View file

@ -183,13 +183,11 @@ def check_for_cygwin_mismatch() -> None:
if is_cygwin_python ^ is_cygwin_git:
exe_type = {True: '(cygwin)', False: '(windows)'}
logger.warn(
'pre-commit has detected a mix of cygwin python / git\n'
'This combination is not supported, it is likely you will '
'receive an error later in the program.\n'
'Make sure to use cygwin git+python while using cygwin\n'
'These can be installed through the cygwin installer.\n'
' - python {}\n'
' - git {}\n'.format(
exe_type[is_cygwin_python], exe_type[is_cygwin_git],
),
f'pre-commit has detected a mix of cygwin python / git\n'
f'This combination is not supported, it is likely you will '
f'receive an error later in the program.\n'
f'Make sure to use cygwin git+python while using cygwin\n'
f'These can be installed through the cygwin installer.\n'
f' - python {exe_type[is_cygwin_python]}\n'
f' - git {exe_type[is_cygwin_git]}\n',
)

View file

@ -81,7 +81,7 @@ def install_environment(
def get_docker_user() -> str: # pragma: windows no cover
try:
return '{}:{}'.format(os.getuid(), os.getgid())
return f'{os.getuid()}:{os.getgid()}'
except AttributeError:
return '1000:1000'
@ -94,7 +94,7 @@ def docker_cmd() -> Tuple[str, ...]: # pragma: windows no cover
# https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from
# The `Z` option tells Docker to label the content with a private
# unshared label. Only the current container can use a private volume.
'-v', '{}:/src:rw,Z'.format(os.getcwd()),
'-v', f'{os.getcwd()}:/src:rw,Z',
'--workdir', '/src',
)

View file

@ -51,8 +51,8 @@ def assert_no_additional_deps(
) -> None:
if additional_deps:
raise AssertionError(
'For now, pre-commit does not support '
'additional_dependencies for {}'.format(lang),
f'For now, pre-commit does not support '
f'additional_dependencies for {lang}',
)

View file

@ -33,7 +33,7 @@ def _envdir(prefix: Prefix, version: str) -> str:
def get_env_patch(venv: str) -> PatchesT: # pragma: windows no cover
if sys.platform == 'cygwin': # pragma: no cover
_, win_venv, _ = cmd_output('cygpath', '-w', venv)
install_prefix = r'{}\bin'.format(win_venv.strip())
install_prefix = fr'{win_venv.strip()}\bin'
lib_dir = 'lib'
elif sys.platform == 'win32': # pragma: no cover
install_prefix = bin_dir(venv)

View file

@ -39,7 +39,7 @@ def _process_filename_at_once(pattern: Pattern[bytes], filename: str) -> int:
if match:
retv = 1
line_no = contents[:match.start()].count(b'\n')
output.write('{}:{}:'.format(filename, line_no + 1))
output.write(f'{filename}:{line_no + 1}:')
matched_lines = match.group().split(b'\n')
matched_lines[0] = contents.split(b'\n')[line_no]

View file

@ -47,10 +47,10 @@ def _find_by_py_launcher(
version: str,
) -> Optional[str]: # pragma: no cover (windows only)
if version.startswith('python'):
num = version[len('python'):]
try:
return cmd_output(
'py', '-{}'.format(version[len('python'):]),
'-c', 'import sys; print(sys.executable)',
'py', f'-{num}', '-c', 'import sys; print(sys.executable)',
)[1].strip()
except CalledProcessError:
pass
@ -88,7 +88,7 @@ def get_default_version() -> str: # pragma: no cover (platform dependent)
return exe
# Next try the `pythonX.X` executable
exe = 'python{}.{}'.format(*sys.version_info)
exe = f'python{sys.version_info[0]}.{sys.version_info[1]}'
if find_executable(exe):
return exe
@ -96,7 +96,8 @@ def get_default_version() -> str: # pragma: no cover (platform dependent)
return exe
# Give a best-effort try for windows
if os.path.exists(r'C:\{}\python.exe'.format(exe.replace('.', ''))):
default_folder_name = exe.replace('.', '')
if os.path.exists(fr'C:\{default_folder_name}\python.exe'):
return exe
# We tried!
@ -135,7 +136,8 @@ def norm_version(version: str) -> str:
# If it is in the form pythonx.x search in the default
# place on windows
if version.startswith('python'):
return r'C:\{}\python.exe'.format(version.replace('.', ''))
default_folder_name = version.replace('.', '')
return fr'C:\{default_folder_name}\python.exe'
# Otherwise assume it is a path
return os.path.expanduser(version)

View file

@ -21,16 +21,12 @@ class LoggingHandler(logging.Handler):
self.use_color = use_color
def emit(self, record: logging.LogRecord) -> None:
output.write_line(
'{} {}'.format(
color.format_color(
f'[{record.levelname}]',
LOG_LEVEL_COLORS[record.levelname],
self.use_color,
),
record.getMessage(),
),
level_msg = color.format_color(
f'[{record.levelname}]',
LOG_LEVEL_COLORS[record.levelname],
self.use_color,
)
output.write_line(f'{level_msg} {record.getMessage()}')
@contextlib.contextmanager

View file

@ -34,8 +34,7 @@ def check_useless_excludes(config_file: str) -> int:
exclude = config['exclude']
if not exclude_matches_any(classifier.filenames, '', exclude):
print(
'The global exclude pattern {!r} does not match any files'
.format(exclude),
f'The global exclude pattern {exclude!r} does not match any files',
)
retv = 1
@ -50,8 +49,8 @@ def check_useless_excludes(config_file: str) -> int:
include, exclude = hook['files'], hook['exclude']
if not exclude_matches_any(names, include, exclude):
print(
'The exclude pattern {!r} for {} does not match any files'
.format(exclude, hook['id']),
f'The exclude pattern {exclude!r} for {hook["id"]} does '
f'not match any files',
)
retv = 1

View file

@ -54,12 +54,9 @@ def get_hook_message(
assert end_msg is not None
assert end_color is not None
assert use_color is not None
return '{}{}{}{}\n'.format(
start,
'.' * (cols - len(start) - len(postfix) - len(end_msg) - 1),
postfix,
color.format_color(end_msg, end_color, use_color),
)
dots = '.' * (cols - len(start) - len(postfix) - len(end_msg) - 1)
end = color.format_color(end_msg, end_color, use_color)
return f'{start}{dots}{postfix}{end}\n'
def write(s: str, stream: IO[bytes] = sys.stdout.buffer) -> None:

View file

@ -137,8 +137,8 @@ class Hook(NamedTuple):
extra_keys = set(dct) - set(_KEYS)
if extra_keys:
logger.warning(
'Unexpected key(s) present on {} => {}: '
'{}'.format(src, dct['id'], ', '.join(sorted(extra_keys))),
f'Unexpected key(s) present on {src} => {dct["id"]}: '
f'{", ".join(sorted(extra_keys))}',
)
return cls(src=src, prefix=prefix, **{k: dct[k] for k in _KEYS})
@ -154,11 +154,9 @@ def _hook(
version = ret['minimum_pre_commit_version']
if parse_version(version) > parse_version(C.VERSION):
logger.error(
'The hook `{}` requires pre-commit version {} but version {} '
'is installed. '
'Perhaps run `pip install --upgrade pre-commit`.'.format(
ret['id'], version, C.VERSION,
),
f'The hook `{ret["id"]}` requires pre-commit version {version} '
f'but version {C.VERSION} is installed. '
f'Perhaps run `pip install --upgrade pre-commit`.',
)
exit(1)
@ -210,10 +208,9 @@ def _cloned_repository_hooks(
for hook in repo_config['hooks']:
if hook['id'] not in by_id:
logger.error(
'`{}` is not present in repository {}. '
'Typo? Perhaps it is introduced in a newer version? '
'Often `pre-commit autoupdate` fixes this.'
.format(hook['id'], repo),
f'`{hook["id"]}` is not present in repository {repo}. '
f'Typo? Perhaps it is introduced in a newer version? '
f'Often `pre-commit autoupdate` fixes this.',
)
exit(1)

View file

@ -52,12 +52,11 @@ def _norm_exe(exe: str) -> Tuple[str, ...]:
def _run_legacy() -> Tuple[int, bytes]:
if __file__.endswith('.legacy'):
raise SystemExit(
"bug: pre-commit's script is installed in migration mode\n"
'run `pre-commit install -f --hook-type {}` to fix this\n\n'
'Please report this bug at '
'https://github.com/pre-commit/pre-commit/issues'.format(
HOOK_TYPE,
),
f"bug: pre-commit's script is installed in migration mode\n"
f'run `pre-commit install -f --hook-type {HOOK_TYPE}` to fix '
f'this\n\n'
f'Please report this bug at '
f'https://github.com/pre-commit/pre-commit/issues',
)
if HOOK_TYPE == 'pre-push':
@ -82,20 +81,17 @@ def _validate_config() -> None:
if os.path.isfile(cfg):
pass
elif SKIP_ON_MISSING_CONFIG or os.getenv('PRE_COMMIT_ALLOW_NO_CONFIG'):
print(
'`{}` config file not found. '
'Skipping `pre-commit`.'.format(CONFIG),
)
print(f'`{CONFIG}` config file not found. Skipping `pre-commit`.')
raise EarlyExit()
else:
raise FatalError(
'No {} file was found\n'
'- To temporarily silence this, run '
'`PRE_COMMIT_ALLOW_NO_CONFIG=1 git ...`\n'
'- To permanently silence this, install pre-commit with the '
'--allow-missing-config option\n'
'- To uninstall pre-commit run '
'`pre-commit uninstall`'.format(CONFIG),
f'No {CONFIG} file was found\n'
f'- To temporarily silence this, run '
f'`PRE_COMMIT_ALLOW_NO_CONFIG=1 git ...`\n'
f'- To permanently silence this, install pre-commit with the '
f'--allow-missing-config option\n'
f'- To uninstall pre-commit run '
f'`pre-commit uninstall`',
)

View file

@ -48,7 +48,7 @@ def _unstaged_changes_cleared(patch_dir: str) -> Generator[None, None, None]:
retcode=None,
)
if retcode and diff_stdout_binary.strip():
patch_filename = 'patch{}'.format(int(time.time()))
patch_filename = f'patch{int(time.time())}'
patch_filename = os.path.join(patch_dir, patch_filename)
logger.warning('Unstaged files detected.')
logger.info(

View file

@ -102,7 +102,7 @@ class Store:
@classmethod
def db_repo_name(cls, repo: str, deps: Sequence[str]) -> str:
if deps:
return '{}:{}'.format(repo, ','.join(sorted(deps)))
return f'{repo}:{",".join(sorted(deps))}'
else:
return repo

View file

@ -105,11 +105,9 @@ class CalledProcessError(RuntimeError):
return b' (none)'
return b''.join((
'command: {!r}\n'
'return code: {}\n'
'expected return code: {}\n'.format(
self.cmd, self.returncode, self.expected_returncode,
).encode(),
f'command: {self.cmd!r}\n'.encode(),
f'return code: {self.returncode}\n'.encode(),
f'expected return code: {self.expected_returncode}\n'.encode(),
b'stdout:', _indent_or_none(self.stdout), b'\n',
b'stderr:', _indent_or_none(self.stderr),
))

View file

@ -1,13 +1,7 @@
#!/usr/bin/env python
import sys
def main():
for i in range(6):
f = sys.stdout if i % 2 == 0 else sys.stderr
f.write(f'{i}\n')
f.flush()
if __name__ == '__main__':
exit(main())
#!/usr/bin/env bash
echo 0
echo 1 1>&2
echo 2
echo 3 1>&2
echo 4
echo 5 1>&2

View file

@ -1,12 +1,11 @@
#!/usr/bin/env python
import sys
def main():
print('stdin: {}'.format(sys.stdin.isatty()))
print('stdout: {}'.format(sys.stdout.isatty()))
print('stderr: {}'.format(sys.stderr.isatty()))
if __name__ == '__main__':
exit(main())
#!/usr/bin/env bash
t() {
if [ -t "$1" ]; then
echo "$2: True"
else
echo "$2: False"
fi
}
t 0 stdin
t 1 stdout
t 2 stderr

View file

@ -291,13 +291,11 @@ def test_minimum_pre_commit_version_failing():
cfg = {'repos': [], 'minimum_pre_commit_version': '999'}
cfgv.validate(cfg, CONFIG_SCHEMA)
assert str(excinfo.value) == (
'\n'
'==> At Config()\n'
'==> At key: minimum_pre_commit_version\n'
'=====> pre-commit version 999 is required but version {} is '
'installed. Perhaps run `pip install --upgrade pre-commit`.'.format(
C.VERSION,
)
f'\n'
f'==> At Config()\n'
f'==> At key: minimum_pre_commit_version\n'
f'=====> pre-commit version 999 is required but version {C.VERSION} '
f'is installed. Perhaps run `pip install --upgrade pre-commit`.'
)

View file

@ -1,4 +1,4 @@
import pipes
import shlex
import pytest
@ -118,12 +118,12 @@ def test_rev_info_update_does_not_freeze_if_already_sha(out_of_date):
def test_autoupdate_up_to_date_repo(up_to_date, tmpdir, store):
contents = (
'repos:\n'
'- repo: {}\n'
' rev: {}\n'
' hooks:\n'
' - id: foo\n'
).format(up_to_date, git.head_rev(up_to_date))
f'repos:\n'
f'- repo: {up_to_date}\n'
f' rev: {git.head_rev(up_to_date)}\n'
f' hooks:\n'
f' - id: foo\n'
)
cfg = tmpdir.join(C.CONFIG_FILE)
cfg.write(contents)
@ -278,7 +278,7 @@ def test_loses_formatting_when_not_detectable(out_of_date, store, tmpdir):
' ],\n'
' }}\n'
']\n'.format(
pipes.quote(out_of_date.path), out_of_date.original_rev,
shlex.quote(out_of_date.path), out_of_date.original_rev,
)
)
cfg = tmpdir.join(C.CONFIG_FILE)
@ -286,12 +286,12 @@ def test_loses_formatting_when_not_detectable(out_of_date, store, tmpdir):
assert autoupdate(str(cfg), store, freeze=False, tags_only=False) == 0
expected = (
'repos:\n'
'- repo: {}\n'
' rev: {}\n'
' hooks:\n'
' - id: foo\n'
).format(out_of_date.path, out_of_date.head_rev)
f'repos:\n'
f'- repo: {out_of_date.path}\n'
f' rev: {out_of_date.head_rev}\n'
f' hooks:\n'
f' - id: foo\n'
)
assert cfg.read() == expected
@ -358,12 +358,12 @@ def test_hook_disppearing_repo_raises(hook_disappearing, store):
def test_autoupdate_hook_disappearing_repo(hook_disappearing, tmpdir, store):
contents = (
'repos:\n'
'- repo: {}\n'
' rev: {}\n'
' hooks:\n'
' - id: foo\n'
).format(hook_disappearing.path, hook_disappearing.original_rev)
f'repos:\n'
f'- repo: {hook_disappearing.path}\n'
f' rev: {hook_disappearing.original_rev}\n'
f' hooks:\n'
f' - id: foo\n'
)
cfg = tmpdir.join(C.CONFIG_FILE)
cfg.write(contents)

View file

@ -52,11 +52,11 @@ def test_shebang_posix_not_on_path():
def test_shebang_posix_on_path(tmpdir):
tmpdir.join('python{}'.format(sys.version_info[0])).ensure()
tmpdir.join(f'python{sys.version_info[0]}').ensure()
with mock.patch.object(sys, 'platform', 'posix'):
with mock.patch.object(os, 'defpath', tmpdir.strpath):
expected = '#!/usr/bin/env python{}'.format(sys.version_info[0])
expected = f'#!/usr/bin/env python{sys.version_info[0]}'
assert shebang() == expected

View file

@ -1,5 +1,5 @@
import os.path
import pipes
import shlex
import sys
import time
from unittest import mock
@ -580,8 +580,7 @@ def test_lots_of_files(store, tempdir_factory):
# Write a crap ton of files
for i in range(400):
filename = '{}{}'.format('a' * 100, i)
open(filename, 'w').close()
open(f'{"a" * 100}{i}', 'w').close()
cmd_output('git', 'add', '.')
install(C.CONFIG_FILE, store, hook_types=['pre-commit'])
@ -673,7 +672,7 @@ def test_local_hook_passes(cap_out, store, repo_with_passing_hook):
'id': 'identity-copy',
'name': 'identity-copy',
'entry': '{} -m pre_commit.meta_hooks.identity'.format(
pipes.quote(sys.executable),
shlex.quote(sys.executable),
),
'language': 'system',
'files': r'\.py$',
@ -893,7 +892,7 @@ def test_args_hook_only(cap_out, store, repo_with_passing_hook):
'id': 'identity-copy',
'name': 'identity-copy',
'entry': '{} -m pre_commit.meta_hooks.identity'.format(
pipes.quote(sys.executable),
shlex.quote(sys.executable),
),
'language': 'system',
'files': r'\.py$',

View file

@ -99,9 +99,7 @@ def test_log_and_exit(cap_out, mock_store_dir):
printed = cap_out.get()
log_file = os.path.join(mock_store_dir, 'pre-commit.log')
assert printed == (
'msg: FatalError: hai\n' 'Check the log at {}\n'.format(log_file)
)
assert printed == f'msg: FatalError: hai\nCheck the log at {log_file}\n'
assert os.path.exists(log_file)
with open(log_file) as f:

View file

@ -1,5 +1,5 @@
import os.path
import pipes
import shlex
from pre_commit.languages.ruby import _install_rbenv
from pre_commit.prefix import Prefix
@ -21,7 +21,7 @@ def test_install_rbenv(tempdir_factory):
cmd_output(
'bash', '-c',
'. {} && rbenv --help'.format(
pipes.quote(prefix.path('rbenv-default', 'bin', 'activate')),
shlex.quote(prefix.path('rbenv-default', 'bin', 'activate')),
),
)
@ -35,6 +35,6 @@ def test_install_rbenv_with_version(tempdir_factory):
cmd_output(
'bash', '-c',
'. {} && rbenv install --help'.format(
pipes.quote(prefix.path('rbenv-1.9.3p547', 'bin', 'activate')),
shlex.quote(prefix.path('rbenv-1.9.3p547', 'bin', 'activate')),
),
)

View file

@ -805,9 +805,9 @@ def test_hook_id_not_present(tempdir_factory, store, fake_log_handler):
with pytest.raises(SystemExit):
_get_hook(config, store, 'i-dont-exist')
assert fake_log_handler.handle.call_args[0][0].msg == (
'`i-dont-exist` is not present in repository file://{}. '
'Typo? Perhaps it is introduced in a newer version? '
'Often `pre-commit autoupdate` fixes this.'.format(path)
f'`i-dont-exist` is not present in repository file://{path}. '
f'Typo? Perhaps it is introduced in a newer version? '
f'Often `pre-commit autoupdate` fixes this.'
)