You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.9 KiB
Python
114 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright (C) 2016 Adrien Vergé
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import os.path
|
|
|
|
import yaml
|
|
|
|
import yamllint.rules
|
|
from yamllint.errors import YamlLintConfigError
|
|
|
|
|
|
def get_extended_conf(name):
|
|
# Is it a standard conf shipped with yamllint...
|
|
if '/' not in name:
|
|
std_conf = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
|
'conf', name + '.yml')
|
|
|
|
if os.path.isfile(std_conf):
|
|
return std_conf
|
|
|
|
# or a custom conf on filesystem?
|
|
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]
|