aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@google.com>2022-05-02 21:26:41 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-05-02 21:26:41 +0000
commitf5171d0395ca78e89db6479057a4262d87e5abb1 (patch)
tree3283f637bf7d4cf46840932f09c51600b2bccbd6
parent45322b9cde1b0f3bcc343caab21287e7022c5c4f (diff)
parent0522922843c6ea447d027e6b88a0b22eb6c652a4 (diff)
downloadrepohooks-f5171d0395ca78e89db6479057a4262d87e5abb1.tar.gz
lint: clean up newer warnings am: 0522922843
Original change: https://android-review.googlesource.com/c/platform/tools/repohooks/+/2078907 Change-Id: I44b70c3a8db717b65389f6a9ae0e6068f3fa4639 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rwxr-xr-xpre-upload.py59
-rw-r--r--rh/config.py44
-rwxr-xr-xrh/config_test.py14
-rwxr-xr-xrh/config_unittest.py2
-rw-r--r--rh/git.py22
-rw-r--r--rh/hooks.py99
-rwxr-xr-xrh/hooks_unittest.py28
-rw-r--r--rh/results.py5
-rw-r--r--rh/shell.py10
-rwxr-xr-xrh/shell_unittest.py10
-rw-r--r--rh/terminal.py22
-rw-r--r--rh/utils.py26
-rwxr-xr-xrh/utils_unittest.py6
-rwxr-xr-xtools/android_test_mapping_format.py7
-rwxr-xr-xtools/android_test_mapping_format_unittest.py48
-rwxr-xr-xtools/clang-format.py10
-rwxr-xr-xtools/google-java-format.py13
-rwxr-xr-xtools/pylint.py18
18 files changed, 213 insertions, 230 deletions
diff --git a/pre-upload.py b/pre-upload.py
index 7eb11b8..fa65310 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -94,7 +94,7 @@ class Output(object):
commit: commit hash.
commit_summary: commit summary.
"""
- status_line = '[%s %s] %s' % (self.COMMIT, commit[0:12], commit_summary)
+ status_line = f'[{self.COMMIT} {commit[0:12]}] {commit_summary}'
rh.terminal.print_status_line(status_line, print_newline=True)
self.hook_index = 1
@@ -106,8 +106,8 @@ class Output(object):
"""
self._curr_hook_name = hook_name
self.hook_start_time = datetime.datetime.now()
- status_line = '[%s %d/%d] %s' % (self.RUNNING, self.hook_index,
- self.num_hooks, hook_name)
+ status_line = (f'[{self.RUNNING} {self.hook_index}/{self.num_hooks}] '
+ f'{hook_name}')
self.hook_index += 1
rh.terminal.print_status_line(status_line)
@@ -115,11 +115,11 @@ class Output(object):
"""Finish processing any per-hook state."""
duration = datetime.datetime.now() - self.hook_start_time
if duration >= self._SLOW_HOOK_DURATION:
+ d = rh.utils.timedelta_str(duration)
self.hook_warning(
- 'This hook took %s to finish which is fairly slow for '
+ f'This hook took {d} to finish which is fairly slow for '
'developers.\nPlease consider moving the check to the '
- 'server/CI system instead.' %
- (rh.utils.timedelta_str(duration),))
+ 'server/CI system instead.')
def hook_error(self, error):
"""Print an error for a single hook.
@@ -135,7 +135,7 @@ class Output(object):
Args:
warning: warning string.
"""
- status_line = '[%s] %s' % (self.WARNING, self._curr_hook_name)
+ status_line = f'[{self.WARNING}] {self._curr_hook_name}'
rh.terminal.print_status_line(status_line, print_newline=True)
print(warning, file=sys.stderr)
@@ -146,19 +146,19 @@ class Output(object):
header: A unique identifier for the source of this error.
error: error string.
"""
- status_line = '[%s] %s' % (self.FAILED, header)
+ status_line = f'[{self.FAILED}] {header}'
rh.terminal.print_status_line(status_line, print_newline=True)
print(error, file=sys.stderr)
self.success = False
def finish(self):
"""Print summary for all the hooks."""
- status_line = '[%s] repohooks for %s %s in %s' % (
- self.PASSED if self.success else self.FAILED,
- self.project_name,
- 'passed' if self.success else 'failed',
- rh.utils.timedelta_str(datetime.datetime.now() - self.start_time))
- rh.terminal.print_status_line(status_line, print_newline=True)
+ header = self.PASSED if self.success else self.FAILED
+ status = 'passed' if self.success else 'failed'
+ d = rh.utils.timedelta_str(datetime.datetime.now() - self.start_time)
+ rh.terminal.print_status_line(
+ f'[{header}] repohooks for {self.project_name} {status} in {d}',
+ print_newline=True)
def _process_hook_results(results):
@@ -185,9 +185,9 @@ def _process_hook_results(results):
if result:
ret = ''
if result.files:
- ret += ' FILES: %s' % (result.files,)
+ ret += f' FILES: {result.files}'
lines = result.error.splitlines()
- ret += '\n'.join(' %s' % (x,) for x in lines)
+ ret += '\n'.join(f' {x}' for x in lines)
if result.is_warning():
has_warning = True
warning_ret += ret
@@ -233,15 +233,15 @@ def _attempt_fixes(fixup_func_list, commit_list):
# merge conflict resolution). Refuse to run the fix in those cases.
return
- prompt = ('An automatic fix can be attempted for the "%s" hook. '
- 'Do you want to run it?' % hook_name)
+ prompt = (f'An automatic fix can be attempted for the "{hook_name}" hook. '
+ 'Do you want to run it?')
if not rh.terminal.boolean_prompt(prompt):
return
result = fixup_func()
if result:
- print('Attempt to fix "%s" for commit "%s" failed: %s' %
- (hook_name, commit, result),
+ print(f'Attempt to fix "{hook_name}" for commit "{commit}" failed: '
+ f'{result}',
file=sys.stderr)
else:
print('Fix successfully applied. Amend the current commit before '
@@ -281,8 +281,7 @@ def _run_project_hooks_in_cwd(project_name, proj_dir, output, commit_list=None):
upstream_branch = rh.git.get_upstream_branch()
except rh.utils.CalledProcessError as e:
output.error('Upstream remote/tracking branch lookup',
- '%s\nDid you run repo start? Is your HEAD detached?' %
- (e,))
+ f'{e}\nDid you run repo start? Is your HEAD detached?')
return False
project = rh.Project(name=project_name, dir=proj_dir, remote=remote)
@@ -358,11 +357,11 @@ def _run_project_hooks(project_name, proj_dir=None, commit_list=None):
result = rh.utils.run(cmd, capture_output=True)
proj_dirs = result.stdout.split()
if not proj_dirs:
- print('%s cannot be found.' % project_name, file=sys.stderr)
+ print(f'{project_name} cannot be found.', file=sys.stderr)
print('Please specify a valid project.', file=sys.stderr)
return False
if len(proj_dirs) > 1:
- print('%s is associated with multiple directories.' % project_name,
+ print(f'{project_name} is associated with multiple directories.',
file=sys.stderr)
print('Please specify a directory to help disambiguate.',
file=sys.stderr)
@@ -409,9 +408,9 @@ def main(project_list, worktree_list=None, **_kwargs):
if found_error:
color = rh.terminal.Color()
- print('%s: Preupload failed due to above error(s).\n'
- 'For more info, please see:\n%s' %
- (color.color(color.RED, 'FATAL'), REPOHOOKS_URL),
+ print(color.color(color.RED, 'FATAL') +
+ ': Preupload failed due to above error(s).\n'
+ f'For more info, please see:\n{REPOHOOKS_URL}',
file=sys.stderr)
sys.exit(1)
@@ -461,16 +460,16 @@ def direct_main(argv):
parser.error('The current directory is not part of a git project.')
opts.dir = os.path.dirname(os.path.abspath(git_dir))
elif not os.path.isdir(opts.dir):
- parser.error('Invalid dir: %s' % opts.dir)
+ parser.error(f'Invalid dir: {opts.dir}')
elif not rh.git.is_git_repository(opts.dir):
- parser.error('Not a git repository: %s' % opts.dir)
+ parser.error(f'Not a git repository: {opts.dir}')
# Identify the project if it wasn't specified; this _requires_ the repo
# tool to be installed and for the project to be part of a repo checkout.
if not opts.project:
opts.project = _identify_project(opts.dir)
if not opts.project:
- parser.error("Repo couldn't identify the project of %s" % opts.dir)
+ parser.error(f"Repo couldn't identify the project of {opts.dir}")
if _run_project_hooks(opts.project, proj_dir=opts.dir,
commit_list=opts.commits):
diff --git a/rh/config.py b/rh/config.py
index 1eb93a7..6cd218b 100644
--- a/rh/config.py
+++ b/rh/config.py
@@ -180,14 +180,14 @@ class PreUploadConfig(object):
# Reject unknown sections.
bad_sections = set(config.sections()) - self.VALID_SECTIONS
if bad_sections:
- raise ValidationError('%s: unknown sections: %s' %
- (self.source, bad_sections))
+ raise ValidationError(
+ f'{self.source}: unknown sections: {bad_sections}')
# Reject blank custom hooks.
for hook in self.custom_hooks:
if not config.get(self.CUSTOM_HOOKS_SECTION, hook):
- raise ValidationError('%s: custom hook "%s" cannot be blank' %
- (self.source, hook))
+ raise ValidationError(
+ f'{self.source}: custom hook "{hook}" cannot be blank')
# Reject unknown builtin hooks.
valid_builtin_hooks = set(rh.hooks.BUILTIN_HOOKS.keys())
@@ -195,8 +195,8 @@ class PreUploadConfig(object):
hooks = set(config.options(self.BUILTIN_HOOKS_SECTION))
bad_hooks = hooks - valid_builtin_hooks
if bad_hooks:
- raise ValidationError('%s: unknown builtin hooks: %s' %
- (self.source, bad_hooks))
+ raise ValidationError(
+ f'{self.source}: unknown builtin hooks: {bad_hooks}')
elif config.has_section(self.BUILTIN_HOOKS_OPTIONS_SECTION):
raise ValidationError('Builtin hook options specified, but missing '
'builtin hook settings')
@@ -205,24 +205,26 @@ class PreUploadConfig(object):
hooks = set(config.options(self.BUILTIN_HOOKS_OPTIONS_SECTION))
bad_hooks = hooks - valid_builtin_hooks
if bad_hooks:
- raise ValidationError('%s: unknown builtin hook options: %s' %
- (self.source, bad_hooks))
+ raise ValidationError(
+ f'{self.source}: unknown builtin hook options: {bad_hooks}')
# Verify hooks are valid shell strings.
for hook in self.custom_hooks:
try:
self.custom_hook(hook)
except ValueError as e:
- raise ValidationError('%s: hook "%s" command line is invalid: '
- '%s' % (self.source, hook, e)) from e
+ raise ValidationError(
+ f'{self.source}: hook "{hook}" command line is invalid: {e}'
+ ) from e
# Verify hook options are valid shell strings.
for hook in self.builtin_hooks:
try:
self.builtin_hook_option(hook)
except ValueError as e:
- raise ValidationError('%s: hook options "%s" are invalid: %s' %
- (self.source, hook, e)) from e
+ raise ValidationError(
+ f'{self.source}: hook options "{hook}" are invalid: {e}'
+ ) from e
# Reject unknown tools.
valid_tools = set(rh.hooks.TOOL_PATHS.keys())
@@ -230,16 +232,16 @@ class PreUploadConfig(object):
tools = set(config.options(self.TOOL_PATHS_SECTION))
bad_tools = tools - valid_tools
if bad_tools:
- raise ValidationError('%s: unknown tools: %s' %
- (self.source, bad_tools))
+ raise ValidationError(
+ f'{self.source}: unknown tools: {bad_tools}')
# Reject unknown options.
if config.has_section(self.OPTIONS_SECTION):
options = set(config.options(self.OPTIONS_SECTION))
bad_options = options - self.VALID_OPTIONS
if bad_options:
- raise ValidationError('%s: unknown options: %s' %
- (self.source, bad_options))
+ raise ValidationError(
+ f'{self.source}: unknown options: {bad_options}')
class PreUploadFile(PreUploadConfig):
@@ -265,7 +267,7 @@ class PreUploadFile(PreUploadConfig):
try:
self.config.read(path)
except configparser.ParsingError as e:
- raise ValidationError('%s: %s' % (path, e)) from e
+ raise ValidationError(f'{path}: {e}') from e
self._validate()
@@ -294,9 +296,9 @@ class LocalPreUploadFile(PreUploadFile):
# Reject Exclude Paths section for local config.
if self.config.has_section(self.BUILTIN_HOOKS_EXCLUDE_SECTION):
- raise ValidationError('%s: [%s] is not valid in local files' %
- (self.path,
- self.BUILTIN_HOOKS_EXCLUDE_SECTION))
+ raise ValidationError(
+ f'{self.path}: [{self.BUILTIN_HOOKS_EXCLUDE_SECTION}] is not '
+ 'valid in local files')
class GlobalPreUploadFile(PreUploadFile):
@@ -331,5 +333,5 @@ class PreUploadSettings(PreUploadConfig):
# We validated configs in isolation, now do one final pass altogether.
- self.source = '{%s}' % '|'.join(self.paths)
+ self.source = '{' + '|'.join(self.paths) + '}'
self._validate()
diff --git a/rh/config_test.py b/rh/config_test.py
index 80fc832..df3afb6 100755
--- a/rh/config_test.py
+++ b/rh/config_test.py
@@ -27,25 +27,25 @@ REPO_ROOT = os.path.dirname(os.path.dirname(REPOTOOLS))
def assertEqual(msg, exp, actual):
"""Assert |exp| equals |actual|."""
- assert exp == actual, '%s: expected "%s" but got "%s"' % (msg, exp, actual)
+ assert exp == actual, f'{msg}: expected "{exp}" but got "{actual}"'
def assertEnv(var, value):
"""Assert |var| is set in the environment as |value|."""
- assert var in os.environ, '$%s missing in environment' % (var,)
- assertEqual('env[%s]' % (var,), value, os.environ[var])
+ assert var in os.environ, f'${var} missing in environment'
+ assertEqual(f'env[{var}]', value, os.environ[var])
def check_commit_id(commit):
"""Check |commit| looks like a git commit id."""
- assert len(commit) == 40, 'commit "%s" must be 40 chars' % (commit,)
+ assert len(commit) == 40, f'commit "{commit}" must be 40 chars'
assert re.match(r'^[a-f0-9]+$', commit), \
- 'commit "%s" must be all hex' % (commit,)
+ f'commit "{commit}" must be all hex'
def check_commit_msg(msg):
"""Check the ${PREUPLOAD_COMMIT_MESSAGE} setting."""
- assert len(msg) > 1, 'commit message must be at least 2 bytes: %s'
+ assert len(msg) > 1, f'commit message must be at least 2 bytes: {msg}'
def check_repo_root(root):
@@ -100,7 +100,7 @@ def main(argv):
check_repo_root(opts.repo_root)
check_files(opts.files)
except AssertionError as e:
- print('error: %s' % (e,), file=sys.stderr)
+ print(f'error: {e}', file=sys.stderr)
return 1
return 0
diff --git a/rh/config_unittest.py b/rh/config_unittest.py
index 3e3e470..475dc22 100755
--- a/rh/config_unittest.py
+++ b/rh/config_unittest.py
@@ -57,7 +57,7 @@ class FileTestCase(unittest.TestCase):
Path to the file where the configuration was written.
"""
path = os.path.join(self.tempdir, filename)
- with open(path, 'w') as fp:
+ with open(path, 'w', encoding='utf-8') as fp:
fp.write(data)
return path
diff --git a/rh/git.py b/rh/git.py
index ab1e35f..f1f658b 100644
--- a/rh/git.py
+++ b/rh/git.py
@@ -35,7 +35,7 @@ def get_upstream_remote():
branch = result.stdout.strip()
# Then get the remote associated with this branch.
- cmd = ['git', 'config', 'branch.%s.remote' % branch]
+ cmd = ['git', 'config', f'branch.{branch}.remote']
result = rh.utils.run(cmd, capture_output=True)
return result.stdout.strip()
@@ -52,14 +52,14 @@ def get_upstream_branch():
if not current_branch:
raise ValueError('Need to be on a tracking branch')
- cfg_option = 'branch.' + current_branch + '.%s'
- cmd = ['git', 'config', cfg_option % 'merge']
+ cfg_option = 'branch.' + current_branch + '.'
+ cmd = ['git', 'config', cfg_option + 'merge']
result = rh.utils.run(cmd, capture_output=True)
full_upstream = result.stdout.strip()
# If remote is not fully qualified, add an implicit namespace.
if '/' not in full_upstream:
- full_upstream = 'refs/heads/%s' % full_upstream
- cmd = ['git', 'config', cfg_option % 'remote']
+ full_upstream = f'refs/heads/{full_upstream}'
+ cmd = ['git', 'config', cfg_option + 'remote']
result = rh.utils.run(cmd, capture_output=True)
remote = result.stdout.strip()
if not remote or not full_upstream:
@@ -77,7 +77,7 @@ def get_commit_for_ref(ref):
def get_remote_revision(ref, remote):
"""Returns the remote revision for this ref."""
- prefix = 'refs/remotes/%s/' % remote
+ prefix = f'refs/remotes/{remote}/'
if ref.startswith(prefix):
return ref[len(prefix):]
return ref
@@ -99,7 +99,7 @@ def get_file_content(commit, path):
a full file, you should check that first. One way to detect is that the
content will not have any newlines.
"""
- cmd = ['git', 'show', '%s:%s' % (commit, path)]
+ cmd = ['git', 'show', f'{commit}:{path}']
return rh.utils.run(cmd, capture_output=True).stdout
@@ -147,7 +147,7 @@ def raw_diff(path, target):
for line in diff_lines:
match = DIFF_RE.match(line)
if not match:
- raise ValueError('Failed to parse diff output: %s' % line)
+ raise ValueError(f'Failed to parse diff output: {line}')
rawdiff = RawDiffEntry(**match.groupdict())
rawdiff.src_mode = int(rawdiff.src_mode)
rawdiff.dst_mode = int(rawdiff.dst_mode)
@@ -164,12 +164,12 @@ def get_affected_files(commit):
Returns:
A list of modified/added (and perhaps deleted) files
"""
- return raw_diff(os.getcwd(), '%s^-' % commit)
+ return raw_diff(os.getcwd(), f'{commit}^-')
def get_commits(ignore_merged_commits=False):
"""Returns a list of commits for this review."""
- cmd = ['git', 'rev-list', '%s..' % get_upstream_branch()]
+ cmd = ['git', 'rev-list', f'{get_upstream_branch()}..']
if ignore_merged_commits:
cmd.append('--first-parent')
return rh.utils.run(cmd, capture_output=True).stdout.split()
@@ -191,7 +191,7 @@ def find_repo_root(path=None):
while not os.path.exists(os.path.join(path, '.repo')):
path = os.path.dirname(path)
if path == '/':
- raise ValueError('Could not locate .repo in %s' % orig_path)
+ raise ValueError(f'Could not locate .repo in {orig_path}')
return path
diff --git a/rh/hooks.py b/rh/hooks.py
index 0b3bb29..d473cb9 100644
--- a/rh/hooks.py
+++ b/rh/hooks.py
@@ -83,7 +83,7 @@ class Placeholders(object):
else:
# First scan for exact matches
for key, val in replacements.items():
- var = '${%s}' % (key,)
+ var = '${' + key + '}'
if arg == var:
if isinstance(val, str):
ret.append(val)
@@ -98,7 +98,7 @@ class Placeholders(object):
if isinstance(val, str):
return val
return ' '.join(val)
- ret.append(re.sub(r'\$\{(%s)\}' % ('|'.join(all_vars),),
+ ret.append(re.sub(r'\$\{(' + '|'.join(all_vars) + r')\}',
replace, arg))
return ret
@@ -111,7 +111,7 @@ class Placeholders(object):
def get(self, var):
"""Helper function to get the replacement |var| value."""
- return getattr(self, 'var_%s' % (var,))
+ return getattr(self, f'var_{var}')
@property
def var_PREUPLOAD_COMMIT_MESSAGE(self):
@@ -400,11 +400,11 @@ def check_google_java_format(project, commit, _desc, _diff, options=None):
def check_commit_msg_bug_field(project, commit, desc, _diff, options=None):
"""Check the commit message for a 'Bug:' line."""
field = 'Bug'
- regex = r'^%s: (None|[0-9]+(, [0-9]+)*)$' % (field,)
+ regex = fr'^{field}: (None|[0-9]+(, [0-9]+)*)$'
check_re = re.compile(regex)
if options.args():
- raise ValueError('commit msg %s check takes no options' % (field,))
+ raise ValueError(f'commit msg {field} check takes no options')
found = []
for line in desc.splitlines():
@@ -412,23 +412,25 @@ def check_commit_msg_bug_field(project, commit, desc, _diff, options=None):
found.append(line)
if not found:
- error = ('Commit message is missing a "%s:" line. It must match the\n'
- 'following case-sensitive regex:\n\n %s') % (field, regex)
+ error = (
+ f'Commit message is missing a "{field}:" line. It must match the\n'
+ f'following case-sensitive regex:\n\n {regex}'
+ )
else:
return None
- return [rh.results.HookResult('commit msg: "%s:" check' % (field,),
+ return [rh.results.HookResult(f'commit msg: "{field}:" check',
project, commit, error=error)]
def check_commit_msg_changeid_field(project, commit, desc, _diff, options=None):
"""Check the commit message for a 'Change-Id:' line."""
field = 'Change-Id'
- regex = r'^%s: I[a-f0-9]+$' % (field,)
+ regex = fr'^{field}: I[a-f0-9]+$'
check_re = re.compile(regex)
if options.args():
- raise ValueError('commit msg %s check takes no options' % (field,))
+ raise ValueError(f'commit msg {field} check takes no options')
found = []
for line in desc.splitlines():
@@ -436,15 +438,17 @@ def check_commit_msg_changeid_field(project, commit, desc, _diff, options=None):
found.append(line)
if not found:
- error = ('Commit message is missing a "%s:" line. It must match the\n'
- 'following case-sensitive regex:\n\n %s') % (field, regex)
+ error = (
+ f'Commit message is missing a "{field}:" line. It must match the\n'
+ f'following case-sensitive regex:\n\n {regex}'
+ )
elif len(found) > 1:
- error = ('Commit message has too many "%s:" lines. There can be only '
- 'one.') % (field,)
+ error = (f'Commit message has too many "{field}:" lines. There can be '
+ 'only one.')
else:
return None
- return [rh.results.HookResult('commit msg: "%s:" check' % (field,),
+ return [rh.results.HookResult(f'commit msg: "{field}:" check',
project, commit, error=error)]
@@ -537,11 +541,11 @@ high-quality Test: descriptions.
def check_commit_msg_test_field(project, commit, desc, _diff, options=None):
"""Check the commit message for a 'Test:' line."""
field = 'Test'
- regex = r'^%s: .*$' % (field,)
+ regex = fr'^{field}: .*$'
check_re = re.compile(regex)
if options.args():
- raise ValueError('commit msg %s check takes no options' % (field,))
+ raise ValueError(f'commit msg {field} check takes no options')
found = []
for line in desc.splitlines():
@@ -553,7 +557,7 @@ def check_commit_msg_test_field(project, commit, desc, _diff, options=None):
else:
return None
- return [rh.results.HookResult('commit msg: "%s:" check' % (field,),
+ return [rh.results.HookResult(f'commit msg: "{field}:" check',
project, commit, error=error)]
@@ -613,22 +617,23 @@ def check_commit_msg_relnote_field_format(project, commit, desc, _diff,
quotes are escaped with a backslash.
"""
field = 'Relnote'
- regex_relnote = r'^%s:.*$' % (field,)
+ regex_relnote = fr'^{field}:.*$'
check_re_relnote = re.compile(regex_relnote, re.IGNORECASE)
if options.args():
- raise ValueError('commit msg %s check takes no options' % (field,))
+ raise ValueError(f'commit msg {field} check takes no options')
# Check 1: Check for possible misspellings of the `Relnote:` field.
# Regex for misspelled fields.
- possible_field_misspells = {'Relnotes', 'ReleaseNote',
- 'Rel-note', 'Rel note',
- 'rel-notes', 'releasenotes',
- 'release-note', 'release-notes'}
- regex_field_misspells = r'^(%s): .*$' % (
- '|'.join(possible_field_misspells),
- )
+ possible_field_misspells = {
+ 'Relnotes', 'ReleaseNote',
+ 'Rel-note', 'Rel note',
+ 'rel-notes', 'releasenotes',
+ 'release-note', 'release-notes',
+ }
+ re_possible_field_misspells = '|'.join(possible_field_misspells)
+ regex_field_misspells = fr'^({re_possible_field_misspells}): .*$'
check_re_field_misspells = re.compile(regex_field_misspells, re.IGNORECASE)
ret = []
@@ -636,9 +641,9 @@ def check_commit_msg_relnote_field_format(project, commit, desc, _diff,
if check_re_field_misspells.match(line):
error = RELNOTE_MISSPELL_MSG % (regex_relnote, )
ret.append(
- rh.results.HookResult(('commit msg: "%s:" '
- 'tag spelling error') % (field,),
- project, commit, error=error))
+ rh.results.HookResult(
+ f'commit msg: "{field}:" tag spelling error',
+ project, commit, error=error))
# Check 2: Check that multiline Relnotes are quoted.
@@ -661,10 +666,9 @@ def check_commit_msg_relnote_field_format(project, commit, desc, _diff,
if (not check_re_other_fields.findall(next_line) and
not check_re_empty_string.match(next_line)):
ret.append(
- rh.results.HookResult(('commit msg: "%s:" '
- 'tag missing quotes') % (field,),
- project, commit,
- error=RELNOTE_MISSING_QUOTES_MSG))
+ rh.results.HookResult(
+ f'commit msg: "{field}:" tag missing quotes',
+ project, commit, error=RELNOTE_MISSING_QUOTES_MSG))
break
# Check 3: Check that multiline Relnotes contain matching quotes.
@@ -696,10 +700,9 @@ def check_commit_msg_relnote_field_format(project, commit, desc, _diff,
break
if first_quote_found != second_quote_found:
ret.append(
- rh.results.HookResult(('commit msg: "%s:" '
- 'tag missing closing quote') % (field,),
- project, commit,
- error=RELNOTE_MISSING_QUOTES_MSG))
+ rh.results.HookResult(
+ f'commit msg: "{field}:" tag missing closing quote',
+ project, commit, error=RELNOTE_MISSING_QUOTES_MSG))
# Check 4: Check that non-starting or non-ending quotes are escaped with a
# backslash.
@@ -717,7 +720,7 @@ def check_commit_msg_relnote_field_format(project, commit, desc, _diff,
if '"""' in cur_line:
break
if line_needs_checking:
- stripped_line = re.sub('^%s:' % field, '', cur_line,
+ stripped_line = re.sub(fr'^{field}:', '', cur_line,
flags=re.IGNORECASE).strip()
for i, character in enumerate(stripped_line):
if i == 0:
@@ -739,11 +742,9 @@ def check_commit_msg_relnote_field_format(project, commit, desc, _diff,
break
if uses_invalid_quotes:
- ret.append(rh.results.HookResult(('commit msg: "%s:" '
- 'tag using unescaped '
- 'quotes') % (field,),
- project, commit,
- error=RELNOTE_INVALID_QUOTES_MSG))
+ ret.append(rh.results.HookResult(
+ f'commit msg: "{field}:" tag using unescaped quotes',
+ project, commit, error=RELNOTE_INVALID_QUOTES_MSG))
return ret
@@ -773,11 +774,11 @@ def check_commit_msg_relnote_for_current_txt(project, commit, desc, diff,
options=None):
"""Check changes to current.txt contain the 'Relnote:' stanza."""
field = 'Relnote'
- regex = r'^%s: .+$' % (field,)
+ regex = fr'^{field}: .+$'
check_re = re.compile(regex, re.IGNORECASE)
if options.args():
- raise ValueError('commit msg %s check takes no options' % (field,))
+ raise ValueError(f'commit msg {field} check takes no options')
filtered = _filter_diff(
diff,
@@ -798,7 +799,7 @@ def check_commit_msg_relnote_for_current_txt(project, commit, desc, diff,
else:
return None
- return [rh.results.HookResult('commit msg: "%s:" check' % (field,),
+ return [rh.results.HookResult(f'commit msg: "{field}:" check',
project, commit, error=error)]
@@ -907,7 +908,7 @@ def check_rustfmt(project, commit, _desc, diff, options=None):
# TODO(b/164111102): rustfmt stable does not support --check on stdin.
# If no error is reported, compare stdin with stdout.
if data != result.stdout:
- msg = ('To fix, please run: %s' %
+ msg = ('To fix, please run: ' +
rh.shell.cmd_to_str(cmd + [d.file]))
ret.append(rh.results.HookResult(
'rustfmt', project, commit, error=msg,
@@ -948,7 +949,7 @@ def check_xmllint(project, commit, _desc, diff, options=None):
'xsl', # Extensible Stylesheet Language.
))
- filtered = _filter_diff(diff, [r'\.(%s)$' % '|'.join(extensions)])
+ filtered = _filter_diff(diff, [r'\.(' + '|'.join(extensions) + r')$'])
if not filtered:
return None
diff --git a/rh/hooks_unittest.py b/rh/hooks_unittest.py
index 8466319..03f45ca 100755
--- a/rh/hooks_unittest.py
+++ b/rh/hooks_unittest.py
@@ -48,7 +48,7 @@ class HooksDocsTests(unittest.TestCase):
"""Extract the |section| text out of the readme."""
ret = []
in_section = False
- with open(self.readme) as fp:
+ with open(self.readme, encoding='utf-8') as fp:
for line in fp:
if not in_section:
# Look for the section like "## [Tool Paths]".
@@ -66,22 +66,22 @@ class HooksDocsTests(unittest.TestCase):
"""Verify builtin hooks are documented."""
data = self._grab_section('[Builtin Hooks]')
for hook in rh.hooks.BUILTIN_HOOKS:
- self.assertIn('* `%s`:' % (hook,), data,
- msg='README.md missing docs for hook "%s"' % (hook,))
+ self.assertIn(f'* `{hook}`:', data,
+ msg=f'README.md missing docs for hook "{hook}"')
def testToolPaths(self):
"""Verify tools are documented."""
data = self._grab_section('[Tool Paths]')
for tool in rh.hooks.TOOL_PATHS:
- self.assertIn('* `%s`:' % (tool,), data,
- msg='README.md missing docs for tool "%s"' % (tool,))
+ self.assertIn(f'* `{tool}`:', data,
+ msg=f'README.md missing docs for tool "{tool}"')
def testPlaceholders(self):
"""Verify placeholder replacement vars are documented."""
data = self._grab_section('Placeholders')
for var in rh.hooks.Placeholders.vars():
- self.assertIn('* `${%s}`:' % (var,), data,
- msg='README.md missing docs for var "%s"' % (var,))
+ self.assertIn('* `${' + var + '}`:', data,
+ msg=f'README.md missing docs for var "{var}"')
class PlaceholderTests(unittest.TestCase):
@@ -149,8 +149,8 @@ class PlaceholderTests(unittest.TestCase):
def testTheTester(self):
"""Make sure we have a test for every variable."""
for var in self.replacer.vars():
- self.assertIn('test%s' % (var,), dir(self),
- msg='Missing unittest for variable %s' % (var,))
+ self.assertIn(f'test{var}', dir(self),
+ msg=f'Missing unittest for variable {var}')
def testPREUPLOAD_COMMIT_MESSAGE(self):
"""Verify handling of PREUPLOAD_COMMIT_MESSAGE."""
@@ -212,7 +212,7 @@ class HookOptionsTests(unittest.TestCase):
# At least one replacement. Most real testing is in PlaceholderTests.
args = ['who', 'goes', 'there ?', '${BUILD_OS} is great']
- exp_args = ['who', 'goes', 'there ?', '%s is great' % (m.return_value,)]
+ exp_args = ['who', 'goes', 'there ?', f'{m.return_value} is great']
self.assertEqual(exp_args, rh.hooks.HookOptions.expand_vars(args))
def testArgs(self):
@@ -296,10 +296,10 @@ class BuiltinHooksTests(unittest.TestCase):
ret = func(self.project, 'commit', desc, diff, options=self.options)
if accept:
self.assertFalse(
- bool(ret), msg='Should have accepted: {{{%s}}}' % (desc,))
+ bool(ret), msg='Should have accepted: {{{' + desc + '}}}')
else:
self.assertTrue(
- bool(ret), msg='Should have rejected: {{{%s}}}' % (desc,))
+ bool(ret), msg='Should have rejected: {{{' + desc + '}}}')
def _test_file_filter(self, mock_check, func, files):
"""Helper for testing hooks that filter by files and run external tools.
@@ -322,8 +322,8 @@ class BuiltinHooksTests(unittest.TestCase):
def testTheTester(self, _mock_check, _mock_run):
"""Make sure we have a test for every hook."""
for hook in rh.hooks.BUILTIN_HOOKS:
- self.assertIn('test_%s' % (hook,), dir(self),
- msg='Missing unittest for builtin hook %s' % (hook,))
+ self.assertIn(f'test_{hook}', dir(self),
+ msg=f'Missing unittest for builtin hook {hook}')
def test_bpfmt(self, mock_check, _mock_run):
"""Verify the bpfmt builtin hook."""
diff --git a/rh/results.py b/rh/results.py
index bdf7626..a7a4b49 100644
--- a/rh/results.py
+++ b/rh/results.py
@@ -51,11 +51,6 @@ class HookResult(object):
def __bool__(self):
return bool(self.error)
- # pylint: disable=nonzero-method
- def __nonzero__(self):
- """Python 2/3 glue."""
- return self.__bool__()
-
def is_warning(self):
return False
diff --git a/rh/shell.py b/rh/shell.py
index dda3be3..0321e44 100644
--- a/rh/shell.py
+++ b/rh/shell.py
@@ -73,18 +73,18 @@ def shell_quote(s):
if c in _SHELL_QUOTABLE_CHARS:
break
else:
- return s if s else u"''"
+ return s if s else "''"
# See if we can use single quotes first. Output is nicer.
if "'" not in s:
- return u"'%s'" % s
+ return f"'{s}'"
# Have to use double quotes. Escape the few chars that still expand when
# used inside of double quotes.
for c in _SHELL_ESCAPE_CHARS:
if c in s:
- s = s.replace(c, r'\%s' % c)
- return u'"%s"' % s
+ s = s.replace(c, fr'\{c}')
+ return f'"{s}"'
def shell_unquote(s):
@@ -157,4 +157,4 @@ def boolean_shell_value(sval, default):
if s in ('no', 'n', '0', 'false'):
return False
- raise ValueError('Could not decode as a boolean value: %r' % (sval,))
+ raise ValueError(f'Could not decode as a boolean value: {sval!r}')
diff --git a/rh/shell_unittest.py b/rh/shell_unittest.py
index 21478cf..56b2321 100755
--- a/rh/shell_unittest.py
+++ b/rh/shell_unittest.py
@@ -40,8 +40,8 @@ class DiffTestCase(unittest.TestCase):
def _assertEqual(self, func, test_input, test_output, result):
"""Like assertEqual but with built in diff support."""
diff = '\n'.join(list(self.differ.compare([test_output], [result])))
- msg = ('Expected %s to translate %r to %r, but got %r\n%s' %
- (func, test_input, test_output, result, diff))
+ msg = (f'Expected {func} to translate {test_input!r} to '
+ f'{test_output!r}, but got {result!r}\n{diff}')
self.assertEqual(test_output, result, msg)
def _testData(self, functor, tests, check_type=True):
@@ -65,8 +65,8 @@ class ShellQuoteTest(DiffTestCase):
# Dict of expected output strings to input lists.
tests_quote = {
"''": '',
- 'a': u'a',
- "'a b c'": u'a b c',
+ 'a': 'a',
+ "'a b c'": 'a b c',
"'a\tb'": 'a\tb',
"'/a$file'": '/a$file',
"'/a#file'": '/a#file',
@@ -105,7 +105,7 @@ class CmdToStrTest(DiffTestCase):
r"'a b' c": ['a b', 'c'],
r'''a "b'c"''': ['a', "b'c"],
r'''a "/'\$b" 'a b c' "xy'z"''':
- [u'a', "/'$b", 'a b c', "xy'z"],
+ ['a', "/'$b", 'a b c', "xy'z"],
'': [],
}
self._testData(rh.shell.cmd_to_str, tests)
diff --git a/rh/terminal.py b/rh/terminal.py
index 39c96ac..f69914c 100644
--- a/rh/terminal.py
+++ b/rh/terminal.py
@@ -136,18 +136,6 @@ def print_status_line(line, print_newline=False):
sys.stderr.flush()
-def get_input(prompt):
- """Python 2/3 glue for raw_input/input differences."""
- try:
- # pylint: disable=raw_input-builtin
- return raw_input(prompt)
- except NameError:
- # Python 3 renamed raw_input() to input(), which is safe to call since
- # it does not evaluate the input.
- # pylint: disable=bad-builtin,input-builtin
- return input(prompt)
-
-
def boolean_prompt(prompt='Do you want to continue?', default=True,
true_value='yes', false_value='no', prolog=None):
"""Helper function for processing boolean choice prompts.
@@ -165,22 +153,22 @@ def boolean_prompt(prompt='Do you want to continue?', default=True,
true_value, false_value = true_value.lower(), false_value.lower()
true_text, false_text = true_value, false_value
if true_value == false_value:
- raise ValueError('true_value and false_value must differ: got %r'
- % true_value)
+ raise ValueError(
+ f'true_value and false_value must differ: got {true_value!r}')
if default:
true_text = true_text[0].upper() + true_text[1:]
else:
false_text = false_text[0].upper() + false_text[1:]
- prompt = ('\n%s (%s/%s)? ' % (prompt, true_text, false_text))
+ prompt = f'\n{prompt} ({true_text}/{false_text})? '
if prolog:
- prompt = ('\n%s\n%s' % (prolog, prompt))
+ prompt = f'\n{prolog}\n{prompt}'
while True:
try:
- response = get_input(prompt).lower()
+ response = input(prompt).lower() # pylint: disable=bad-builtin
except EOFError:
# If the user hits CTRL+D, or stdin is disabled, use the default.
print()
diff --git a/rh/utils.py b/rh/utils.py
index 00c997c..14553a8 100644
--- a/rh/utils.py
+++ b/rh/utils.py
@@ -42,11 +42,11 @@ def timedelta_str(delta):
total = delta.total_seconds()
hours, rem = divmod(total, 3600)
mins, secs = divmod(rem, 60)
- ret = '%i.%03is' % (secs, delta.microseconds // 1000)
+ ret = f'{int(secs)}.{delta.microseconds // 1000:03}s'
if mins:
- ret = '%im%s' % (mins, ret)
+ ret = f'{int(mins)}m{ret}'
if hours:
- ret = '%ih%s' % (hours, ret)
+ ret = f'{int(hours)}h{ret}'
return ret
@@ -87,8 +87,8 @@ class CalledProcessError(subprocess.CalledProcessError):
def __init__(self, returncode, cmd, stdout=None, stderr=None, msg=None,
exception=None):
if exception is not None and not isinstance(exception, Exception):
- raise TypeError('exception must be an exception instance; got %r'
- % (exception,))
+ raise TypeError(
+ f'exception must be an exception instance; got {exception!r}')
super().__init__(returncode, cmd, stdout)
# The parent class will set |output|, so delete it.
@@ -117,7 +117,7 @@ class CalledProcessError(subprocess.CalledProcessError):
A summary string for this result.
"""
items = [
- 'return code: %s; command: %s' % (self.returncode, self.cmdstr),
+ f'return code: {self.returncode}; command: {self.cmdstr}',
]
if stderr and self.stderr:
items.append(self.stderr)
@@ -171,7 +171,7 @@ def _kill_child_process(proc, int_timeout, kill_timeout, cmd, original_handler,
# Still doesn't want to die. Too bad, so sad, time to die.
proc.kill()
except EnvironmentError as e:
- print('Ignoring unhandled exception in _kill_child_process: %s' % e,
+ print(f'Ignoring unhandled exception in _kill_child_process: {e}',
file=sys.stderr)
# Ensure our child process has been reaped, but don't wait forever.
@@ -180,7 +180,7 @@ def _kill_child_process(proc, int_timeout, kill_timeout, cmd, original_handler,
if not rh.signals.relay_signal(original_handler, signum, frame):
# Mock up our own, matching exit code for signaling.
raise TerminateCalledProcessError(
- signum << 8, cmd, msg='Received signal %i' % signum)
+ signum << 8, cmd, msg=f'Received signal {signum}')
class _Popen(subprocess.Popen):
@@ -196,7 +196,7 @@ class _Popen(subprocess.Popen):
process has knowingly been waitpid'd already.
"""
- # pylint: disable=arguments-differ
+ # pylint: disable=arguments-differ,arguments-renamed
def send_signal(self, signum):
if self.returncode is not None:
# The original implementation in Popen allows signaling whatever
@@ -245,7 +245,7 @@ class _Popen(subprocess.Popen):
# We use the keyword arg |input| which trips up pylint checks.
-# pylint: disable=redefined-builtin,input-builtin
+# pylint: disable=redefined-builtin
def run(cmd, redirect_stdout=False, redirect_stderr=False, cwd=None, input=None,
shell=False, env=None, extra_env=None, combine_stdout_stderr=False,
check=True, int_timeout=1, kill_timeout=1, capture_output=False,
@@ -399,9 +399,9 @@ def run(cmd, redirect_stdout=False, redirect_stderr=False, cwd=None, input=None,
result.returncode = proc.returncode
if check and proc.returncode:
- msg = 'cwd=%s' % cwd
+ msg = f'cwd={cwd}'
if extra_env:
- msg += ', extra env=%s' % extra_env
+ msg += f', extra env={extra_env}'
raise CalledProcessError(
result.returncode, result.cmd, msg=msg,
stdout=ensure_text(result.stdout),
@@ -436,4 +436,4 @@ def run(cmd, redirect_stdout=False, redirect_stderr=False, cwd=None, input=None,
result.stderr = ensure_text(result.stderr)
return result
-# pylint: enable=redefined-builtin,input-builtin
+# pylint: enable=redefined-builtin
diff --git a/rh/utils_unittest.py b/rh/utils_unittest.py
index ea2ddaa..586dfcc 100755
--- a/rh/utils_unittest.py
+++ b/rh/utils_unittest.py
@@ -152,13 +152,13 @@ class RunCommandTests(unittest.TestCase):
def test_stdout_utf8(self):
"""Verify reading UTF-8 data works."""
ret = rh.utils.run(['printf', r'\xc3\x9f'], redirect_stdout=True)
- self.assertEqual(u'ß', ret.stdout)
+ self.assertEqual('ß', ret.stdout)
self.assertIsNone(ret.stderr)
def test_stdin_utf8(self):
"""Verify writing UTF-8 data works."""
- ret = rh.utils.run(['cat'], redirect_stdout=True, input=u'ß')
- self.assertEqual(u'ß', ret.stdout)
+ ret = rh.utils.run(['cat'], redirect_stdout=True, input='ß')
+ self.assertEqual('ß', ret.stdout)
self.assertIsNone(ret.stderr)
def test_check_false(self):
diff --git a/tools/android_test_mapping_format.py b/tools/android_test_mapping_format.py
index ae784cf..a71b94b 100755
--- a/tools/android_test_mapping_format.py
+++ b/tools/android_test_mapping_format.py
@@ -184,12 +184,13 @@ def main(argv):
if opts.commit:
json_data = rh.git.get_file_content(opts.commit, filename)
else:
- with open(os.path.join(opts.project_dir, filename)) as file:
+ with open(os.path.join(opts.project_dir, filename),
+ encoding='utf-8') as file:
json_data = file.read()
process_file(json_data)
except:
- print('Visit %s for details about the format of TEST_MAPPING '
- 'file.' % _TEST_MAPPING_URL, file=sys.stderr)
+ print('Visit {_TEST_MAPPING_URL} for details about the format of '
+ 'TEST_MAPPING file.', file=sys.stderr)
raise
diff --git a/tools/android_test_mapping_format_unittest.py b/tools/android_test_mapping_format_unittest.py
index 14bae32..cf3c3ca 100755
--- a/tools/android_test_mapping_format_unittest.py
+++ b/tools/android_test_mapping_format_unittest.py
@@ -198,25 +198,25 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_valid_test_mapping(self):
"""Verify that the check doesn't raise any error for valid test mapping.
"""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_VALID_TEST_MAPPING)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
android_test_mapping_format.process_file(file.read())
def test_invalid_test_mapping_bad_json(self):
"""Verify that TEST_MAPPING file with bad json can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_JSON)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
ValueError, android_test_mapping_format.process_file,
file.read())
def test_invalid_test_mapping_wrong_test_key(self):
"""Verify that test config using wrong key can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_TEST_WRONG_KEY)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -224,9 +224,9 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_invalid_test_mapping_wrong_test_value(self):
"""Verify that test config using wrong host value can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_TEST_WRONG_HOST_VALUE)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -234,16 +234,16 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_invalid_test_mapping_wrong_preferred_targets_value(self):
"""Verify invalid preferred_targets are rejected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_TEST_WRONG_PREFERRED_TARGETS_VALUE_NONE_LIST)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
file.read())
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_TEST_WRONG_PREFERRED_TARGETS_VALUE_WRONG_TYPE)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -251,9 +251,9 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_invalid_test_mapping_wrong_test_option(self):
"""Verify that test config using wrong option can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_TEST_WRONG_OPTION)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -261,9 +261,9 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_invalid_test_mapping_wrong_import_key(self):
"""Verify that import setting using wrong key can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_IMPORT_WRONG_KEY)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -271,9 +271,9 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_invalid_test_mapping_wrong_import_value(self):
"""Verify that import setting using wrong value can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_IMPORT_WRONG_IMPORT_VALUE)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -281,9 +281,9 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_invalid_test_mapping_file_patterns_value(self):
"""Verify that file_patterns using wrong value can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_BAD_FILE_PATTERNS)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
android_test_mapping_format.InvalidTestMappingError,
android_test_mapping_format.process_file,
@@ -291,16 +291,16 @@ class AndroidTestMappingFormatTests(unittest.TestCase):
def test_valid_test_mapping_file_with_supported_comments(self):
"""Verify that '//'-format comment can be filtered."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_TEST_MAPPING_WITH_SUPPORTED_COMMENTS)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
android_test_mapping_format.process_file(file.read())
def test_valid_test_mapping_file_with_non_supported_comments(self):
"""Verify that non-supported comment can be detected."""
- with open(self.test_mapping_file, 'w') as file:
+ with open(self.test_mapping_file, 'w', encoding='utf-8') as file:
file.write(_TEST_MAPPING_WITH_NON_SUPPORTED_COMMENTS)
- with open(self.test_mapping_file, 'r') as file:
+ with open(self.test_mapping_file, 'r', encoding='utf-8') as file:
self.assertRaises(
ValueError, android_test_mapping_format.process_file,
file.read())
diff --git a/tools/clang-format.py b/tools/clang-format.py
index 2533b15..bb233e6 100755
--- a/tools/clang-format.py
+++ b/tools/clang-format.py
@@ -75,14 +75,14 @@ def main(argv):
if opts.extensions:
cmd.extend(['--extensions', opts.extensions])
if not opts.working_tree:
- cmd.extend(['%s^' % opts.commit, opts.commit])
+ cmd.extend([f'{opts.commit}^', opts.commit])
cmd.extend(['--'] + opts.files)
# Fail gracefully if clang-format itself aborts/fails.
try:
result = rh.utils.run(cmd, capture_output=True)
except rh.utils.CalledProcessError as e:
- print('clang-format failed:\n%s' % (e,), file=sys.stderr)
+ print(f'clang-format failed:\n{e}', file=sys.stderr)
print('\nPlease report this to the clang team.', file=sys.stderr)
return 1
@@ -110,9 +110,9 @@ def main(argv):
else:
print('The following files have formatting errors:')
for filename in diff_filenames:
- print('\t%s' % filename)
- print('You can try to fix this by running:\n%s --fix %s' %
- (sys.argv[0], rh.shell.cmd_to_str(argv)))
+ print(f'\t{filename}')
+ print('You can try to fix this by running:\n'
+ '{sys.argv[0]} --fix {rh.shell.cmd_to_str(argv)}')
return 1
return 0
diff --git a/tools/google-java-format.py b/tools/google-java-format.py
index 6659511..829b8e3 100755
--- a/tools/google-java-format.py
+++ b/tools/google-java-format.py
@@ -66,19 +66,17 @@ def main(argv):
# https://github.com/google/google-java-format/issues/108
format_path = find_executable(opts.google_java_format)
if not format_path:
- print('Unable to find google-java-format at %s' %
- opts.google_java_format)
+ print('Unable to find google-java-format at: {opts.google_java_format}',
+ file=sys.stderr)
return 1
extra_env = {
- 'PATH': '%s%s%s' % (os.path.dirname(format_path),
- os.pathsep,
- os.environ['PATH'])
+ 'PATH': os.path.dirname(format_path) + os.pathsep + os.environ['PATH'],
}
# TODO: Delegate to the tool once this issue is resolved:
# https://github.com/google/google-java-format/issues/107
- diff_cmd = ['git', 'diff', '--no-ext-diff', '-U0', '%s^!' % opts.commit]
+ diff_cmd = ['git', 'diff', '--no-ext-diff', '-U0', f'{opts.commit}^!']
diff_cmd.extend(['--'] + opts.files)
diff = rh.utils.run(diff_cmd, capture_output=True).stdout
@@ -92,8 +90,7 @@ def main(argv):
extra_env=extra_env).stdout
if stdout:
print('One or more files in your commit have Java formatting errors.')
- print('You can run `%s --fix %s` to fix this' %
- (sys.argv[0], rh.shell.cmd_to_str(argv)))
+ print('You can run: {sys.argv[0]} --fix {rh.shell.cmd_to_str(argv)}')
return 1
return 0
diff --git a/tools/pylint.py b/tools/pylint.py
index 570f055..3fbb148 100755
--- a/tools/pylint.py
+++ b/tools/pylint.py
@@ -24,7 +24,7 @@ import subprocess
assert (sys.version_info.major, sys.version_info.minor) >= (3, 6), (
- 'Python 3.6 or newer is required; found %s' % (sys.version,))
+ f'Python 3.6 or newer is required; found {sys.version}')
DEFAULT_PYLINTRC_PATH = os.path.join(
@@ -37,8 +37,8 @@ def is_pylint3(pylint):
result = subprocess.run([pylint, '--version'], stdout=subprocess.PIPE,
check=True)
if b'Python 3' not in result.stdout:
- print('%s: unable to locate a Python 3 version of pylint; Python 3 '
- 'support cannot be guaranteed' % (__file__,), file=sys.stderr)
+ print(f'{__file__}: unable to locate a Python 3 version of pylint; '
+ 'Python 3 support cannot be guaranteed', file=sys.stderr)
return False
return True
@@ -55,8 +55,8 @@ def find_pylint3():
# If there's no pylint, give up.
if not shutil.which('pylint'):
- print('%s: unable to locate pylint; please install:\n'
- 'sudo apt-get install pylint' % (__file__,), file=sys.stderr)
+ print(f'{__file__}: unable to locate pylint; please install:\n'
+ 'sudo apt-get install pylint', file=sys.stderr)
sys.exit(1)
return 'pylint'
@@ -103,7 +103,7 @@ def main(argv):
pylintrc = DEFAULT_PYLINTRC_PATH
# If we pass a non-existent rcfile to pylint, it'll happily ignore
# it.
- assert os.path.exists(pylintrc), 'Could not find %s' % pylintrc
+ assert os.path.exists(pylintrc), f'Could not find {pylintrc}'
cmd += ['--rcfile', pylintrc]
cmd += unknown + opts.files
@@ -116,10 +116,10 @@ def main(argv):
return 0
except OSError as e:
if e.errno == errno.ENOENT:
- print('%s: unable to run `%s`: %s' % (__file__, cmd[0], e),
+ print(f'{__file__}: unable to run `{cmd[0]}`: {e}',
file=sys.stderr)
- print('%s: Try installing pylint: sudo apt-get install %s' %
- (__file__, os.path.basename(cmd[0])), file=sys.stderr)
+ print(f'{__file__}: Try installing pylint: sudo apt-get install '
+ f'{os.path.basename(cmd[0])}', file=sys.stderr)
return 1
raise