def find_rule_classes(extra_path):
files = []<EOL>modules = []<EOL>if os.path.isfile(extra_path):<EOL><INDENT>files = [os.path.basename(extra_path)]<EOL>directory = os.path.dirname(extra_path)<EOL><DEDENT>elif os.path.isdir(extra_path):<EOL><INDENT>files = os.listdir(extra_path)<EOL>directory = extra_path<EOL><DEDENT>else:<EOL><INDENT>raise UserRuleError(u"<STR_LIT>".format(extra_path))<EOL><DEDENT>for filename in files:<EOL><INDENT>if fnmatch.fnmatch(filename, '<STR_LIT>'):<EOL><INDENT>modules.append(os.path.splitext(filename)[<NUM_LIT:0>])<EOL><DEDENT><DEDENT>if not modules:<EOL><INDENT>return []<EOL><DEDENT>sys.path.append(directory)<EOL>rule_classes = []<EOL>for module in modules:<EOL><INDENT>try:<EOL><INDENT>importlib.import_module(module)<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise UserRuleError(u"<STR_LIT>".format(module, ustr(e)))<EOL><DEDENT>rule_classes.extend([clazz for _, clazz in inspect.getmembers(sys.modules[module])<EOL>if<EOL>inspect.isclass(clazz) and  <EOL>clazz.__module__ == module and  <EOL>(issubclass(clazz, rules.LineRule) or issubclass(clazz, rules.CommitRule))])<EOL>for rule_class in rule_classes:<EOL><INDENT>assert_valid_rule_class(rule_class)<EOL><DEDENT><DEDENT>return rule_classes<EOL>
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