style: Use f-strings wherever possible

They're faster.
This commit is contained in:
Dimitri Papadopoulos 2023-09-30 14:41:13 +02:00 committed by Adrien Vergé
parent 816d575228
commit f63e56fd98
12 changed files with 115 additions and 132 deletions

View File

@ -286,8 +286,8 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run(('-d', 'default', '-f', 'parsable', path))
expected_out = ('%s:1:1: [warning] missing document start "---" '
'(document-start)\n' % path)
expected_out = (f'{path}:1:1: [warning] missing document start "---" '
f'(document-start)\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (0, expected_out, ''))
@ -424,9 +424,9 @@ class CommandLineTestCase(unittest.TestCase):
cli.run(('-f', 'parsable', path))
self.assertEqual(ctx.returncode, 1)
self.assertEqual(ctx.stdout, (
'%s:2:4: [error] trailing spaces (trailing-spaces)\n'
'%s:3:4: [error] no new line character at the end of file '
'(new-line-at-end-of-file)\n' % (path, path)))
f'{path}:2:4: [error] trailing spaces (trailing-spaces)\n'
f'{path}:3:4: [error] no new line character at the end of file '
f'(new-line-at-end-of-file)\n'))
self.assertEqual(ctx.stderr, '')
def test_run_one_warning(self):
@ -476,8 +476,8 @@ class CommandLineTestCase(unittest.TestCase):
cli.run(['-f', 'parsable'] + items)
self.assertEqual((ctx.returncode, ctx.stderr), (1, ''))
self.assertEqual(ctx.stdout, (
'%s:3:1: [error] duplication of key "key" in mapping '
'(key-duplicates)\n') % path)
f'{path}:3:1: [error] duplication of key "key" in mapping '
f'(key-duplicates)\n'))
def test_run_piped_output_nocolor(self):
path = os.path.join(self.wd, 'a.yaml')
@ -486,11 +486,11 @@ class CommandLineTestCase(unittest.TestCase):
cli.run((path, ))
self.assertEqual((ctx.returncode, ctx.stderr), (1, ''))
self.assertEqual(ctx.stdout, (
'%s\n'
' 2:4 error trailing spaces (trailing-spaces)\n'
' 3:4 error no new line character at the end of file '
'(new-line-at-end-of-file)\n'
'\n' % path))
f'{path}\n'
f' 2:4 error trailing spaces (trailing-spaces)\n'
f' 3:4 error no new line character at the end of file '
f'(new-line-at-end-of-file)\n'
f'\n'))
def test_run_default_format_output_in_tty(self):
path = os.path.join(self.wd, 'a.yaml')
@ -517,13 +517,13 @@ class CommandLineTestCase(unittest.TestCase):
output.close()
self.assertEqual(out, (
'\033[4m%s\033[0m\n'
' \033[2m2:4\033[0m \033[31merror\033[0m '
'trailing spaces \033[2m(trailing-spaces)\033[0m\n'
' \033[2m3:4\033[0m \033[31merror\033[0m '
'no new line character at the end of file '
'\033[2m(new-line-at-end-of-file)\033[0m\n'
'\n' % path))
f'\033[4m{path}\033[0m\n'
f' \033[2m2:4\033[0m \033[31merror\033[0m '
f'trailing spaces \033[2m(trailing-spaces)\033[0m\n'
f' \033[2m3:4\033[0m \033[31merror\033[0m '
f'no new line character at the end of file '
f'\033[2m(new-line-at-end-of-file)\033[0m\n'
f'\n'))
def test_run_default_format_output_without_tty(self):
path = os.path.join(self.wd, 'a.yaml')
@ -531,11 +531,11 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run((path, ))
expected_out = (
'%s\n'
' 2:4 error trailing spaces (trailing-spaces)\n'
' 3:4 error no new line character at the end of file '
'(new-line-at-end-of-file)\n'
'\n' % path)
f'{path}\n'
f' 2:4 error trailing spaces (trailing-spaces)\n'
f' 3:4 error no new line character at the end of file '
f'(new-line-at-end-of-file)\n'
f'\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
@ -545,11 +545,11 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run((path, '--format', 'auto'))
expected_out = (
'%s\n'
' 2:4 error trailing spaces (trailing-spaces)\n'
' 3:4 error no new line character at the end of file '
'(new-line-at-end-of-file)\n'
'\n' % path)
f'{path}\n'
f' 2:4 error trailing spaces (trailing-spaces)\n'
f' 3:4 error no new line character at the end of file '
f'(new-line-at-end-of-file)\n'
f'\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
@ -559,13 +559,13 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run((path, '--format', 'colored'))
expected_out = (
'\033[4m%s\033[0m\n'
' \033[2m2:4\033[0m \033[31merror\033[0m '
'trailing spaces \033[2m(trailing-spaces)\033[0m\n'
' \033[2m3:4\033[0m \033[31merror\033[0m '
'no new line character at the end of file '
'\033[2m(new-line-at-end-of-file)\033[0m\n'
'\n' % path)
f'\033[4m{path}\033[0m\n'
f' \033[2m2:4\033[0m \033[31merror\033[0m '
f'trailing spaces \033[2m(trailing-spaces)\033[0m\n'
f' \033[2m3:4\033[0m \033[31merror\033[0m '
f'no new line character at the end of file '
f'\033[2m(new-line-at-end-of-file)\033[0m\n'
f'\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
@ -575,10 +575,10 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run((path, '--format', 'colored'))
expected_out = (
'\033[4m%s\033[0m\n'
' \033[2m1:1\033[0m \033[33mwarning\033[0m '
'missing document start "---" \033[2m(document-start)\033[0m\n'
'\n' % path)
f'\033[4m{path}\033[0m\n'
f' \033[2m1:1\033[0m \033[33mwarning\033[0m '
f'missing document start "---" \033[2m(document-start)\033[0m\n'
f'\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (0, expected_out, ''))
@ -588,13 +588,12 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run((path, '--format', 'github'))
expected_out = (
'::group::%s\n'
'::error file=%s,line=2,col=4::2:4 [trailing-spaces] trailing'
' spaces\n'
'::error file=%s,line=3,col=4::3:4 [new-line-at-end-of-file] no'
' new line character at the end of file\n'
'::endgroup::\n\n'
% (path, path, path))
f'::group::{path}\n'
f'::error file={path},line=2,col=4::2:4 [trailing-spaces] trailing'
f' spaces\n'
f'::error file={path},line=3,col=4::3:4 [new-line-at-end-of-file]'
f' no new line character at the end of file\n'
f'::endgroup::\n\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
@ -608,13 +607,12 @@ class CommandLineTestCase(unittest.TestCase):
os.environ['GITHUB_WORKFLOW'] = 'something'
cli.run((path, ))
expected_out = (
'::group::%s\n'
'::error file=%s,line=2,col=4::2:4 [trailing-spaces] trailing'
' spaces\n'
'::error file=%s,line=3,col=4::3:4 [new-line-at-end-of-file] no'
' new line character at the end of file\n'
'::endgroup::\n\n'
% (path, path, path))
f'::group::{path}\n'
f'::error file={path},line=2,col=4::2:4 [trailing-spaces] trailing'
f' spaces\n'
f'::error file={path},line=3,col=4::3:4 [new-line-at-end-of-file]'
f' no new line character at the end of file\n'
f'::endgroup::\n\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
@ -640,11 +638,11 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run((path, '--no-warnings', '-f', 'auto'))
expected_out = (
'%s\n'
' 2:4 error trailing spaces (trailing-spaces)\n'
' 3:4 error no new line character at the end of file '
'(new-line-at-end-of-file)\n'
'\n' % path)
f'{path}\n'
f' 2:4 error trailing spaces (trailing-spaces)\n'
f' 3:4 error no new line character at the end of file '
f'(new-line-at-end-of-file)\n'
f'\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))
@ -671,10 +669,10 @@ class CommandLineTestCase(unittest.TestCase):
with RunContext(self) as ctx:
cli.run(('-d', 'rules:\n new-lines:\n type: unix', path))
expected_out = (
'%s\n'
' 1:4 error wrong new line character: expected \\n'
' (new-lines)\n'
'\n' % path)
f'{path}\n'
f' 1:4 error wrong new line character: expected \\n'
f' (new-lines)\n'
f'\n')
self.assertEqual(
(ctx.returncode, ctx.stdout, ctx.stderr), (1, expected_out, ''))

