# -*- 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 . 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]