summaryrefslogtreecommitdiffstats
path: root/gitlint/rule_finder.py
diff options
context:
space:
mode:
Diffstat (limited to 'gitlint/rule_finder.py')
-rw-r--r--gitlint/rule_finder.py137
1 files changed, 0 insertions, 137 deletions
diff --git a/gitlint/rule_finder.py b/gitlint/rule_finder.py
deleted file mode 100644
index 2b8b293..0000000
--- a/gitlint/rule_finder.py
+++ /dev/null
@@ -1,137 +0,0 @@
-import fnmatch
-import inspect
-import os
-import sys
-import importlib
-
-from gitlint import rules, options
-from gitlint.utils import ustr
-
-
-def find_rule_classes(extra_path):
- """
- Searches a given directory or python module for rule classes. This is done by
- adding the directory path to the python path, importing the modules and then finding
- any Rule class in those modules.
-
- :param extra_path: absolute directory or file path to search for rule classes
- :return: The list of rule classes that are found in the given directory or module
- """
-
- files = []
- modules = []
-
- if os.path.isfile(extra_path):
- files = [os.path.basename(extra_path)]
- directory = os.path.dirname(extra_path)
- elif os.path.isdir(extra_path):
- files = os.listdir(extra_path)
- directory = extra_path
- else:
- raise rules.UserRuleError(u"Invalid extra-path: {0}".format(extra_path))
-
- # Filter out files that are not python modules
- for filename in files:
- if fnmatch.fnmatch(filename, '*.py'):
- # We have to treat __init__ files a bit special: add the parent dir instead of the filename, and also
- # add their parent dir to the sys.path (this fixes import issues with pypy2).
- if filename == "__init__.py":
- modules.append(os.path.basename(directory))
- sys.path.append(os.path.dirname(directory))
- else:
- modules.append(os.path.splitext(filename)[0])
-
- # No need to continue if there are no modules specified
- if not modules:
- return []
-
- # Append the extra rules path to python path so that we can import them
- sys.path.append(directory)
-
- # Find all the rule classes in the found python files
- rule_classes = []
- for module in modules:
- # Import the module
- try:
- importlib.import_module(module)
-
- except Exception as e:
- raise rules.UserRuleError(u"Error while importing extra-path module '{0}': {1}".format(module, ustr(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
- # 2) is the parent path the current module. If not, we are dealing with an imported class, skip
- # 3) is it a subclass of rule
- rule_classes.extend([clazz for _, clazz in inspect.getmembers(sys.modules[module])
- if
- inspect.isclass(clazz) and # check isclass to ensure clazz.__module__ exists
- clazz.__module__ == module and # ignore imported classes
- (issubclass(clazz, rules.LineRule) or issubclass(clazz, rules.CommitRule))])
-
- # validate that the rule classes are valid user-defined rules
- for rule_class in rule_classes:
- assert_valid_rule_class(rule_class)
-
- return rule_classes
-
-
-def assert_valid_rule_class(clazz, rule_type="User-defined"):
- """
- Asserts that a given rule clazz is valid by checking a number of its properties:
- - Rules must extend from LineRule or CommitRule
- - Rule classes must have id and name string attributes.
- The options_spec is optional, but if set, it must be a list of gitlint Options.
- - Rule classes must have a validate method. In case of a CommitRule, validate must take a single commit parameter.
- In case of LineRule, validate must take line and commit as first and second parameters.
- - LineRule classes must have a target class attributes that is set to either
- CommitMessageTitle or CommitMessageBody.
- - Rule id's cannot start with R, T, B or M as these rule ids are reserved for gitlint itself.
- """
-
- # Rules must extend from LineRule or CommitRule
- if not (issubclass(clazz, rules.LineRule) or issubclass(clazz, rules.CommitRule)):
- msg = u"{0} rule class '{1}' must extend from {2}.{3} or {2}.{4}"
- raise rules.UserRuleError(msg.format(rule_type, clazz.__name__, rules.CommitRule.__module__,
- rules.LineRule.__name__, rules.CommitRule.__name__))
-
- # Rules must have an id attribute
- if not hasattr(clazz, 'id') or clazz.id is None or not clazz.id:
- msg = u"{0} rule class '{1}' must have an 'id' attribute"
- raise rules.UserRuleError(msg.format(rule_type, clazz.__name__))
-
- # Rule id's cannot start with gitlint reserved letters
- if clazz.id[0].upper() in ['R', 'T', 'B', 'M']:
- msg = u"The id '{1}' of '{0}' is invalid. Gitlint reserves ids starting with R,T,B,M"
- raise rules.UserRuleError(msg.format(clazz.__name__, clazz.id[0]))
-
- # Rules must have a name attribute
- if not hasattr(clazz, 'name') or clazz.name is None or not clazz.name:
- msg = u"{0} rule class '{1}' must have a 'name' attribute"
- raise rules.UserRuleError(msg.format(rule_type, clazz.__name__))
-
- # if set, options_spec must be a list of RuleOption
- if not isinstance(clazz.options_spec, list):
- msg = u"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__))
-
- # check that all items in options_spec are actual gitlint options
- for option in clazz.options_spec:
- if not isinstance(option, options.RuleOption):
- msg = u"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__))
-
- # Rules must have a validate method. We use isroutine() as it's both python 2 and 3 compatible.
- # For more info see http://stackoverflow.com/a/17019998/381010
- if not hasattr(clazz, 'validate') or not inspect.isroutine(clazz.validate):
- msg = u"{0} rule class '{1}' must have a 'validate' method"
- raise rules.UserRuleError(msg.format(rule_type, clazz.__name__))
-
- # 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 = u"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__)
- raise rules.UserRuleError(msg)