View File

@ -39,7 +39,7 @@ from tests.common import RuleTestCase
# text = text.replace('\u21d4', '') # byte order mark
# text = text.replace('\u2192', '\t') # right arrow
# text = text.replace('\u00b0', '') # empty scalar
# with open('tests/yaml-1.2-spec-examples/%s' % id, 'w',
# with open(f'tests/yaml-1.2-spec-examples/{id}', 'w',
# encoding='utf-8') as g:
# g.write(text)

View File

@ -49,52 +49,41 @@ def supports_color():
class Format:
@staticmethod
def parsable(problem, filename):
return ('%(file)s:%(line)s:%(column)s: [%(level)s] %(message)s' %
{'file': filename,
'line': problem.line,
'column': problem.column,
'level': problem.level,
'message': problem.message})
return (f'{filename}:{problem.line}:{problem.column}: '
f'[{problem.level}] {problem.message}')
@staticmethod
def standard(problem, filename):
line = ' %d:%d' % (problem.line, problem.column)
line = f' {problem.line}:{problem.column}'
line += max(12 - len(line), 0) * ' '
line += problem.level
line += max(21 - len(line), 0) * ' '
line += problem.desc
if problem.rule:
line += ' (%s)' % problem.rule
line += f' ({problem.rule})'
return line
@staticmethod
def standard_color(problem, filename):
line = ' \033[2m%d:%d\033[0m' % (problem.line, problem.column)
line = f' \033[2m{problem.line}:{problem.column}\033[0m'
line += max(20 - len(line), 0) * ' '
if problem.level == 'warning':
line += '\033[33m%s\033[0m' % problem.level
line += f'\033[33m{problem.level}\033[0m'
else:
line += '\033[31m%s\033[0m' % problem.level
line += f'\033[31m{problem.level}\033[0m'
line += max(38 - len(line), 0) * ' '
line += problem.desc
if problem.rule:
line += ' \033[2m(%s)\033[0m' % problem.rule
line += f' \033[2m({problem.rule})\033[0m'
return line
@staticmethod
def github(problem, filename):
line = '::'
line += problem.level
line += ' file=' + filename + ','
line += 'line=' + format(problem.line) + ','
line += 'col=' + format(problem.column)
line += '::'
line += format(problem.line)
line += ':'
line += format(problem.column)
line += ' '
line = f'::{problem.level} file={format(filename)},' \
f'line={format(problem.line)},col={format(problem.column)}' \
f'::{format(problem.line)}:{format(problem.column)} '
if problem.rule:
line += '[' + problem.rule + '] '
line += f'[{problem.rule}] '
line += problem.desc
return line
@ -118,12 +107,12 @@ def show_problems(problems, file, args_format, no_warn):
print(Format.parsable(problem, file))
elif args_format == 'github':
if first:
print('::group::%s' % file)
print(f'::group::{file}')
first = False
print(Format.github(problem, file))
elif args_format == 'colored':
if first:
print('\033[4m%s\033[0m' % file)
print(f'\033[4m{file}\033[0m')
first = False
print(Format.standard_color(problem, file))
else:
@ -184,7 +173,7 @@ def run(argv=None):
action='store_true',
help='output only error level problems')
parser.add_argument('-v', '--version', action='version',
version='{} {}'.format(APP_NAME, APP_VERSION))
version=f'{APP_NAME} {APP_VERSION}')
args = parser.parse_args(argv)
@ -202,7 +191,7 @@ def run(argv=None):
try:
if args.config_data is not None:
if args.config_data != '' and ':' not in args.config_data:
args.config_data = 'extends: ' + args.config_data
args.config_data = f'extends: {args.config_data}'
conf = YamlLintConfig(content=args.config_data)
elif args.config_file is not None:
conf = YamlLintConfig(file=args.config_file)

