From f65553c4f757dc9037deea552e0475b480eda772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 6 Jun 2019 11:01:30 +0200 Subject: [PATCH] config: Validate config options with list of enums Allow rules to declare a list of valid values for an option. For example, a rule like: CONF = {'allowed-values': list} ... allowed any value to be passed in the list (including bad ones). It is now possible to declare: CONF = {'allowed-values': ['value1', 'value2', 'value3']} ... so that the list passed to the options must contain only values in `['value1', 'value2', 'value3']`. --- tests/test_config.py | 19 +++++++++++++++++++ yamllint/config.py | 14 ++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/tests/test_config.py b/tests/test_config.py index f5d9402..d676382 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -174,6 +174,25 @@ class SimpleConfigTestCase(unittest.TestCase): self.assertRaises(config.YamlLintConfigError, config.validate_rule_conf, Rule, {'choice': 'abc'}) + Rule.CONF = {'multiple': ['item1', 'item2', 'item3']} + Rule.DEFAULT = {'multiple': ['item1']} + config.validate_rule_conf(Rule, {'multiple': []}) + config.validate_rule_conf(Rule, {'multiple': ['item2']}) + config.validate_rule_conf(Rule, {'multiple': ['item2', 'item3']}) + config.validate_rule_conf(Rule, {}) + self.assertRaises(config.YamlLintConfigError, + config.validate_rule_conf, Rule, + {'multiple': 'item1'}) + self.assertRaises(config.YamlLintConfigError, + config.validate_rule_conf, Rule, + {'multiple': ['']}) + self.assertRaises(config.YamlLintConfigError, + config.validate_rule_conf, Rule, + {'multiple': ['item1', 4]}) + self.assertRaises(config.YamlLintConfigError, + config.validate_rule_conf, Rule, + {'multiple': ['item4']}) + class ExtendedConfigTestCase(unittest.TestCase): def test_extend_on_object(self): diff --git a/yamllint/config.py b/yamllint/config.py index b4a7c1d..2cafe8a 100644 --- a/yamllint/config.py +++ b/yamllint/config.py @@ -134,12 +134,26 @@ def validate_rule_conf(rule, conf): raise YamlLintConfigError( 'invalid config: unknown option "%s" for rule "%s"' % (optkey, rule.ID)) + # Example: CONF = {option: (bool, 'mixed')} + # → {option: true} → {option: mixed} if isinstance(options[optkey], tuple): if (conf[optkey] not in options[optkey] and type(conf[optkey]) not in options[optkey]): raise YamlLintConfigError( 'invalid config: option "%s" of "%s" should be in %s' % (optkey, rule.ID, options[optkey])) + # Example: CONF = {option: ['flag1', 'flag2']} + # → {option: [flag1]} → {option: [flag1, flag2]} + elif isinstance(options[optkey], list): + if (type(conf[optkey]) is not list or + any(flag not in options[optkey] + for flag in conf[optkey])): + raise YamlLintConfigError( + ('invalid config: option "%s" of "%s" should only ' + 'contain values in %s') + % (optkey, rule.ID, str(options[optkey]))) + # Example: CONF = {option: int} + # → {option: 42} else: if not isinstance(conf[optkey], options[optkey]): raise YamlLintConfigError(