diff options
author | Mike Frysinger <vapier@google.com> | 2022-05-02 21:26:41 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-05-02 21:26:41 +0000 |
commit | f5171d0395ca78e89db6479057a4262d87e5abb1 (patch) | |
tree | 3283f637bf7d4cf46840932f09c51600b2bccbd6 | |
parent | 45322b9cde1b0f3bcc343caab21287e7022c5c4f (diff) | |
parent | 0522922843c6ea447d027e6b88a0b22eb6c652a4 (diff) | |
download | repohooks-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-x | pre-upload.py | 59 | ||||
-rw-r--r-- | rh/config.py | 44 | ||||
-rwxr-xr-x | rh/config_test.py | 14 | ||||
-rwxr-xr-x | rh/config_unittest.py | 2 | ||||
-rw-r--r-- | rh/git.py | 22 | ||||
-rw-r--r-- | rh/hooks.py | 99 | ||||
-rwxr-xr-x | rh/hooks_unittest.py | 28 | ||||
-rw-r--r-- | rh/results.py | 5 | ||||
-rw-r--r-- | rh/shell.py | 10 | ||||
-rwxr-xr-x | rh/shell_unittest.py | 10 | ||||
-rw-r--r-- | rh/terminal.py | 22 | ||||
-rw-r--r-- | rh/utils.py | 26 | ||||
-rwxr-xr-x | rh/utils_unittest.py | 6 | ||||
-rwxr-xr-x | tools/android_test_mapping_format.py | 7 | ||||
-rwxr-xr-x | tools/android_test_mapping_format_unittest.py | 48 | ||||
-rwxr-xr-x | tools/clang-format.py | 10 | ||||
-rwxr-xr-x | tools/google-java-format.py | 13 | ||||
-rwxr-xr-x | tools/pylint.py | 18 |
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 @@ -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 |