View File

@ -76,7 +76,7 @@ class YamlLintConfig:
try:
conf = yaml.safe_load(raw_content)
except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e)
raise YamlLintConfigError(f'invalid config: {e}')
if not isinstance(conf, dict):
raise YamlLintConfigError('invalid config: not a dict')
@ -95,7 +95,7 @@ class YamlLintConfig:
try:
self.extend(base)
except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e)
raise YamlLintConfigError(f'invalid config: {e}')
if 'ignore' in conf and 'ignore-from-file' in conf:
raise YamlLintConfigError(
@ -143,7 +143,7 @@ class YamlLintConfig:
try:
rule = yamllint.rules.get(id)
except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e)
raise YamlLintConfigError(f'invalid config: {e}')
self.rules[id] = validate_rule_conf(rule, self.rules[id])
@ -179,16 +179,16 @@ def validate_rule_conf(rule, conf):
continue
if optkey not in options:
raise YamlLintConfigError(
'invalid config: unknown option "%s" for rule "%s"' %
(optkey, rule.ID))
f'invalid config: unknown option "{optkey}" for rule '
f'"{rule.ID}"')
# Example: CONF = {option: (bool, 'mixed')}
# → {option: true} → {option: mixed}
if isinstance(options[optkey], tuple):
if (conf[optkey] not in options[optkey] and
type(conf[optkey]) not in options[optkey]):
raise YamlLintConfigError(
'invalid config: option "%s" of "%s" should be in %s'
% (optkey, rule.ID, options[optkey]))
f'invalid config: option "{optkey}" of "{rule.ID}" '
f'should be in {options[optkey]}')
# Example: CONF = {option: ['flag1', 'flag2', int]}
# → {option: [flag1]} → {option: [42, flag1, flag2]}
elif isinstance(options[optkey], list):
@ -197,16 +197,15 @@ def validate_rule_conf(rule, conf):
type(flag) not in options[optkey]
for flag in conf[optkey])):
raise YamlLintConfigError(
('invalid config: option "%s" of "%s" should only '
'contain values in %s')
% (optkey, rule.ID, str(options[optkey])))
f'invalid config: option "{optkey}" of "{rule.ID}" '
f'should only contain values in {options[optkey]}')
# Example: CONF = {option: int}
# → {option: 42}
else:
if not isinstance(conf[optkey], options[optkey]):
raise YamlLintConfigError(
'invalid config: option "%s" of "%s" should be %s'
% (optkey, rule.ID, options[optkey].__name__))
f'invalid config: option "{optkey}" of "{rule.ID}" '
f'should be {options[optkey].__name__}')
for optkey in options:
if optkey not in conf:
conf[optkey] = options_default[optkey]
@ -214,12 +213,11 @@ def validate_rule_conf(rule, conf):
if hasattr(rule, 'VALIDATE'):
res = rule.VALIDATE(conf)
if res:
raise YamlLintConfigError('invalid config: %s: %s' %
(rule.ID, res))
raise YamlLintConfigError(f'invalid config: {rule.ID}: {res}')
else:
raise YamlLintConfigError(('invalid config: rule "%s": should be '
'either "enable", "disable" or a dict')
% rule.ID)
raise YamlLintConfigError(
f'invalid config: rule "{rule.ID}": should be either "enable", '
f'"disable" or a dict')
return conf
@ -228,7 +226,7 @@ def get_extended_config_file(name):
# Is it a standard conf shipped with yamllint...
if '/' not in name:
std_conf = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'conf', name + '.yaml')
'conf', f'{name}.yaml')
if os.path.isfile(std_conf):
return std_conf

