diff options
author | Joris Roovers <joris.roovers@gmail.com> | 2020-10-31 12:04:37 +0100 |
---|---|---|
committer | Joris Roovers <joris.roovers@gmail.com> | 2020-11-01 10:58:58 +0100 |
commit | ec1453728770dc8b8877f7aef888c7ccca5a3d05 (patch) | |
tree | 6c412a444cb59dc2696ad1ab3a1ce5f3919fec03 | |
parent | 484117b6261a2a519a572a0a7376bbab4fe15aa7 (diff) |
Replace format() with f-strings
Replaces most occurences for format() with f-strings (supported since
Python 3.6) - this makes for more readable code in most cases.
Relates to #151
29 files changed, 160 insertions, 173 deletions
diff --git a/docs/user_defined_rules.md b/docs/user_defined_rules.md index 88d1dd8..fd944d1 100644 --- a/docs/user_defined_rules.md +++ b/docs/user_defined_rules.md @@ -152,7 +152,7 @@ class SpecialChars(LineRule): # options can be accessed by looking them up by their name in self.options for char in self.options['special-chars'].value: if char in line: - msg = "Title contains the special character '{0}'".format(char) + msg = f"Title contains the special character '{char}'" violation = RuleViolation(self.id, msg, line) violations.append(violation) @@ -262,8 +262,7 @@ class BodyMaxLineCount(CommitRule): line_count = len(commit.message.body) max_line_count = self.options['max-line-count'].value if line_count > max_line_count: - message = "Body contains too many lines ({0} > {1})".format(line_count, - max_line_count) + message = f"Body contains too many lines ({line_count} > {max_line_count})" return [RuleViolation(self.id, message, line_nr=1)] ``` diff --git a/examples/my_commit_rules.py b/examples/my_commit_rules.py index 5e8ce08..5a66c94 100644 --- a/examples/my_commit_rules.py +++ b/examples/my_commit_rules.py @@ -35,7 +35,7 @@ class BodyMaxLineCount(CommitRule): line_count = len(commit.message.body) max_line_count = self.options['max-line-count'].value if line_count > max_line_count: - message = "Body contains too many lines ({0} > {1})".format(line_count, max_line_count) + message = f"Body contains too many lines ({line_count} > {max_line_count})" return [RuleViolation(self.id, message, line_nr=1)] @@ -88,7 +88,7 @@ class BranchNamingConventions(CommitRule): break if not valid_branch_name: - msg = "Branch name '{0}' does not start with one of {1}".format(branch, allowed_branch_prefixes) + msg = f"Branch name '{branch}' does not start with one of {allowed_branch_prefixes}" violations.append(RuleViolation(self.id, msg, line_nr=1)) return violations diff --git a/examples/my_line_rules.py b/examples/my_line_rules.py index 820024a..3a1ef36 100644 --- a/examples/my_line_rules.py +++ b/examples/my_line_rules.py @@ -45,7 +45,7 @@ class SpecialChars(LineRule): # options can be accessed by looking them up by their name in self.options for char in self.options['special-chars'].value: if char in line: - msg = "Title contains the special character '{0}'".format(char) + msg = f"Title contains the special character '{char}'" violation = RuleViolation(self.id, msg, line) violations.append(violation) diff --git a/gitlint/cli.py b/gitlint/cli.py index a42d4c6..76a9734 100644 --- a/gitlint/cli.py +++ b/gitlint/cli.py @@ -187,7 +187,7 @@ class ContextObj: type=click.Path(exists=True, resolve_path=True, file_okay=False, readable=True), help="Path of the target git repository. [default: current working directory]") @click.option('-C', '--config', type=click.Path(exists=True, dir_okay=False, readable=True, resolve_path=True), - help="Config file location [default: {0}]".format(DEFAULT_CONFIG_FILE)) + help=f"Config file location [default: {DEFAULT_CONFIG_FILE}]") @click.option('-c', multiple=True, help="Config flags in format <rule>.<option>=<value> (e.g.: -c T1.line-length=80). " + "Flag can be used multiple times to set multiple config values.") # pylint: disable=bad-continuation @@ -242,10 +242,10 @@ def cli( # pylint: disable=too-many-arguments click.echo(e) ctx.exit(GIT_CONTEXT_ERROR_CODE) except GitLintUsageError as e: - click.echo("Error: {0}".format(e)) + click.echo(f"Error: {e}") ctx.exit(USAGE_ERROR_CODE) except LintConfigError as e: - click.echo("Config Error: {0}".format(e)) + click.echo(f"Config Error: {e}") ctx.exit(CONFIG_ERROR_CODE) @@ -315,7 +315,7 @@ def install_hook(ctx): try: hooks.GitHookInstaller.install_commit_msg_hook(ctx.obj.config) hook_path = hooks.GitHookInstaller.commit_msg_hook_path(ctx.obj.config) - click.echo("Successfully installed gitlint commit-msg hook in {0}".format(hook_path)) + click.echo(f"Successfully installed gitlint commit-msg hook in {hook_path}") ctx.exit(0) except hooks.GitHookInstallerError as e: click.echo(e, err=True) @@ -329,7 +329,7 @@ def uninstall_hook(ctx): try: hooks.GitHookInstaller.uninstall_commit_msg_hook(ctx.obj.config) hook_path = hooks.GitHookInstaller.commit_msg_hook_path(ctx.obj.config) - click.echo("Successfully uninstalled gitlint commit-msg hook from {0}".format(hook_path)) + click.echo(f"Successfully uninstalled gitlint commit-msg hook from {hook_path}") ctx.exit(0) except hooks.GitHookInstallerError as e: click.echo(e, err=True) @@ -411,14 +411,14 @@ def generate_config(ctx): path = os.path.realpath(path) dir_name = os.path.dirname(path) if not os.path.exists(dir_name): - click.echo("Error: Directory '{0}' does not exist.".format(dir_name), err=True) + click.echo(f"Error: Directory '{dir_name}' does not exist.", err=True) ctx.exit(USAGE_ERROR_CODE) elif os.path.exists(path): - click.echo("Error: File \"{0}\" already exists.".format(path), err=True) + click.echo(f"Error: File \"{path}\" already exists.", err=True) ctx.exit(USAGE_ERROR_CODE) LintConfigGenerator.generate_config(path) - click.echo("Successfully generated {0}".format(path)) + click.echo(f"Successfully generated {path}") ctx.exit(0) diff --git a/gitlint/config.py b/gitlint/config.py index 2e50046..91179c9 100644 --- a/gitlint/config.py +++ b/gitlint/config.py @@ -220,7 +220,7 @@ class LintConfig: if rule_class: self.rules.add_rule(rule_class, rule_class.id, {'is_contrib': True}) else: - raise LintConfigError("No contrib rule with id or name '{0}' found.".format(rule_id_or_name)) + raise LintConfigError(f"No contrib rule with id or name '{rule_id_or_name}' found.") except (options.RuleOptionError, rules.UserRuleError) as e: raise LintConfigError(str(e)) @@ -228,11 +228,11 @@ class LintConfig: def _get_option(self, rule_name_or_id, option_name): rule = self.rules.find_rule(rule_name_or_id) if not rule: - raise LintConfigError("No such rule '{0}'".format(rule_name_or_id)) + raise LintConfigError(f"No such rule '{rule_name_or_id}'") option = rule.options.get(option_name) if not option: - raise LintConfigError("Rule '{0}' has no option '{1}'".format(rule_name_or_id, option_name)) + raise LintConfigError(f"Rule '{rule_name_or_id}' has no option '{option_name}'") return option @@ -249,14 +249,14 @@ class LintConfig: try: option.set(option_value) except options.RuleOptionError as e: - msg = "'{0}' is not a valid value for option '{1}.{2}'. {3}." - raise LintConfigError(msg.format(option_value, rule_name_or_id, option_name, e)) + msg = f"'{option_value}' is not a valid value for option '{rule_name_or_id}.{option_name}'. {e}." + raise LintConfigError(msg) def set_general_option(self, option_name, option_value): attr_name = option_name.replace("-", "_") # only allow setting general options that exist and don't start with an underscore if not hasattr(self, attr_name) or attr_name[0] == "_": - raise LintConfigError("'{0}' is not a valid gitlint option".format(option_name)) + raise LintConfigError(f"'{option_name}' is not a valid gitlint option") # else: setattr(self, attr_name, option_value) @@ -280,21 +280,21 @@ class LintConfig: def __str__(self): # config-path is not a user exposed variable, so don't print it under the general section - return_str = "config-path: {0}\n".format(self._config_path) - return_str += "[GENERAL]\n" - return_str += "extra-path: {0}\n".format(self.extra_path) - return_str += "contrib: {0}\n".format(self.contrib) + return_str = f"config-path: {self._config_path}\n" + return_str += f"[GENERAL]\n" + return_str += f"extra-path: {self.extra_path}\n" + return_str += f"contrib: {self.contrib}\n" return_str += "ignore: {0}\n".format(",".join(self.ignore)) - return_str += "ignore-merge-commits: {0}\n".format(self.ignore_merge_commits) - return_str += "ignore-fixup-commits: {0}\n".format(self.ignore_fixup_commits) - return_str += "ignore-squash-commits: {0}\n".format(self.ignore_squash_commits) - return_str += "ignore-revert-commits: {0}\n".format(self.ignore_revert_commits) - return_str += "ignore-stdin: {0}\n".format(self.ignore_stdin) - return_str += "staged: {0}\n".format(self.staged) - return_str += "verbosity: {0}\n".format(self.verbosity) - return_str += "debug: {0}\n".format(self.debug) - return_str += "target: {0}\n".format(self.target) - return_str += "[RULES]\n{0}".format(self.rules) + return_str += f"ignore-merge-commits: {self.ignore_merge_commits}\n" + return_str += f"ignore-fixup-commits: {self.ignore_fixup_commits}\n" + return_str += f"ignore-squash-commits: {self.ignore_squash_commits}\n" + return_str += f"ignore-revert-commits: {self.ignore_revert_commits}\n" + return_str += f"ignore-stdin: {self.ignore_stdin}\n" + return_str += f"staged: {self.staged}\n" + return_str += f"verbosity: {self.verbosity}\n" + return_str += f"debug: {self.debug}\n" + return_str += f"target: {self.target}\n" + return_str += f"[RULES]\n{self.rules}" return return_str @@ -359,7 +359,7 @@ class RuleCollection: def __unicode__(self): return_str = "" for rule in self._rules.values(): - return_str += " {0}: {1}\n".format(rule.id, rule.name) + return_str += f" {rule.id}: {rule.name}\n" for option_name, option_value in sorted(rule.options.items()): if option_value.value is None: option_val_repr = None @@ -369,7 +369,7 @@ class RuleCollection: option_val_repr = option_value.value.pattern else: option_val_repr = option_value.value - return_str += " {0}={1}\n".format(option_name, option_val_repr) + return_str += f" {option_name}={option_val_repr}\n" return return_str @@ -414,12 +414,12 @@ class LintConfigBuilder: self.set_option(rule_name, option_name, option_value) except ValueError: # raised if the config string is invalid raise LintConfigError( - "'{0}' is an invalid configuration option. Use '<rule>.<option>=<value>'".format(config_option)) + f"'{config_option}' is an invalid configuration option. Use '<rule>.<option>=<value>'") def set_from_config_file(self, filename): """ Loads lint config from a ini-style config file """ if not os.path.exists(filename): - raise LintConfigError("Invalid file path: {0}".format(filename)) + raise LintConfigError(f"Invalid file path: {filename}") self._config_path = os.path.realpath(filename) try: parser = ConfigParser() @@ -449,14 +449,14 @@ class LintConfigBuilder: # - not empty # - no whitespace or colons if rule_name == "" or bool(re.search("\\s|:", rule_name, re.UNICODE)): - msg = "The rule-name part in '{0}' cannot contain whitespace, colons or be empty" - raise LintConfigError(msg.format(qualified_rule_name)) + msg = f"The rule-name part in '{qualified_rule_name}' cannot contain whitespace, colons or be empty" + raise LintConfigError(msg) # find parent rule parent_rule = config.rules.find_rule(parent_rule_specifier) if not parent_rule: - msg = "No such rule '{0}' (named rule: '{1}')" - raise LintConfigError(msg.format(parent_rule_specifier, qualified_rule_name)) + msg = f"No such rule '{parent_rule_specifier}' (named rule: '{qualified_rule_name}')" + raise LintConfigError(msg) # Determine canonical id and name by recombining the parent id/name and instance name parts. canonical_id = parent_rule.__class__.id + self.RULE_QUALIFIER_SYMBOL + rule_name diff --git a/gitlint/git.py b/gitlint/git.py index 59f1af0..8f239bf 100644 --- a/gitlint/git.py +++ b/gitlint/git.py @@ -32,8 +32,7 @@ class GitExitCodeError(GitContextError): def __init__(self, command, stderr): self.command = command self.stderr = stderr - super(GitExitCodeError, self).__init__( - "An error occurred while executing '{0}': {1}".format(command, stderr)) + super(GitExitCodeError, self).__init__(f"An error occurred while executing '{command}': {stderr}") def _git(*command_parts, **kwargs): @@ -55,8 +54,7 @@ def _git(*command_parts, **kwargs): error_msg = e.stderr.strip() error_msg_lower = error_msg.lower() if '_cwd' in git_kwargs and b"not a git repository" in error_msg_lower: - error_msg = "{0} is not a git repository.".format(git_kwargs['_cwd']) - raise GitContextError(error_msg) + raise GitContextError(f"{git_kwargs['_cwd']} is not a git repository.") if (b"does not have any commits yet" in error_msg_lower or b"ambiguous argument 'head': unknown revision" in error_msg_lower): @@ -105,7 +103,7 @@ class GitCommitMessage: def from_full_message(context, commit_msg_str): """ Parses a full git commit message by parsing a given string into the different parts of a commit message """ all_lines = commit_msg_str.splitlines() - cutline = "{0} ------------------------ >8 ------------------------".format(context.commentchar) + cutline = f"{context.commentchar} ------------------------ >8 ------------------------" try: cutline_index = all_lines.index(cutline) except ValueError: diff --git a/gitlint/hooks.py b/gitlint/hooks.py index f13acf6..aa3766a 100644 --- a/gitlint/hooks.py +++ b/gitlint/hooks.py @@ -27,7 +27,7 @@ class GitHookInstaller: """ Asserts that a given target directory is a git repository """ hooks_dir = git_hooks_dir(target) if not os.path.isdir(hooks_dir): - raise GitHookInstallerError("{0} is not a git repository.".format(target)) + raise GitHookInstallerError(f"{target} is not a git repository.") @staticmethod def install_commit_msg_hook(lint_config): @@ -35,7 +35,7 @@ class GitHookInstaller: dest_path = GitHookInstaller.commit_msg_hook_path(lint_config) if os.path.exists(dest_path): raise GitHookInstallerError( - "There is already a commit-msg hook file present in {0}.\n".format(dest_path) + + f"There is already a commit-msg hook file present in {dest_path}.\n" + "gitlint currently does not support appending to an existing commit-msg file.") # copy hook file @@ -49,14 +49,14 @@ class GitHookInstaller: GitHookInstaller._assert_git_repo(lint_config.target) dest_path = GitHookInstaller.commit_msg_hook_path(lint_config) if not os.path.exists(dest_path): - raise GitHookInstallerError("There is no commit-msg hook present in {0}.".format(dest_path)) + raise GitHookInstallerError(f"There is no commit-msg hook present in {dest_path}.") with io.open(dest_path, encoding=DEFAULT_ENCODING) as fp: lines = fp.readlines() if len(lines) < 2 or lines[1] != GITLINT_HOOK_IDENTIFIER: - msg = "The commit-msg hook in {0} was not installed by gitlint (or it was modified).\n" + \ + msg = f"The commit-msg hook in {dest_path} was not installed by gitlint (or it was modified).\n" + \ "Uninstallation of 3th party or modified gitlint hooks is not supported." - raise GitHookInstallerError(msg.format(dest_path)) + raise GitHookInstallerError(msg) # If we are sure it's a gitlint hook, go ahead and remove it os.remove(dest_path) diff --git a/gitlint/lint.py b/gitlint/lint.py index f9e1e1a..4b6c8a3 100644 --- a/gitlint/lint.py +++ b/gitlint/lint.py @@ -78,8 +78,8 @@ class GitLinter: # Skip linting if this is a special commit type that is configured to be ignored ignore_commit_types = ["merge", "squash", "fixup", "revert"] for commit_type in ignore_commit_types: - if getattr(commit, "is_{0}_commit".format(commit_type)) and \ - getattr(self.config, "ignore_{0}_commits".format(commit_type)): + if getattr(commit, f"is_{commit_type}_commit") and \ + getattr(self.config, f"ignore_{commit_type}_commits"): return [] violations = [] @@ -98,10 +98,9 @@ class GitLinter: """ Print a given set of violations to the standard error output """ for v in violations: line_nr = v.line_nr if v.line_nr else "-" - self.display.e("{0}: {1}".format(line_nr, v.rule_id), exact=True) - self.display.ee("{0}: {1} {2}".format(line_nr, v.rule_id, v.message), exact=True) + self.display.e(f"{line_nr}: {v.rule_id}", exact=True) + self.display.ee(f"{line_nr}: {v.rule_id} {v.message}", exact=True) if v.content: - self.display.eee("{0}: {1} {2}: \"{3}\"".format(line_nr, v.rule_id, v.message, v.content), - exact=True) + self.display.eee(f"{line_nr}: {v.rule_id} {v.message}: \"{v.content}\"", exact=True) else: - self.display.eee("{0}: {1} {2}".format(line_nr, v.rule_id, v.message), exact=True) + self.display.eee(f"{line_nr}: {v.rule_id} {v.message}", exact=True) diff --git a/gitlint/options.py b/gitlint/options.py index a4981bc..f9e1071 100644 --- a/gitlint/options.py +++ b/gitlint/options.py @@ -41,7 +41,7 @@ class RuleOption: return self # pragma: no cover def __unicode__(self): - return "({0}: {1} ({2}))".format(self.name, self.value, self.description) # pragma: no cover + return f"({self.name}: {self.value} ({self.description}))" # pragma: no cover def __repr__(self): return self.__str__() # pragma: no cover @@ -63,9 +63,9 @@ class IntOption(RuleOption): def _raise_exception(self, value): if self.allow_negative: - error_msg = "Option '{0}' must be an integer (current value: '{1}')".format(self.name, value) + error_msg = f"Option '{self.name}' must be an integer (current value: '{value}')" else: - error_msg = "Option '{0}' must be a positive integer (current value: '{1}')".format(self.name, value) + error_msg = f"Option '{self.name}' must be a positive integer (current value: '{value}')" raise RuleOptionError(error_msg) @allow_none @@ -85,7 +85,7 @@ class BoolOption(RuleOption): def set(self, value): value = str(value).strip().lower() if value not in ['true', 'false']: - raise RuleOptionError("Option '{0}' must be either 'true' or 'false'".format(self.name)) + raise RuleOptionError(f"Option '{self.name}' must be either 'true' or 'false'") self.value = value == 'true' @@ -118,17 +118,16 @@ class PathOption(RuleOption): if self.type == 'dir': if not os.path.isdir(value): - error_msg = "Option {0} must be an existing directory (current value: '{1}')".format(self.name, value) + error_msg = f"Option {self.name} must be an existing directory (current value: '{value}')" elif self.type == 'file': if not os.path.isfile(value): - error_msg = "Option {0} must be an existing file (current value: '{1}')".format(self.name, value) + error_msg = f"Option {self.name} must be an existing file (current value: '{value}')" elif self.type == 'both': if not os.path.isdir(value) and not os.path.isfile(value): - error_msg = ("Option {0} must be either an existing directory or file " - "(current value: '{1}')").format(self.name, value) + error_msg = (f"Option {self.name} must be either an existing directory or file " + f"(current value: '{value}')") else: - error_msg = "Option {0} type must be one of: 'file', 'dir', 'both' (current: '{1}')".format(self.name, - self.type) + error_msg = f"Option {self.name} type must be one of: 'file', 'dir', 'both' (current: '{self.type}')" if error_msg: raise RuleOptionError(error_msg) @@ -143,7 +142,7 @@ class RegexOption(RuleOption): try: self.value = re.compile(value, re.UNICODE) except (re.error, TypeError) as exc: - raise RuleOptionError("Invalid regular expression: '{0}'".format(exc)) + raise RuleOptionError(f"Invalid regular expression: '{exc}'") def __deepcopy__(self, _): # copy.deepcopy() - used in rules.py - doesn't support copying regex objects prior to Python 3.7 diff --git a/gitlint/rule_finder.py b/gitlint/rule_finder.py index c1528df..e1c5e77 100644 --- a/gitlint/rule_finder.py +++ b/gitlint/rule_finder.py @@ -27,7 +27,7 @@ def find_rule_classes(extra_path): files = os.listdir(extra_path) directory = extra_path else: - raise rules.UserRuleError("Invalid extra-path: {0}".format(extra_path)) + raise rules.UserRuleError(f"Invalid extra-path: {extra_path}") # Filter out files that are not python modules for filename in files: @@ -55,7 +55,7 @@ def find_rule_classes(extra_path): importlib.import_module(module) except Exception as e: - raise rules.UserRuleError("Error while importing extra-path module '{0}': {1}".format(module, e)) + raise rules.UserRuleError(f"Error while importing extra-path module '{module}': {e}") # Find all rule classes in the module. We do this my inspecting all members of the module and checking # 1) is it a class, if not, skip @@ -93,55 +93,53 @@ def assert_valid_rule_class(clazz, rule_type="User-defined"): # pylint: disable # Rules must extend from LineRule, CommitRule or ConfigurationRule if not (issubclass(clazz, rules.LineRule) or issubclass(clazz, rules.CommitRule) or issubclass(clazz, rules.ConfigurationRule)): - msg = "{0} rule class '{1}' must extend from {2}.{3}, {2}.{4} or {2}.{5}" - raise rules.UserRuleError(msg.format(rule_type, clazz.__name__, rules.CommitRule.__module__, - rules.LineRule.__name__, rules.CommitRule.__name__, - rules.ConfigurationRule.__name__)) + msg = f"{rule_type} rule class '{clazz.__name__}' " + \ + f"must extend from {rules.CommitRule.__module__}.{rules.LineRule.__name__}, " + \ + f"{rules.CommitRule.__module__}.{rules.CommitRule.__name__} or " + \ + f"{rules.CommitRule.__module__}.{rules.ConfigurationRule.__name__}" + raise rules.UserRuleError(msg) # Rules must have an id attribute if not hasattr(clazz, 'id') or clazz.id is None or not clazz.id: - msg = "{0} rule class '{1}' must have an 'id' attribute" - raise rules.UserRuleError(msg.format(rule_type, clazz.__name__)) + raise rules.UserRuleError(f"{rule_type} rule class '{clazz.__name__}' must have an 'id' attribute") # Rule id's cannot start with gitlint reserved letters if clazz.id[0].upper() in ['R', 'T', 'B', 'M', 'I']: - msg = "The id '{1}' of '{0}' is invalid. Gitlint reserves ids starting with R,T,B,M,I" - raise rules.UserRuleError(msg.format(clazz.__name__, clazz.id[0])) + msg = f"The id '{clazz.id[0]}' of '{clazz.__name__}' is invalid. Gitlint reserves ids starting with R,T,B,M,I" + raise rules.UserRuleError(msg) # Rules must have a name attribute if not hasattr(clazz, 'name') or clazz.name is None or not clazz.name: - msg = "{0} rule class '{1}' must have a 'name' attribute" - raise rules.UserRuleError(msg.format(rule_type, clazz.__name__)) + raise rules.UserRuleError(f"{rule_type} rule class '{clazz.__name__}' must have a 'name' attribute") # if set, options_spec must be a list of RuleOption if not isinstance(clazz.options_spec, list): - msg = "The options_spec attribute of {0} rule class '{1}' must be a list of {2}.{3}" - raise rules.UserRuleError(msg.format(rule_type.lower(), clazz.__name__, - options.RuleOption.__module__, options.RuleOption.__name__)) + msg = f"The options_spec attribute of {rule_type.lower()} rule class '{clazz.__name__}' " + \ + f"must be a list of {options.RuleOption.__module__}.{options.RuleOption.__name__}" + raise rules.UserRuleError(msg) # check that all items in options_spec are actual gitlint options for option in clazz.options_spec: if not isinstance(option, options.RuleOption): - msg = "The options_spec attribute of {0} rule class '{1}' must be a list of {2}.{3}" - raise rules.UserRuleError(msg.format(rule_type.lower(), clazz.__name__, - options.RuleOption.__module__, options.RuleOption.__name__)) + msg = f"The options_spec attribute of {rule_type.lower()} rule class '{clazz.__name__}' " + \ + f"must be a list of {options.RuleOption.__module__}.{options.RuleOption.__name__}" + raise rules.UserRuleError(msg) # Line/Commit rules must have a `validate` method # We use isroutine() as it's both python 2 and 3 compatible. Details: http://stackoverflow.com/a/17019998/381010 if (issubclass(clazz, rules.LineRule) or issubclass(clazz, rules.CommitRule)): if not hasattr(clazz, 'validate') or not inspect.isroutine(clazz.validate): - msg = "{0} rule class '{1}' must have a 'validate' method" - raise rules.UserRuleError(msg.format(rule_type, clazz.__name__)) + raise rules.UserRuleError(f"{rule_type} rule class '{clazz.__name__}' must have a 'validate' method") # Configuration rules must have an `apply` method elif issubclass(clazz, rules.ConfigurationRule): if not hasattr(clazz, 'apply') or not inspect.isroutine(clazz.apply): - msg = "{0} Configuration rule class '{1}' must have an 'apply' method" - raise rules.UserRuleError(msg.format(rule_type, clazz.__name__)) + msg = f"{rule_type} Configuration rule class '{clazz.__name__}' must have an 'apply' method" + raise rules.UserRuleError(msg) # LineRules must have a valid target: rules.CommitMessageTitle or rules.CommitMessageBody if issubclass(clazz, rules.LineRule): if clazz.target not in [rules.CommitMessageTitle, rules.CommitMessageBody]: - msg = "The target attribute of the {0} LineRule class '{1}' must be either {2}.{3} or {2}.{4}" - msg = msg.format(rule_type.lower(), clazz.__name__, rules.CommitMessageTitle.__module__, - rules.CommitMessageTitle.__name__, rules.CommitMessageBody.__name__) + msg = f"The target attribute of the {rule_type.lower()} LineRule class '{clazz.__name__}' " + \ + f"must be either {rules.CommitMessageTitle.__module__}.{rules.CommitMessageTitle.__name__} " + \ + f"or {rules.CommitMessageTitle.__module__}.{rules.CommitMessageBody.__name__}" raise rules.UserRuleError(msg) diff --git a/gitlint/rules.py b/gitlint/rules.py index e944ce0..32e0327 100644 --- a/gitlint/rules.py +++ b/gitlint/rules.py @@ -39,7 +39,7 @@ class Rule: return self # pragma: no cover def __unicode__(self): - return "{0} {1}".format(self.id, self.name) # pragma: no cover + return f"{self.id} {self.name}" # pragma: no cover def __repr__(self): return self.__str__() # pragma: no cover @@ -96,8 +96,7 @@ class RuleViolation: return self # pragma: no cover def __unicode__(self): - return f"{0}: {1} {2}: \"{3}\"".format(self.line_nr, self.rule_id, self.message, - self.content) # pragma: no cover + return f"{self.line_nr}: {self.rule_id} {self.message}: \"{self.content}\"" # pragma: no cover def __repr__(self): return self.__unicode__() # pragma: no cover @@ -195,7 +194,7 @@ class TitleTrailingPunctuation(LineRule): punctuation_marks = '?:!.,;' for punctuation_mark in punctuation_marks: if title.endswith(punctuation_mark): - return [RuleViolation(self.id, "Title has trailing punctuation ({0})".format(punctuation_mark), title)] + return [RuleViolation(self.id, f"Title has trailing punctuation ({punctuation_mark})", title)] class TitleHardTab(HardTab): @@ -232,7 +231,7 @@ class TitleRegexMatches(LineRule): return if not self.options['regex'].value.search(title): - violation_msg = "Title does not match regex ({0})".format(self.options['regex'].value.pattern) + violation_msg = f"Title does not match regex ({self.options['regex'].value.pattern})" return [RuleViolation(self.id, violation_msg, title)] @@ -246,7 +245,7 @@ class TitleMinLength(LineRule): min_length = self.options['min-length'].value actual_length = len(title) if actual_length < min_length: - violation_message = "Title is too short ({0}<{1})".format(actual_length, min_length) + violation_message = f"Title is too short ({actual_length}<{min_length})" return [RuleViolation(self.id, violation_message, title, 1)] @@ -289,7 +288,7 @@ class BodyMinLength(CommitRule): body_message_no_newline = "".join([line for line in commit.message.body if line is not None]) actual_length = len(body_message_no_newline) if 0 < actual_length < min_length: - violation_message = "Body message is too short ({0}<{1})".format(actual_length, min_length) + violation_message = f"Body message is too short ({actual_length}<{min_length})" return [RuleViolation(self.id, violation_message, body_message_no_newline, 3)] @@ -318,7 +317,7 @@ class BodyChangedFileMention(CommitRule): # in the commit msg body if needs_mentioned_file in commit.changed_files: if needs_mentioned_file not in " ".join(commit.message.body): - violation_message = "Body does not mention changed file '{0}'".format(needs_mentioned_file) + violation_message = f"Body does not m |