Config: Refactor to use YamlLintConfig objects
This commit is contained in:
@@ -18,7 +18,7 @@ import unittest
|
|||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from yamllint.config import parse_config
|
from yamllint.config import YamlLintConfig
|
||||||
from yamllint.errors import LintProblem
|
from yamllint.errors import LintProblem
|
||||||
from yamllint import lint
|
from yamllint import lint
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class RuleTestCase(unittest.TestCase):
|
|||||||
conf = yaml.safe_load(conf)
|
conf = yaml.safe_load(conf)
|
||||||
conf = {'extends': 'default',
|
conf = {'extends': 'default',
|
||||||
'rules': conf}
|
'rules': conf}
|
||||||
return parse_config(yaml.safe_dump(conf))
|
return YamlLintConfig(yaml.safe_dump(conf))
|
||||||
|
|
||||||
def check(self, source, conf, **kwargs):
|
def check(self, source, conf, **kwargs):
|
||||||
expected_problems = []
|
expected_problems = []
|
||||||
|
|||||||
@@ -14,56 +14,164 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import os
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from yamllint import config
|
from yamllint import config
|
||||||
|
|
||||||
|
|
||||||
class ConfigTestCase(unittest.TestCase):
|
class SimpleConfigTestCase(unittest.TestCase):
|
||||||
def setUp(self):
|
def test_parse_config(self):
|
||||||
self.base = config.parse_config_from_file(os.path.join(
|
new = config.YamlLintConfig('rules:\n'
|
||||||
os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
|
' colons:\n'
|
||||||
'yamllint', 'conf', 'default.yml'))
|
' max-spaces-before: 0\n'
|
||||||
|
' max-spaces-after: 1\n')
|
||||||
|
|
||||||
|
self.assertEqual(list(new.rules.keys()), ['colons'])
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
|
||||||
|
|
||||||
|
self.assertEqual(len(new.enabled_rules()), 1)
|
||||||
|
|
||||||
|
def test_unknown_rule(self):
|
||||||
|
with self.assertRaisesRegexp(
|
||||||
|
config.YamlLintConfigError,
|
||||||
|
'invalid config: no such rule: "this-one-does-not-exist"'):
|
||||||
|
config.YamlLintConfig('rules:\n'
|
||||||
|
' this-one-does-not-exist: {}\n')
|
||||||
|
|
||||||
|
def test_missing_option(self):
|
||||||
|
with self.assertRaisesRegexp(
|
||||||
|
config.YamlLintConfigError,
|
||||||
|
'invalid config: missing option "max-spaces-before" '
|
||||||
|
'for rule "colons"'):
|
||||||
|
config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-after: 1\n')
|
||||||
|
|
||||||
|
def test_unknown_option(self):
|
||||||
|
with self.assertRaisesRegexp(
|
||||||
|
config.YamlLintConfigError,
|
||||||
|
'invalid config: unknown option "abcdef" for rule "colons"'):
|
||||||
|
config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-before: 0\n'
|
||||||
|
' max-spaces-after: 1\n'
|
||||||
|
' abcdef: yes\n')
|
||||||
|
|
||||||
|
|
||||||
|
class ExtendedConfigTestCase(unittest.TestCase):
|
||||||
|
def test_extend_add_rule(self):
|
||||||
|
old = config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-before: 0\n'
|
||||||
|
' max-spaces-after: 1\n')
|
||||||
|
new = config.YamlLintConfig('rules:\n'
|
||||||
|
' hyphens:\n'
|
||||||
|
' max-spaces-after: 2\n')
|
||||||
|
new.extend(old)
|
||||||
|
|
||||||
|
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
|
||||||
|
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
|
||||||
|
|
||||||
|
self.assertEqual(len(new.enabled_rules()), 2)
|
||||||
|
|
||||||
|
def test_extend_remove_rule(self):
|
||||||
|
old = config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-before: 0\n'
|
||||||
|
' max-spaces-after: 1\n'
|
||||||
|
' hyphens:\n'
|
||||||
|
' max-spaces-after: 2\n')
|
||||||
|
new = config.YamlLintConfig('rules:\n'
|
||||||
|
' colons: disable\n')
|
||||||
|
new.extend(old)
|
||||||
|
|
||||||
|
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
|
||||||
|
self.assertEqual(new.rules['colons'], False)
|
||||||
|
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
|
||||||
|
|
||||||
|
self.assertEqual(len(new.enabled_rules()), 1)
|
||||||
|
|
||||||
|
def test_extend_edit_rule(self):
|
||||||
|
old = config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-before: 0\n'
|
||||||
|
' max-spaces-after: 1\n'
|
||||||
|
' hyphens:\n'
|
||||||
|
' max-spaces-after: 2\n')
|
||||||
|
new = config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-before: 3\n'
|
||||||
|
' max-spaces-after: 4\n')
|
||||||
|
new.extend(old)
|
||||||
|
|
||||||
|
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-before'], 3)
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-after'], 4)
|
||||||
|
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
|
||||||
|
|
||||||
|
self.assertEqual(len(new.enabled_rules()), 2)
|
||||||
|
|
||||||
|
def test_extend_reenable_rule(self):
|
||||||
|
old = config.YamlLintConfig('rules:\n'
|
||||||
|
' colons:\n'
|
||||||
|
' max-spaces-before: 0\n'
|
||||||
|
' max-spaces-after: 1\n'
|
||||||
|
' hyphens: disable\n')
|
||||||
|
new = config.YamlLintConfig('rules:\n'
|
||||||
|
' hyphens:\n'
|
||||||
|
' max-spaces-after: 2\n')
|
||||||
|
new.extend(old)
|
||||||
|
|
||||||
|
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
|
||||||
|
self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
|
||||||
|
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
|
||||||
|
|
||||||
|
self.assertEqual(len(new.enabled_rules()), 2)
|
||||||
|
|
||||||
|
|
||||||
|
class ExtendedLibraryConfigTestCase(unittest.TestCase):
|
||||||
def test_extend_config_disable_rule(self):
|
def test_extend_config_disable_rule(self):
|
||||||
new = config.parse_config('extends: default\n'
|
old = config.YamlLintConfig('extends: default')
|
||||||
'rules:\n'
|
new = config.YamlLintConfig('extends: default\n'
|
||||||
' trailing-spaces: disable\n')
|
'rules:\n'
|
||||||
|
' trailing-spaces: disable\n')
|
||||||
|
|
||||||
base = self.base.copy()
|
old.rules['trailing-spaces'] = False
|
||||||
del base['trailing-spaces']
|
|
||||||
|
|
||||||
self.assertEqual(sorted(new.keys()), sorted(base.keys()))
|
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
|
||||||
for rule in new:
|
for rule in new.rules:
|
||||||
self.assertEqual(new[rule], base[rule])
|
self.assertEqual(new.rules[rule], old.rules[rule])
|
||||||
|
|
||||||
def test_extend_config_override_whole_rule(self):
|
def test_extend_config_override_whole_rule(self):
|
||||||
new = config.parse_config('extends: default\n'
|
old = config.YamlLintConfig('extends: default')
|
||||||
'rules:\n'
|
new = config.YamlLintConfig('extends: default\n'
|
||||||
' empty-lines:\n'
|
'rules:\n'
|
||||||
' max: 42\n'
|
' empty-lines:\n'
|
||||||
' max-start: 43\n'
|
' max: 42\n'
|
||||||
' max-end: 44\n')
|
' max-start: 43\n'
|
||||||
|
' max-end: 44\n')
|
||||||
|
|
||||||
base = self.base.copy()
|
old.rules['empty-lines']['max'] = 42
|
||||||
base['empty-lines']['max'] = 42
|
old.rules['empty-lines']['max-start'] = 43
|
||||||
base['empty-lines']['max-start'] = 43
|
old.rules['empty-lines']['max-end'] = 44
|
||||||
base['empty-lines']['max-end'] = 44
|
|
||||||
|
|
||||||
self.assertEqual(sorted(new.keys()), sorted(base.keys()))
|
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
|
||||||
for rule in new:
|
for rule in new.rules:
|
||||||
self.assertEqual(new[rule], base[rule])
|
self.assertEqual(new.rules[rule], old.rules[rule])
|
||||||
|
|
||||||
def test_extend_config_override_rule_partly(self):
|
def test_extend_config_override_rule_partly(self):
|
||||||
new = config.parse_config('extends: default\n'
|
old = config.YamlLintConfig('extends: default')
|
||||||
'rules:\n'
|
new = config.YamlLintConfig('extends: default\n'
|
||||||
' empty-lines:\n'
|
'rules:\n'
|
||||||
' max-start: 42\n')
|
' empty-lines:\n'
|
||||||
|
' max-start: 42\n')
|
||||||
|
|
||||||
base = self.base.copy()
|
old.rules['empty-lines']['max-start'] = 42
|
||||||
base['empty-lines']['max-start'] = 42
|
|
||||||
|
|
||||||
self.assertEqual(sorted(new.keys()), sorted(base.keys()))
|
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
|
||||||
for rule in new:
|
for rule in new.rules:
|
||||||
self.assertEqual(new[rule], base[rule])
|
self.assertEqual(new.rules[rule], old.rules[rule])
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from yamllint import config
|
|
||||||
from yamllint.errors import LintProblem
|
from yamllint.errors import LintProblem
|
||||||
from yamllint import parser
|
from yamllint import parser
|
||||||
|
|
||||||
@@ -32,7 +31,7 @@ __version__ = APP_VERSION
|
|||||||
|
|
||||||
|
|
||||||
def get_costemic_problems(buffer, conf):
|
def get_costemic_problems(buffer, conf):
|
||||||
rules = config.get_enabled_rules(conf)
|
rules = conf.enabled_rules()
|
||||||
|
|
||||||
# Split token rules from line rules
|
# Split token rules from line rules
|
||||||
token_rules = [r for r in rules if r.TYPE == 'token']
|
token_rules = [r for r in rules if r.TYPE == 'token']
|
||||||
@@ -45,7 +44,7 @@ def get_costemic_problems(buffer, conf):
|
|||||||
for elem in parser.token_or_line_generator(buffer):
|
for elem in parser.token_or_line_generator(buffer):
|
||||||
if isinstance(elem, parser.Token):
|
if isinstance(elem, parser.Token):
|
||||||
for rule in token_rules:
|
for rule in token_rules:
|
||||||
rule_conf = conf[rule.ID]
|
rule_conf = conf.rules[rule.ID]
|
||||||
for problem in rule.check(rule_conf,
|
for problem in rule.check(rule_conf,
|
||||||
elem.curr, elem.prev, elem.next,
|
elem.curr, elem.prev, elem.next,
|
||||||
context[rule.ID]):
|
context[rule.ID]):
|
||||||
@@ -54,7 +53,7 @@ def get_costemic_problems(buffer, conf):
|
|||||||
yield problem
|
yield problem
|
||||||
elif isinstance(elem, parser.Line):
|
elif isinstance(elem, parser.Line):
|
||||||
for rule in line_rules:
|
for rule in line_rules:
|
||||||
rule_conf = conf[rule.ID]
|
rule_conf = conf.rules[rule.ID]
|
||||||
for problem in rule.check(rule_conf, elem):
|
for problem in rule.check(rule_conf, elem):
|
||||||
problem.rule = rule.ID
|
problem.rule = rule.ID
|
||||||
problem.level = rule_conf['level']
|
problem.level = rule_conf['level']
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import sys
|
|||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION
|
from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION
|
||||||
from yamllint import config
|
from yamllint.config import YamlLintConfig, YamlLintConfigError
|
||||||
from yamllint.errors import YamlLintConfigError
|
|
||||||
from yamllint import lint
|
from yamllint import lint
|
||||||
|
|
||||||
|
|
||||||
@@ -82,11 +81,11 @@ def run(argv):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if args.config_file is not None:
|
if args.config_file is not None:
|
||||||
conf = config.parse_config_from_file(args.config_file)
|
conf = YamlLintConfig(file=args.config_file)
|
||||||
elif os.path.isfile('.yamllint'):
|
elif os.path.isfile('.yamllint'):
|
||||||
conf = config.parse_config_from_file('.yamllint')
|
conf = YamlLintConfig(file='.yamllint')
|
||||||
else:
|
else:
|
||||||
conf = config.parse_config('extends: default')
|
conf = YamlLintConfig('extends: default')
|
||||||
except YamlLintConfigError as e:
|
except YamlLintConfigError as e:
|
||||||
print(e, file=sys.stderr)
|
print(e, file=sys.stderr)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|||||||
@@ -19,10 +19,109 @@ import os.path
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
import yamllint.rules
|
import yamllint.rules
|
||||||
from yamllint.errors import YamlLintConfigError
|
|
||||||
|
|
||||||
|
|
||||||
def get_extended_conf(name):
|
class YamlLintConfigError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class YamlLintConfig(object):
|
||||||
|
def __init__(self, content=None, file=None):
|
||||||
|
assert (content is None) ^ (file is None)
|
||||||
|
|
||||||
|
if file is not None:
|
||||||
|
with open(file) as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
self.parse(content)
|
||||||
|
self.validate()
|
||||||
|
|
||||||
|
def enabled_rules(self):
|
||||||
|
return [yamllint.rules.get(id) for id, val in self.rules.items()
|
||||||
|
if val is not False]
|
||||||
|
|
||||||
|
def extend(self, base_config):
|
||||||
|
assert isinstance(base_config, YamlLintConfig)
|
||||||
|
|
||||||
|
for rule in self.rules:
|
||||||
|
if (type(self.rules[rule]) == dict and
|
||||||
|
rule in base_config.rules and
|
||||||
|
base_config.rules[rule] is not False):
|
||||||
|
base_config.rules[rule].update(self.rules[rule])
|
||||||
|
else:
|
||||||
|
base_config.rules[rule] = self.rules[rule]
|
||||||
|
|
||||||
|
self.rules = base_config.rules
|
||||||
|
|
||||||
|
def parse(self, raw_content):
|
||||||
|
try:
|
||||||
|
conf = yaml.safe_load(raw_content)
|
||||||
|
except Exception as e:
|
||||||
|
raise YamlLintConfigError('invalid config: %s' % e)
|
||||||
|
|
||||||
|
self.rules = conf.get('rules', {})
|
||||||
|
|
||||||
|
# Does this conf override another conf that we need to load?
|
||||||
|
if 'extends' in conf:
|
||||||
|
path = get_extended_config_file(conf['extends'])
|
||||||
|
base = YamlLintConfig(file=path)
|
||||||
|
try:
|
||||||
|
self.extend(base)
|
||||||
|
except Exception as e:
|
||||||
|
raise YamlLintConfigError('invalid config: %s' % e)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
for id in self.rules:
|
||||||
|
try:
|
||||||
|
rule = yamllint.rules.get(id)
|
||||||
|
except Exception as e:
|
||||||
|
raise YamlLintConfigError('invalid config: %s' % e)
|
||||||
|
|
||||||
|
self.rules[id] = validate_rule_conf(rule, self.rules[id])
|
||||||
|
|
||||||
|
|
||||||
|
def validate_rule_conf(rule, conf):
|
||||||
|
if conf is False or conf == 'disable':
|
||||||
|
return False
|
||||||
|
|
||||||
|
if type(conf) == dict:
|
||||||
|
if 'level' not in conf:
|
||||||
|
conf['level'] = 'error'
|
||||||
|
elif conf['level'] not in ('error', 'warning'):
|
||||||
|
raise YamlLintConfigError(
|
||||||
|
'invalid config: level should be "error" or "warning"')
|
||||||
|
|
||||||
|
options = getattr(rule, 'CONF', {})
|
||||||
|
for optkey in conf:
|
||||||
|
if optkey == 'level':
|
||||||
|
continue
|
||||||
|
if optkey not in options:
|
||||||
|
raise YamlLintConfigError(
|
||||||
|
'invalid config: unknown option "%s" for rule "%s"' %
|
||||||
|
(optkey, rule.ID))
|
||||||
|
if type(options[optkey]) == tuple:
|
||||||
|
if conf[optkey] not in options[optkey]:
|
||||||
|
raise YamlLintConfigError(
|
||||||
|
'invalid config: option "%s" of "%s" should be in %s'
|
||||||
|
% (optkey, rule.ID, options[optkey]))
|
||||||
|
else:
|
||||||
|
if type(conf[optkey]) != options[optkey]:
|
||||||
|
raise YamlLintConfigError(
|
||||||
|
'invalid config: option "%s" of "%s" should be %s'
|
||||||
|
% (optkey, rule.ID, options[optkey].__name__))
|
||||||
|
for optkey in options:
|
||||||
|
if optkey not in conf:
|
||||||
|
raise YamlLintConfigError(
|
||||||
|
'invalid config: missing option "%s" for rule "%s"' %
|
||||||
|
(optkey, rule.ID))
|
||||||
|
else:
|
||||||
|
raise YamlLintConfigError(('invalid config: rule "%s": should be '
|
||||||
|
'either "disable" or a dict') % rule.ID)
|
||||||
|
|
||||||
|
return conf
|
||||||
|
|
||||||
|
|
||||||
|
def get_extended_config_file(name):
|
||||||
# Is it a standard conf shipped with yamllint...
|
# Is it a standard conf shipped with yamllint...
|
||||||
if '/' not in name:
|
if '/' not in name:
|
||||||
std_conf = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
std_conf = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
||||||
@@ -33,81 +132,3 @@ def get_extended_conf(name):
|
|||||||
|
|
||||||
# or a custom conf on filesystem?
|
# or a custom conf on filesystem?
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
def extend_config(content):
|
|
||||||
try:
|
|
||||||
conf = yaml.safe_load(content)
|
|
||||||
|
|
||||||
if 'rules' not in conf:
|
|
||||||
conf['rules'] = {}
|
|
||||||
|
|
||||||
# Does this conf override another conf that we need to load?
|
|
||||||
if 'extends' in conf:
|
|
||||||
base = parse_config_from_file(get_extended_conf(conf['extends']))
|
|
||||||
|
|
||||||
for rule in conf['rules']:
|
|
||||||
if type(conf['rules'][rule]) == dict and rule in base:
|
|
||||||
base[rule].update(conf['rules'][rule])
|
|
||||||
else:
|
|
||||||
base[rule] = conf['rules'][rule]
|
|
||||||
conf['rules'] = base
|
|
||||||
|
|
||||||
return conf
|
|
||||||
except Exception as e:
|
|
||||||
raise YamlLintConfigError('invalid config: %s' % e)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_config(content):
|
|
||||||
conf = extend_config(content)
|
|
||||||
rules = {}
|
|
||||||
|
|
||||||
for id in conf['rules']:
|
|
||||||
try:
|
|
||||||
rule = yamllint.rules.get(id)
|
|
||||||
except Exception as e:
|
|
||||||
raise YamlLintConfigError('invalid config: %s' % e)
|
|
||||||
|
|
||||||
if conf['rules'][id] == 'disable':
|
|
||||||
continue
|
|
||||||
|
|
||||||
rules[id] = {'level': 'error'}
|
|
||||||
if type(conf['rules'][id]) == dict:
|
|
||||||
if 'level' in conf['rules'][id]:
|
|
||||||
if conf['rules'][id]['level'] not in ('error', 'warning'):
|
|
||||||
raise YamlLintConfigError(
|
|
||||||
'invalid config: level should be "error" or "warning"')
|
|
||||||
rules[id]['level'] = conf['rules'][id]['level']
|
|
||||||
|
|
||||||
options = getattr(rule, 'CONF', {})
|
|
||||||
for optkey in conf['rules'][id]:
|
|
||||||
if optkey == 'level':
|
|
||||||
continue
|
|
||||||
if optkey not in options:
|
|
||||||
raise YamlLintConfigError(
|
|
||||||
'invalid config: unknown option "%s" for rule "%s"' %
|
|
||||||
(optkey, id))
|
|
||||||
if type(options[optkey]) == tuple:
|
|
||||||
if conf['rules'][id][optkey] not in options[optkey]:
|
|
||||||
raise YamlLintConfigError(
|
|
||||||
('invalid config: option "%s" of "%s" should be '
|
|
||||||
'in %s') % (optkey, id, options[optkey]))
|
|
||||||
else:
|
|
||||||
if type(conf['rules'][id][optkey]) != options[optkey]:
|
|
||||||
raise YamlLintConfigError(
|
|
||||||
('invalid config: option "%s" of "%s" should be '
|
|
||||||
'%s' % (optkey, id, options[optkey].__name__)))
|
|
||||||
rules[id][optkey] = conf['rules'][id][optkey]
|
|
||||||
else:
|
|
||||||
raise YamlLintConfigError(('invalid config: rule "%s": should be '
|
|
||||||
'either "disable" or a dict') % id)
|
|
||||||
return rules
|
|
||||||
|
|
||||||
|
|
||||||
def parse_config_from_file(path):
|
|
||||||
with open(path) as f:
|
|
||||||
return parse_config(f.read())
|
|
||||||
|
|
||||||
|
|
||||||
def get_enabled_rules(conf):
|
|
||||||
return [yamllint.rules.get(r) for r in conf.keys() if conf[r] is not False]
|
|
||||||
|
|||||||
Reference in New Issue
Block a user