From 43c50379e0a991578dbb05332bdc0513a141cb8a Mon Sep 17 00:00:00 2001 From: xatier Date: Mon, 27 May 2019 01:37:40 -0700 Subject: [PATCH 1/8] Sort import orders --- setup.py | 2 +- yamllint/cli.py | 6 +++--- yamllint/rules/colons.py | 2 +- yamllint/rules/indentation.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 1b93008..ffa2ee2 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from setuptools import setup, find_packages +from setuptools import find_packages, setup from yamllint import (__author__, __license__, APP_NAME, APP_VERSION, APP_DESCRIPTION) diff --git a/yamllint/cli.py b/yamllint/cli.py index c5916e5..9975b4e 100644 --- a/yamllint/cli.py +++ b/yamllint/cli.py @@ -16,15 +16,15 @@ from __future__ import print_function +import argparse import os -import sys import platform -import argparse +import sys from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION +from yamllint import linter from yamllint.config import YamlLintConfig, YamlLintConfigError from yamllint.linter import PROBLEM_LEVELS -from yamllint import linter def find_files_recursively(items): diff --git a/yamllint/rules/colons.py b/yamllint/rules/colons.py index fd46bef..1a63cad 100644 --- a/yamllint/rules/colons.py +++ b/yamllint/rules/colons.py @@ -72,7 +72,7 @@ Use this rule to control the number of spaces before and after colons (``:``). import yaml -from yamllint.rules.common import spaces_after, spaces_before, is_explicit_key +from yamllint.rules.common import is_explicit_key, spaces_after, spaces_before ID = 'colons' diff --git a/yamllint/rules/indentation.py b/yamllint/rules/indentation.py index 8bb7175..d83eb65 100644 --- a/yamllint/rules/indentation.py +++ b/yamllint/rules/indentation.py @@ -193,7 +193,7 @@ Use this rule to control the indentation. import yaml from yamllint.linter import LintProblem -from yamllint.rules.common import is_explicit_key, get_real_end_line +from yamllint.rules.common import get_real_end_line, is_explicit_key ID = 'indentation' From 4ef7e05f3a8e3e91b0c0691c6c02077e2408b681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ondrej=20Va=C5=A1ko?= Date: Thu, 6 Jun 2019 09:59:00 +0200 Subject: [PATCH 2/8] truthy: Add allowed-values configuration option Allows using key `allowed-values` for `truthy` section in configuration file (#150). This allows to use configuration `truthy: allowed-values: ["yes", "no", "..."]`, to set custom allowed truthy values. This is especially useful for people using ansible, where values like `yes` or `no` are valid and officially supported, but yamllint reports them as illegal. Implemented by difference of set of TRUTHY constants and configured allowed values. Signed-off-by: Ondrej Vasko --- tests/rules/test_truthy.py | 62 ++++++++++++++++++++++++++++++++++++++ yamllint/rules/truthy.py | 40 +++++++++++++++++++++--- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/tests/rules/test_truthy.py b/tests/rules/test_truthy.py index b0402ed..796f3c7 100644 --- a/tests/rules/test_truthy.py +++ b/tests/rules/test_truthy.py @@ -49,6 +49,68 @@ class TruthyTestCase(RuleTestCase): problem3=(7, 3), problem4=(7, 7), problem5=(8, 3), problem6=(8, 7)) + def test_different_allowed_values(self): + conf = ('truthy:\n' + ' allowed-values: ["yes", "no"]\n') + self.check('---\n' + 'key1: foo\n' + 'key2: yes\n' + 'key3: bar\n' + 'key4: no\n', conf) + self.check('---\n' + 'key1: true\n' + 'key2: Yes\n' + 'key3: false\n' + 'key4: no\n' + 'key5: yes\n', + conf, + problem1=(2, 7), problem2=(3, 7), + problem3=(4, 7)) + + def test_combined_allowed_values(self): + conf = ('truthy:\n' + ' allowed-values: ["yes", "no", "true", "false"]\n') + self.check('---\n' + 'key1: foo\n' + 'key2: yes\n' + 'key3: bar\n' + 'key4: no\n', conf) + self.check('---\n' + 'key1: true\n' + 'key2: Yes\n' + 'key3: false\n' + 'key4: no\n' + 'key5: yes\n', + conf, problem1=(3, 7)) + + def test_no_allowed_values(self): + conf = ('truthy:\n' + ' allowed-values: []\n') + self.check('---\n' + 'key1: foo\n' + 'key2: bar\n', conf) + self.check('---\n' + 'key1: true\n' + 'key2: yes\n' + 'key3: false\n' + 'key4: no\n', conf, + problem1=(2, 7), problem2=(3, 7), + problem3=(4, 7), problem4=(5, 7)) + + def test_empty_string_allowed_values(self): + conf = ('truthy:\n' + ' allowed-values: ["", ""]\n') + self.check('---\n' + 'key1: foo\n' + 'key2: bar\n', conf) + self.check('---\n' + 'key1: true\n' + 'key2: yes\n' + 'key3: false\n' + 'key4: no\n', conf, + problem1=(2, 7), problem2=(3, 7), + problem3=(4, 7), problem4=(5, 7)) + def test_explicit_types(self): conf = 'truthy: enable\n' self.check('---\n' diff --git a/yamllint/rules/truthy.py b/yamllint/rules/truthy.py index b738dc2..89fbfff 100644 --- a/yamllint/rules/truthy.py +++ b/yamllint/rules/truthy.py @@ -22,6 +22,14 @@ This can be useful to prevent surprises from YAML parsers transforming ``[yes, FALSE, Off]`` into ``[true, false, false]`` or ``{y: 1, yes: 2, on: 3, true: 4, True: 5}`` into ``{y: 1, true: 5}``. +Default list of prohibited truthy values is ``YES, Yes, yes, NO, No, no, +TRUE, True, FALSE, False, ON, On, on, OFF, Off, off``. + +.. rubric:: Options + +* ``allowed-values`` defines list of truthy values, which will be ignored + during linting. + .. rubric:: Examples #. With ``truthy: {}`` @@ -63,6 +71,26 @@ This can be useful to prevent surprises from YAML parsers transforming yes: 1 on: 2 True: 3 + +#. With ``truthy: {allowed-values: ["yes", "no"]}`` + + the following code snippet would **PASS**: + :: + + - yes + - no + - "true" + - 'false' + - foo + - bar + + the following code snippet would **FAIL**: + :: + + - true + - false + - on + - off """ import yaml @@ -71,11 +99,13 @@ from yamllint.linter import LintProblem ID = 'truthy' TYPE = 'token' +CONF = {'allowed-values': list} +DEFAULT = {'allowed-values': ['true', 'false']} TRUTHY = ['YES', 'Yes', 'yes', 'NO', 'No', 'no', - 'TRUE', 'True', # 'true' is a boolean - 'FALSE', 'False', # 'false' is a boolean + 'TRUE', 'True', 'true', + 'FALSE', 'False', 'false', 'ON', 'On', 'on', 'OFF', 'Off', 'off'] @@ -85,7 +115,9 @@ def check(conf, token, prev, next, nextnext, context): return if isinstance(token, yaml.tokens.ScalarToken): - if token.value in TRUTHY and token.style is None: + if (token.value in (set(TRUTHY) - set(conf['allowed-values'])) and + token.style is None): yield LintProblem(token.start_mark.line + 1, token.start_mark.column + 1, - "truthy value should be true or false") + "truthy value should be one of [" + + ", ".join(sorted(conf['allowed-values'])) + "]") From 0fef4c14e78b53af8475339a742c5f68bb973f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 6 Jun 2019 10:10:34 +0200 Subject: [PATCH 3/8] truthy: Try to make docs on allowed-values more explicit Edit documentation for the `truthy` rule, in order to: - add quotes to examples (`'yes'` instead of `yes`) to avoid misconfigurations, - group truthy values in the `allowed-values` option paragraph, for easier reading. --- yamllint/rules/truthy.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/yamllint/rules/truthy.py b/yamllint/rules/truthy.py index 89fbfff..1648b51 100644 --- a/yamllint/rules/truthy.py +++ b/yamllint/rules/truthy.py @@ -15,20 +15,21 @@ # along with this program. If not, see . """ -Use this rule to forbid non-explictly typed truthy values other than ``true`` -and ``false``, for example ``YES``, ``False`` and ``off``. +Use this rule to forbid non-explictly typed truthy values other than allowed +ones (by default: ``true`` and ``false``), for example ``YES`` or ``off``. This can be useful to prevent surprises from YAML parsers transforming ``[yes, FALSE, Off]`` into ``[true, false, false]`` or ``{y: 1, yes: 2, on: 3, true: 4, True: 5}`` into ``{y: 1, true: 5}``. -Default list of prohibited truthy values is ``YES, Yes, yes, NO, No, no, -TRUE, True, FALSE, False, ON, On, on, OFF, Off, off``. - .. rubric:: Options -* ``allowed-values`` defines list of truthy values, which will be ignored - during linting. +* ``allowed-values`` defines the list of truthy values which will be ignored + during linting. The default is ``['true', 'false']``, but can be changed to + any list containing: ``'TRUE'``, ``'True'``, ``'true'``, ``'FALSE'``, + ``'False'``, ``'false'``, ``'YES'``, ``'Yes'``, ``'yes'``, ``'NO'``, + ``'No'``, ``'no'``, ``'ON'``, ``'On'``, ``'on'``, ``'OFF'``, ``'Off'``, + ``'off'``. .. rubric:: Examples 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 4/8] 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( From 0ba193331b8e066218c3c5f3417c214904c23e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 6 Jun 2019 11:05:33 +0200 Subject: [PATCH 5/8] truthy: Validate options passed to 'allowed-values' Make sure values passed in allowed values are correct ones. This is possible thanks to previous commit, and should prevent users from writing incorrect configurations. --- tests/rules/test_truthy.py | 14 -------------- yamllint/rules/truthy.py | 10 ++++++---- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/tests/rules/test_truthy.py b/tests/rules/test_truthy.py index 796f3c7..82e4f6c 100644 --- a/tests/rules/test_truthy.py +++ b/tests/rules/test_truthy.py @@ -97,20 +97,6 @@ class TruthyTestCase(RuleTestCase): problem1=(2, 7), problem2=(3, 7), problem3=(4, 7), problem4=(5, 7)) - def test_empty_string_allowed_values(self): - conf = ('truthy:\n' - ' allowed-values: ["", ""]\n') - self.check('---\n' - 'key1: foo\n' - 'key2: bar\n', conf) - self.check('---\n' - 'key1: true\n' - 'key2: yes\n' - 'key3: false\n' - 'key4: no\n', conf, - problem1=(2, 7), problem2=(3, 7), - problem3=(4, 7), problem4=(5, 7)) - def test_explicit_types(self): conf = 'truthy: enable\n' self.check('---\n' diff --git a/yamllint/rules/truthy.py b/yamllint/rules/truthy.py index 1648b51..3cf058b 100644 --- a/yamllint/rules/truthy.py +++ b/yamllint/rules/truthy.py @@ -98,10 +98,6 @@ import yaml from yamllint.linter import LintProblem -ID = 'truthy' -TYPE = 'token' -CONF = {'allowed-values': list} -DEFAULT = {'allowed-values': ['true', 'false']} TRUTHY = ['YES', 'Yes', 'yes', 'NO', 'No', 'no', @@ -111,6 +107,12 @@ TRUTHY = ['YES', 'Yes', 'yes', 'OFF', 'Off', 'off'] +ID = 'truthy' +TYPE = 'token' +CONF = {'allowed-values': list(TRUTHY)} +DEFAULT = {'allowed-values': ['true', 'false']} + + def check(conf, token, prev, next, nextnext, context): if prev and isinstance(prev, yaml.tokens.TagToken): return From f6a24552d9048484b22c1b5cd51370f8dba8dfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Fri, 7 Jun 2019 10:04:55 +0200 Subject: [PATCH 6/8] yamllint version 1.16.0 --- CHANGELOG.rst | 8 ++++++++ yamllint/__init__.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index de0e50c..105fccd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Changelog ========= +1.16.0 (2019-06-07) +------------------- + +- Add FreeBSD installation instructions +- Fix the ``line`` rule to correctly handle DOS new lines +- Add the ``allowed-values`` option to the ``truthy`` rule +- Allow configuration options to be a list of enums + 1.15.0 (2019-02-11) ------------------- diff --git a/yamllint/__init__.py b/yamllint/__init__.py index 91c19eb..932054e 100644 --- a/yamllint/__init__.py +++ b/yamllint/__init__.py @@ -22,7 +22,7 @@ indentation, etc.""" APP_NAME = 'yamllint' -APP_VERSION = '1.15.0' +APP_VERSION = '1.16.0' APP_DESCRIPTION = __doc__ __author__ = u'Adrien Vergé' From 930c8eea94614142daac00c24a9a5f51c8c43dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Sun, 7 Jul 2019 18:00:24 +0200 Subject: [PATCH 7/8] docs: Simplify installation instruction in the README --- README.rst | 32 +++++--------------------------- docs/quickstart.rst | 9 ++++++++- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/README.rst b/README.rst index 7f59956..0bebb78 100644 --- a/README.rst +++ b/README.rst @@ -38,38 +38,16 @@ Screenshot Installation ^^^^^^^^^^^^ -On Fedora / CentOS (note: `EPEL `_ is -required on CentOS): - -.. code:: bash - - sudo dnf install yamllint - -On Debian 8+ / Ubuntu 16.04+: - -.. code:: bash - - sudo apt-get install yamllint - -On FreeBSD: - -.. code:: sh - - pkg install py27-yamllint - pkg install py36-yamllint - -On Mac OS 10.11+: - -.. code:: bash - - brew install yamllint - -Alternatively using pip, the Python package manager: +Using pip, the Python package manager: .. code:: bash pip install --user yamllint +yamllint is also packaged for all major operating systems, see installation +examples (``dnf``, ``apt-get``...) `in the documentation +`_. + Usage ^^^^^ diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 427a9f3..8d959d6 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -4,7 +4,8 @@ Quickstart Installing yamllint ------------------- -On Fedora / CentOS: +On Fedora / CentOS (note: `EPEL `_ is +required on CentOS): .. code:: bash @@ -22,6 +23,12 @@ On Mac OS 10.11+: brew install yamllint +On FreeBSD: + +.. code:: sh + + pkg install py36-yamllint + Alternatively using pip, the Python package manager: .. code:: bash From cb5fe2c050f09aa5d29331aa1fec62306055c841 Mon Sep 17 00:00:00 2001 From: Remi Pointel Date: Tue, 9 Jul 2019 09:37:43 +0200 Subject: [PATCH 8/8] add OpenBSD installation instructions. --- docs/quickstart.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 8d959d6..9cf5f17 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -29,6 +29,12 @@ On FreeBSD: pkg install py36-yamllint +On OpenBSD: + +.. code:: sh + + doas pkg_add py3-yamllint + Alternatively using pip, the Python package manager: .. code:: bash