def test_ignore_named_rules(self): """ Test that named rules can be ignored """ # Add named rule to lint config config_builder = LintConfigBuilder() rule_id = TitleMustNotContainWord.id + u":my-ïd" config_builder.set_option(rule_id, "words", [u"Föo"]) lint_config = config_builder.build() linter = GitLinter(lint_config) commit = self.gitcommit(u"WIP: Föo bar\n\nFoo bår hur dur bla bla") # By default, we expect both the violations of the regular rule as well as the named rule to show up violations = [ RuleViolation("T5", u"Title contains the word 'WIP' (case-insensitive)", u"WIP: Föo bar", 1), RuleViolation(u"T5:my-ïd", u"Title contains the word 'Föo' (case-insensitive)", u"WIP: Föo bar", 1) ] self.assertListEqual(violations, linter.lint(commit)) # ignore regular rule: only named rule violations show up lint_config.ignore = ["T5"] self.assertListEqual(violations[1:], linter.lint(commit)) # ignore named rule by id: only regular rule violations show up lint_config.ignore = [rule_id] self.assertListEqual(violations[:-1], linter.lint(commit)) # ignore named rule by name: only regular rule violations show up lint_config.ignore = [TitleMustNotContainWord.name + u":my-ïd"] self.assertListEqual(violations[:-1], linter.lint(commit))
def test_named_rules(self): # Store a copy of the default rules from the config, so we can reference it later config_builder = LintConfigBuilder() config = config_builder.build() default_rules = copy.deepcopy(config.rules) self.assertEqual(default_rules, config.rules) # deepcopy should be equal # Add a named rule by setting an option in the config builder that follows the named rule pattern # Assert that whitespace in the rule name is stripped rule_qualifiers = [u'T7:my-extra-rüle', u' T7 : my-extra-rüle ', u'\tT7:\tmy-extra-rüle\t', u'T7:\t\n \tmy-extra-rüle\t\n\n', "title-match-regex:my-extra-rüle"] for rule_qualifier in rule_qualifiers: config_builder = LintConfigBuilder() config_builder.set_option(rule_qualifier, 'regex', "föo") expected_rules = copy.deepcopy(default_rules) my_rule = rules.TitleRegexMatches({'regex': "föo"}) my_rule.id = rules.TitleRegexMatches.id + ":my-extra-rüle" my_rule.name = rules.TitleRegexMatches.name + ":my-extra-rüle" expected_rules._rules[u'T7:my-extra-rüle'] = my_rule self.assertEqual(config_builder.build().rules, expected_rules) # assert that changing an option on the newly added rule is passed correctly to the RuleCollection # we try this with all different rule qualifiers to ensure they all are normalized and map # to the same rule for other_rule_qualifier in rule_qualifiers: cb = config_builder.clone() cb.set_option(other_rule_qualifier, 'regex', other_rule_qualifier + "bōr") # before setting the expected rule option value correctly, the RuleCollection should be different self.assertNotEqual(cb.build().rules, expected_rules) # after setting the option on the expected rule, it should be equal my_rule.options['regex'].set(other_rule_qualifier + "bōr") self.assertEqual(cb.build().rules, expected_rules) my_rule.options['regex'].set("wrong")
def test_rebuild_config(self): # normal config build config_builder = LintConfigBuilder() config_builder.set_option('general', 'verbosity', 3) lint_config = config_builder.build() self.assertEqual(lint_config.verbosity, 3) # check that existing config changes when we rebuild it existing_lintconfig = LintConfig() existing_lintconfig.verbosity = 2 lint_config = config_builder.build(existing_lintconfig) self.assertEqual(lint_config.verbosity, 3)
def test_rebuild_config(self): # normal config build config_builder = LintConfigBuilder() config_builder.set_option('general', 'verbosity', 3) lint_config = config_builder.build() self.assertEqual(lint_config.verbosity, 3) # check that existing config changes when we rebuild it existing_lintconfig = LintConfig() existing_lintconfig.verbosity = 2 lint_config = config_builder.build(existing_lintconfig) self.assertEqual(lint_config.verbosity, 3)
def test_general_option_after_rule_option(self): # We used to have a bug where we didn't process general options before setting specific options, this would # lead to errors when e.g.: trying to configure a user rule before the rule class was loaded by extra-path # This test is here to test for regressions against this. config_builder = LintConfigBuilder() config_builder.set_option(u'my-üser-commit-rule', 'violation-count', 3) user_rules_path = self.get_sample_path("user_rules") config_builder.set_option('general', 'extra-path', user_rules_path) config = config_builder.build() self.assertEqual(config.extra_path, user_rules_path) self.assertEqual(config.get_rule_option(u'my-üser-commit-rule', 'violation-count'), 3)
def test_rebuild_config(self): # normal config build config_builder = LintConfigBuilder() config_builder.set_option('general', 'verbosity', 3) lint_config = config_builder.build() self.assertEqual(lint_config.verbosity, 3) # check that existing config gets overwritten when we pass it to a configbuilder with different options existing_lintconfig = LintConfig() existing_lintconfig.verbosity = 2 lint_config = config_builder.build(existing_lintconfig) self.assertEqual(lint_config.verbosity, 3) self.assertEqual(existing_lintconfig.verbosity, 3)
def test_named_rules_negative(self): # T7 = title-match-regex # Invalid rule name for invalid_name in [ "", " ", " ", "\t", "\n", u"å b", u"å:b", u"åb:", u":åb" ]: config_builder = LintConfigBuilder() config_builder.set_option(u"T7:{0}".format(invalid_name), 'regex', u"tëst") expected_msg = u"The rule-name part in 'T7:{0}' cannot contain whitespace, colons or be empty" with self.assertRaisesMessage(LintConfigError, expected_msg.format(invalid_name)): config_builder.build() # Invalid parent rule name config_builder = LintConfigBuilder() config_builder.set_option(u"Ž123:foöbar", u"fåke-option", u"fåke-value") with self.assertRaisesMessage( LintConfigError, u"No such rule 'Ž123' (named rule: 'Ž123:foöbar')"): config_builder.build() # Invalid option name (this is the same as with regular rules) config_builder = LintConfigBuilder() config_builder.set_option(u"T7:foöbar", u"blå", u"my-rëgex") with self.assertRaisesMessage(LintConfigError, u"Rule 'T7:foöbar' has no option 'blå'"): config_builder.build()
def test_clone(self): config_builder = LintConfigBuilder() config_builder.set_option('general', 'verbosity', 2) config_builder.set_option('title-max-length', 'line-length', 100) expected = {'title-max-length': {'line-length': 100}, 'general': {'verbosity': 2}} self.assertDictEqual(config_builder._config_blueprint, expected) # Clone and verify that the blueprint is the same as the original cloned_builder = config_builder.clone() self.assertDictEqual(cloned_builder._config_blueprint, expected) # Modify the original and make sure we're not modifying the clone (i.e. check that the copy is a deep copy) config_builder.set_option('title-max-length', 'line-length', 120) self.assertDictEqual(cloned_builder._config_blueprint, expected)
def test_set_option(self): config_builder = LintConfigBuilder() config = config_builder.build() # assert some defaults self.assertEqual( config.get_rule_option('title-max-length', 'line-length'), 72) self.assertEqual( config.get_rule_option('body-max-line-length', 'line-length'), 80) self.assertListEqual( config.get_rule_option('title-must-not-contain-word', 'words'), ["WIP"]) self.assertEqual(config.verbosity, 3) # Make some changes and check blueprint config_builder.set_option('title-max-length', 'line-length', 100) config_builder.set_option('general', 'verbosity', 2) config_builder.set_option('title-must-not-contain-word', 'words', ["foo", "bar"]) expected_blueprint = { 'title-must-not-contain-word': { 'words': ['foo', 'bar'] }, 'title-max-length': { 'line-length': 100 }, 'general': { 'verbosity': 2 } } self.assertDictEqual(config_builder._config_blueprint, expected_blueprint) # Build config and verify that the changes have occurred and no other changes config = config_builder.build() self.assertEqual( config.get_rule_option('title-max-length', 'line-length'), 100) self.assertEqual( config.get_rule_option('body-max-line-length', 'line-length'), 80) # should be unchanged self.assertListEqual( config.get_rule_option('title-must-not-contain-word', 'words'), ["foo", "bar"]) self.assertEqual(config.verbosity, 2)
def build_config( # pylint: disable=too-many-arguments target, config_path, c, extra_path, ignore, contrib, ignore_stdin, staged, verbose, silent, debug): """ Creates a LintConfig object based on a set of commandline parameters. """ config_builder = LintConfigBuilder() # Config precedence: # First, load default config or config from configfile if config_path: config_builder.set_from_config_file(config_path) elif os.path.exists(DEFAULT_CONFIG_FILE): config_builder.set_from_config_file(DEFAULT_CONFIG_FILE) # Then process any commandline configuration flags config_builder.set_config_from_string_list(c) # Finally, overwrite with any convenience commandline flags if ignore: config_builder.set_option('general', 'ignore', ignore) if contrib: config_builder.set_option('general', 'contrib', contrib) if ignore_stdin: config_builder.set_option('general', 'ignore-stdin', ignore_stdin) if silent: config_builder.set_option('general', 'verbosity', 0) elif verbose > 0: config_builder.set_option('general', 'verbosity', verbose) if extra_path: config_builder.set_option('general', 'extra-path', extra_path) if target: config_builder.set_option('general', 'target', target) if debug: config_builder.set_option('general', 'debug', debug) if staged: config_builder.set_option('general', 'staged', staged) config = config_builder.build() return config, config_builder
def build_config(ctx, target, config_path, c, extra_path, ignore, verbose, silent, debug): """ Creates a LintConfig object based on a set of commandline parameters. """ config_builder = LintConfigBuilder() try: # Config precedence: # First, load default config or config from configfile if config_path: config_builder.set_from_config_file(config_path) elif os.path.exists(DEFAULT_CONFIG_FILE): config_builder.set_from_config_file(DEFAULT_CONFIG_FILE) # Then process any commandline configuration flags config_builder.set_config_from_string_list(c) # Finally, overwrite with any convenience commandline flags if ignore: config_builder.set_option('general', 'ignore', ignore) if silent: config_builder.set_option('general', 'verbosity', 0) elif verbose > 0: config_builder.set_option('general', 'verbosity', verbose) if extra_path: config_builder.set_option('general', 'extra-path', extra_path) if target: config_builder.set_option('general', 'target', target) if debug: config_builder.set_option('general', 'debug', debug) config = config_builder.build() return config, config_builder except LintConfigError as e: click.echo(u"Config Error: {0}".format(ustr(e))) ctx.exit(CONFIG_ERROR_CODE) # return CONFIG_ERROR_CODE on config error
def build_config(ctx, target, config_path, c, extra_path, ignore, verbose, silent, debug): """ Creates a LintConfig object based on a set of commandline parameters. """ config_builder = LintConfigBuilder() try: # Config precedence: # First, load default config or config from configfile if config_path: config_builder.set_from_config_file(config_path) elif os.path.exists(DEFAULT_CONFIG_FILE): config_builder.set_from_config_file(DEFAULT_CONFIG_FILE) # Then process any commandline configuration flags config_builder.set_config_from_string_list(c) # Finally, overwrite with any convenience commandline flags if ignore: config_builder.set_option('general', 'ignore', ignore) if silent: config_builder.set_option('general', 'verbosity', 0) elif verbose > 0: config_builder.set_option('general', 'verbosity', verbose) if extra_path: config_builder.set_option('general', 'extra-path', extra_path) if target: config_builder.set_option('general', 'target', target) if debug: config_builder.set_option('general', 'debug', debug) config = config_builder.build() if debug: click.echo(str(config), nl=True) return config, config_builder except LintConfigError as e: click.echo("Config Error: {0}".format(str(e))) ctx.exit(CONFIG_ERROR_CODE) # return CONFIG_ERROR_CODE on config error