summaryrefslogtreecommitdiffstats
path: root/gitlint/config.py
diff options
context:
space:
mode:
Diffstat (limited to 'gitlint/config.py')
-rw-r--r--gitlint/config.py117
1 files changed, 49 insertions, 68 deletions
diff --git a/gitlint/config.py b/gitlint/config.py
index 4dad707..1eeb35d 100644
--- a/gitlint/config.py
+++ b/gitlint/config.py
@@ -1,9 +1,4 @@
-try:
- # python 2.x
- from ConfigParser import ConfigParser, Error as ConfigParserError
-except ImportError: # pragma: no cover
- # python 3.x
- from configparser import ConfigParser, Error as ConfigParserError # pragma: no cover, pylint: disable=import-error
+from configparser import ConfigParser, Error as ConfigParserError
import copy
import io
@@ -12,11 +7,12 @@ import os
import shutil
from collections import OrderedDict
-from gitlint.utils import ustr, sstr, DEFAULT_ENCODING
+from gitlint.utils import DEFAULT_ENCODING
from gitlint import rules # For some weird reason pylint complains about this, pylint: disable=unused-import
from gitlint import options
from gitlint import rule_finder
from gitlint.contrib import rules as contrib_rules
+from gitlint.exception import GitlintError
def handle_option_error(func):
@@ -27,16 +23,16 @@ def handle_option_error(func):
try:
return func(*args)
except options.RuleOptionError as e:
- raise LintConfigError(ustr(e))
+ raise LintConfigError(str(e)) from e
return wrapped
-class LintConfigError(Exception):
+class LintConfigError(GitlintError):
pass
-class LintConfig(object):
+class LintConfig:
""" Class representing gitlint configuration.
Contains active config as well as number of methods to easily get/set the config.
"""
@@ -198,7 +194,7 @@ class LintConfig(object):
self.rules.add_rules(rule_classes, {'is_user_defined': True})
except (options.RuleOptionError, rules.UserRuleError) as e:
- raise LintConfigError(ustr(e))
+ raise LintConfigError(str(e)) from e
@property
def contrib(self):
@@ -219,27 +215,25 @@ class LintConfig(object):
# For each specified contrib rule, check whether it exists among the contrib classes
for rule_id_or_name in self.contrib:
rule_class = next((rc for rc in rule_classes if
- rc.id == ustr(rule_id_or_name) or rc.name == ustr(rule_id_or_name)), False)
+ rule_id_or_name in (rc.id, rc.name)), False)
# If contrib rule exists, instantiate it and add it to the rules list
if rule_class:
self.rules.add_rule(rule_class, rule_class.id, {'is_contrib': True})
else:
- raise LintConfigError(u"No contrib rule with id or name '{0}' found.".format(ustr(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(ustr(e))
+ raise LintConfigError(str(e)) from e
def _get_option(self, rule_name_or_id, option_name):
- rule_name_or_id = ustr(rule_name_or_id) # convert to unicode first
- option_name = ustr(option_name)
rule = self.rules.find_rule(rule_name_or_id)
if not rule:
- raise LintConfigError(u"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(u"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
@@ -256,14 +250,14 @@ class LintConfig(object):
try:
option.set(option_value)
except options.RuleOptionError as e:
- msg = u"'{0}' is not a valid value for option '{1}.{2}'. {3}."
- raise LintConfigError(msg.format(option_value, rule_name_or_id, option_name, ustr(e)))
+ msg = f"'{option_value}' is not a valid value for option '{rule_name_or_id}.{option_name}'. {e}."
+ raise LintConfigError(msg) from e
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(u"'{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)
@@ -285,30 +279,26 @@ class LintConfig(object):
self.ignore == other.ignore and \
self._config_path == other._config_path # noqa
- def __ne__(self, other):
- return not self.__eq__(other) # required for py2
-
def __str__(self):
# config-path is not a user exposed variable, so don't print it under the general section
- return_str = u"config-path: {0}\n".format(self._config_path)
- return_str += u"[GENERAL]\n"
- return_str += u"extra-path: {0}\n".format(self.extra_path)
- return_str += u"contrib: {0}\n".format(sstr(self.contrib))
- return_str += u"ignore: {0}\n".format(",".join(self.ignore))
- return_str += u"ignore-merge-commits: {0}\n".format(self.ignore_merge_commits)
- return_str += u"ignore-fixup-commits: {0}\n".format(self.ignore_fixup_commits)
- return_str += u"ignore-squash-commits: {0}\n".format(self.ignore_squash_commits)
- return_str += u"ignore-revert-commits: {0}\n".format(self.ignore_revert_commits)
- return_str += u"ignore-stdin: {0}\n".format(self.ignore_stdin)
- return_str += u"staged: {0}\n".format(self.staged)
- return_str += u"verbosity: {0}\n".format(self.verbosity)
- return_str += u"debug: {0}\n".format(self.debug)
- return_str += u"target: {0}\n".format(self.target)
- return_str += u"[RULES]\n{0}".format(self.rules)
- return return_str
-
-
-class RuleCollection(object):
+ return (f"config-path: {self._config_path}\n"
+ f"[GENERAL]\n"
+ f"extra-path: {self.extra_path}\n"
+ f"contrib: {self.contrib}\n"
+ f"ignore: {','.join(self.ignore)}\n"
+ f"ignore-merge-commits: {self.ignore_merge_commits}\n"
+ f"ignore-fixup-commits: {self.ignore_fixup_commits}\n"
+ f"ignore-squash-commits: {self.ignore_squash_commits}\n"
+ f"ignore-revert-commits: {self.ignore_revert_commits}\n"
+ f"ignore-stdin: {self.ignore_stdin}\n"
+ f"staged: {self.staged}\n"
+ f"verbosity: {self.verbosity}\n"
+ f"debug: {self.debug}\n"
+ f"target: {self.target}\n"
+ f"[RULES]\n{self.rules}")
+
+
+class RuleCollection:
""" Class representing an ordered list of rules. Methods are provided to easily retrieve, add or delete rules. """
def __init__(self, rule_classes=None, rule_attrs=None):
@@ -318,8 +308,6 @@ class RuleCollection(object):
self.add_rules(rule_classes, rule_attrs)
def find_rule(self, rule_id_or_name):
- # try finding rule by id
- rule_id_or_name = ustr(rule_id_or_name) # convert to unicode first
rule = self._rules.get(rule_id_or_name)
# if not found, try finding rule by name
if not rule:
@@ -351,7 +339,7 @@ class RuleCollection(object):
""" Deletes all rules from the collection that match a given attribute name and value """
# Create a new list based on _rules.values() because in python 3, values() is a ValuesView as opposed to a list
# This means you can't modify the ValueView while iterating over it.
- for rule in [r for r in self._rules.values()]:
+ for rule in [r for r in self._rules.values()]: # pylint: disable=unnecessary-comprehension
if hasattr(rule, attr_name) and (getattr(rule, attr_name) == attr_val):
del self._rules[rule.id]
@@ -362,19 +350,13 @@ class RuleCollection(object):
def __eq__(self, other):
return isinstance(other, RuleCollection) and self._rules == other._rules
- def __ne__(self, other):
- return not self.__eq__(other) # required for py2
-
def __len__(self):
return len(self._rules)
- def __repr__(self):
- return self.__unicode__() # pragma: no cover
-
- def __unicode__(self):
+ def __str__(self):
return_str = ""
for rule in self._rules.values():
- return_str += u" {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
@@ -384,11 +366,11 @@ class RuleCollection(object):
option_val_repr = option_value.value.pattern
else:
option_val_repr = option_value.value
- return_str += u" {0}={1}\n".format(option_name, option_val_repr)
+ return_str += f" {option_name}={option_val_repr}\n"
return return_str
-class LintConfigBuilder(object):
+class LintConfigBuilder:
""" Factory class that can build gitlint config.
This is primarily useful to deal with complex configuration scenarios where configuration can be set and overridden
from various sources (typically according to certain precedence rules) before the actual config should be
@@ -427,28 +409,27 @@ class LintConfigBuilder(object):
raise ValueError()
rule_name, option_name = config_name.split(".", 1)
self.set_option(rule_name, option_name, option_value)
- except ValueError: # raised if the config string is invalid
+ except ValueError as e: # raised if the config string is invalid
raise LintConfigError(
- u"'{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>'") from e
def set_from_config_file(self, filename):
""" Loads lint config from a ini-style config file """
if not os.path.exists(filename):
- raise LintConfigError(u"Invalid file path: {0}".format(filename))
+ raise LintConfigError(f"Invalid file path: {filename}")
self._config_path = os.path.realpath(filename)
try:
parser = ConfigParser()
with io.open(filename, encoding=DEFAULT_ENCODING) as config_file:
- # readfp() is deprecated in python 3.2+, but compatible with 2.7
- parser.readfp(config_file, filename) # pylint: disable=deprecated-method
+ parser.read_file(config_file, filename)
for section_name in parser.sections():
for option_name, option_value in parser.items(section_name):
- self.set_option(section_name, option_name, ustr(option_value))
+ self.set_option(section_name, option_name, str(option_value))
except ConfigParserError as e:
- raise LintConfigError(ustr(e))
+ raise LintConfigError(str(e)) from e
def _add_named_rule(self, config, qualified_rule_name):
""" Adds a Named Rule to a given LintConfig object.
@@ -465,14 +446,14 @@ class LintConfigBuilder(object):
# - not empty
# - no whitespace or colons
if rule_name == "" or bool(re.search("\\s|:", rule_name, re.UNICODE)):
- msg = u"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 = u"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
@@ -525,7 +506,7 @@ class LintConfigBuilder(object):
GITLINT_CONFIG_TEMPLATE_SRC_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "files/gitlint")
-class LintConfigGenerator(object):
+class LintConfigGenerator:
@staticmethod
def generate_config(dest):
""" Generates a gitlint config file at the given destination location.