Add the ability to run custom rules included in a project

pull/19/head
Peter Ericson 9 years ago
parent 9b72a2d29a
commit 0b985a063a

@ -15,6 +15,7 @@ If ``-c`` is not provided, yamllint will look for a configuration file in the
following locations (by order of preference):
- ``.yamllint`` in the current working directory
- ``.yamllint/config`` in the current working directory
- ``$XDG_CONFIG_HOME/yamllint/config``
- ``~/.config/yamllint/config``

@ -0,0 +1,62 @@
Custom Rules
============
There are times when you might like to add custom rules to your
project. This could be because the rules you'd like to enforce are
not general enough to consider including in upstream yamllint.
yamllint will look for custom rules in ``.yamllint/rules``. To enable
a custom rule you need to explicitly reference the rule in your
config.
Example
~~~~~~~
In this example there is a custom rule called ``truthy`` that will
complain if ambiguous truthy values are not quoted.
This is the directory structure:
.. code:: plain
.
|-- .yamllint
| |-- config
| `-- rules
| |-- __init__.py
| `-- truthy.py
`-- example.yml
2 directories, 4 files
This is an example yaml file with ambiguous truthy values:
.. code:: yaml
---
a: y
b: yes
c: on
d: True
This is an example config file:
.. code:: yaml
---
extends: default
rules:
truthy: enable
Lint problems from the custom rule are now included in the yamllint
output:
.. code:: plain
$ yamllint example.yml
example.yml
2:3 error ambiguous truthy value is not quoted (truthy)
3:3 error ambiguous truthy value is not quoted (truthy)
4:3 error ambiguous truthy value is not quoted (truthy)
5:3 error ambiguous truthy value is not quoted (truthy)

@ -26,3 +26,4 @@ Table of contents
disable_with_comments
development
text_editors
custom_rules

@ -0,0 +1,73 @@
# -*- 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
import shutil
import tempfile
from tests.common import RuleTestCase
from yamllint.config import YamlLintConfigError
class CustomTestCase(RuleTestCase):
rule_id = 'custom'
@classmethod
def setUpClass(self):
self.tmpd = tempfile.mkdtemp()
rules = os.path.join(self.tmpd, '.yamllint', 'rules')
os.makedirs(rules)
with open(os.path.join(rules, '__init__.py'), 'w'):
pass
with open(os.path.join(rules, 'custom.py'), 'w') as f:
f.write("""ID = 'custom'
TYPE = 'token'
def check(*args, **kwargs):
if 0:
yield
""")
self.orig_cwd = os.getcwd()
os.chdir(self.tmpd)
def test_disabled(self):
conf = 'custom: disable\n'
self.check('---\n', conf)
def test_enabled(self):
conf = 'custom: enable\n'
self.check('---\n', conf)
def test_config_present(self):
conf = 'custom: enable\n'
self.check('---\n', conf)
def test_config_missing(self):
conf = ''
with self.assertRaises(YamlLintConfigError):
self.check('---\n', conf)
@classmethod
def tearDownClass(self):
os.chdir(self.orig_cwd)
shutil.rmtree(self.tmpd)

@ -113,6 +113,8 @@ def run(argv=None):
conf = YamlLintConfig(file=args.config_file)
elif os.path.isfile('.yamllint'):
conf = YamlLintConfig(file='.yamllint')
elif os.path.isfile('.yamllint/config'):
conf = YamlLintConfig(file='.yamllint/config')
elif os.path.isfile(user_global_config):
conf = YamlLintConfig(file=user_global_config)
else:

@ -14,6 +14,10 @@
# 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 importlib
import os
import sys
from yamllint.rules import (
braces,
brackets,
@ -54,6 +58,15 @@ _RULES = {
def get(id):
if id not in _RULES:
try:
if os.path.isdir('.yamllint'):
sys.path.append('.yamllint')
module = importlib.import_module('rules.' + id)
_RULES[module.ID] = module
except ImportError as exc:
pass
if id not in _RULES:
raise ValueError('no such rule: "%s"' % id)

Loading…
Cancel
Save