View File

@ -50,7 +50,7 @@ class LintProblem:
@property
def message(self):
if self.rule is not None:
return '{} ({})'.format(self.desc, self.rule)
return f'{self.desc} ({self.rule})'
return self.desc
def __eq__(self, other):
@ -63,7 +63,7 @@ class LintProblem:
(self.line == other.line and self.column < other.column))
def __repr__(self):
return '%d:%d: %s' % (self.line, self.column, self.message)
return f'{self.line}:{self.column}: {self.message}'
def get_cosmetic_problems(buffer, conf, filepath):

View File

@ -68,6 +68,6 @@ _RULES = {
def get(id):
if id not in _RULES:
raise ValueError('no such rule: "%s"' % id)
raise ValueError(f'no such rule: "{id}"')
return _RULES[id]

View File

@ -113,5 +113,5 @@ def check(conf, line):
max = conf['max-end']
if blank_lines > max:
yield LintProblem(line.line_no, 1, 'too many blank lines (%d > %d)'
% (blank_lines, max))
yield LintProblem(line.line_no, 1,
f'too many blank lines ({blank_lines} > {max})')

View File

@ -227,7 +227,7 @@ class Parent:
self.implicit_block_seq = False
def __repr__(self):
return '%s:%d' % (labels[self.type], self.indent)
return f'{labels[self.type]}:{self.indent}'
def check_scalar_indentation(conf, token, context):
@ -303,8 +303,8 @@ def check_scalar_indentation(conf, token, context):
if indent != expected_indent:
yield LintProblem(line_no, indent + 1,
'wrong indentation: expected %d but found %d' %
(expected_indent, indent))
f'wrong indentation: expected {expected_indent}'
f'but found {indent}')
def _check(conf, token, prev, next, nextnext, context):
@ -342,11 +342,11 @@ def _check(conf, token, prev, next, nextnext, context):
if found_indentation != expected:
if expected < 0:
message = 'wrong indentation: expected at least %d' % \
(found_indentation + 1)
message = f'wrong indentation: expected at least ' \
f'{found_indentation + 1}'
else:
message = 'wrong indentation: expected %d but found %d' % \
(expected, found_indentation)
message = f'wrong indentation: expected {expected} but ' \
f'found {found_indentation}'
yield LintProblem(token.start_mark.line + 1,
found_indentation + 1, message)

View File

@ -95,6 +95,6 @@ def check(conf, token, prev, next, nextnext, context):
next.value != '<<'):
yield LintProblem(
next.start_mark.line + 1, next.start_mark.column + 1,
'duplication of key "%s" in mapping' % next.value)
f'duplication of key "{next.value}" in mapping')
else:
context['stack'][-1].keys.append(next.value)

View File

@ -122,6 +122,6 @@ def check(conf, token, prev, next, nextnext, context):
for key in context['stack'][-1].keys):
yield LintProblem(
next.start_mark.line + 1, next.start_mark.column + 1,
'wrong ordering of key "%s" in mapping' % next.value)
f'wrong ordering of key "{next.value}" in mapping')
else:
context['stack'][-1].keys.append(next.value)

View File

@ -99,8 +99,7 @@ def check(conf, token, prev, next, nextnext, context):
IS_OCTAL_NUMBER_PATTERN.match(val[1:])):
yield LintProblem(
token.start_mark.line + 1, token.end_mark.column + 1,
'forbidden implicit octal value "%s"' %
token.value)
f'forbidden implicit octal value "{token.value}"')
if conf['forbid-explicit-octal']:
if isinstance(token, yaml.tokens.ScalarToken):
@ -110,5 +109,4 @@ def check(conf, token, prev, next, nextnext, context):
IS_OCTAL_NUMBER_PATTERN.match(val[2:])):
yield LintProblem(
token.start_mark.line + 1, token.end_mark.column + 1,
'forbidden explicit octal value "%s"' %
token.value)
f'forbidden explicit octal value "{token.value}"')

View File

@ -240,7 +240,7 @@ def check(conf, token, prev, next, nextnext, context):
if (token.style is None or
not (_quote_match(quote_type, token.style) or
(conf['allow-quoted-quotes'] and _has_quoted_quotes(token)))):
msg = "string value is not quoted with %s quotes" % quote_type
msg = f"string value is not quoted with {quote_type} quotes"
elif conf['required'] is False:
@ -249,7 +249,7 @@ def check(conf, token, prev, next, nextnext, context):
not _quote_match(quote_type, token.style) and
not (conf['allow-quoted-quotes'] and
_has_quoted_quotes(token))):
msg = "string value is not quoted with %s quotes" % quote_type
msg = f"string value is not quoted with {quote_type} quotes"
elif not token.style:
is_extra_required = any(re.search(r, token.value)
@ -267,14 +267,14 @@ def check(conf, token, prev, next, nextnext, context):
is_extra_allowed = any(re.search(r, token.value)
for r in conf['extra-allowed'])
if not (is_extra_required or is_extra_allowed):
msg = "string value is redundantly quoted with %s quotes" % (
quote_type)
msg = f"string value is redundantly quoted with " \
f"{quote_type} quotes"
# But when used need to match config
elif (token.style and
not _quote_match(quote_type, token.style) and
not (conf['allow-quoted-quotes'] and _has_quoted_quotes(token))):
msg = "string value is not quoted with %s quotes" % quote_type
msg = f"string value is not quoted with {quote_type} quotes"
elif not token.style:
is_extra_required = len(conf['extra-required']) and any(