From ff9ebde6080b2e1af68fca29e5edbf694b4a65f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Wed, 9 May 2018 20:17:15 +0200 Subject: [PATCH 01/15] docs: Remove old Debian / Ubuntu installation instructions --- docs/quickstart.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 3365877..4f90008 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -16,13 +16,6 @@ On Debian 8+ / Ubuntu 16.04+: sudo apt-get install yamllint -On older Debian / Ubuntu versions: - -.. code:: bash - - sudo add-apt-repository -y ppa:adrienverge/ppa && sudo apt-get update - sudo apt-get install yamllint - Alternatively using pip, the Python package manager: .. code:: bash From 51c30505b5a2221a244f2aec4a96321471c9688f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Wed, 9 May 2018 20:17:23 +0200 Subject: [PATCH 02/15] docs: Add Mac OS installation instructions See https://github.com/adrienverge/yamllint/issues/91 and https://github.com/Homebrew/homebrew-core/blob/af2bbe9/Formula/yamllint.rb --- README.rst | 6 ++++++ docs/quickstart.rst | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/README.rst b/README.rst index 1f5dac1..32360d1 100644 --- a/README.rst +++ b/README.rst @@ -50,6 +50,12 @@ On Debian 8+ / Ubuntu 16.04+: sudo apt-get install yamllint +On Mac OS 10.11+: + +.. code:: bash + + brew install yamllint + Alternatively using pip, the Python package manager: .. code:: bash diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 4f90008..68cf3d0 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -16,6 +16,12 @@ On Debian 8+ / Ubuntu 16.04+: sudo apt-get install yamllint +On Mac OS 10.11+: + +.. code:: bash + + brew install yamllint + Alternatively using pip, the Python package manager: .. code:: bash From 203cfc20f033f38b6d0ee94bddf2df250c9670c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Wed, 9 May 2018 20:20:18 +0200 Subject: [PATCH 03/15] docs: Remove sudo from pip installation instructions --- README.rst | 2 +- docs/quickstart.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index 32360d1..7756abc 100644 --- a/README.rst +++ b/README.rst @@ -60,7 +60,7 @@ Alternatively using pip, the Python package manager: .. code:: bash - sudo pip install yamllint + pip install --user yamllint Usage ^^^^^ diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 68cf3d0..eee4a2e 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -26,14 +26,14 @@ Alternatively using pip, the Python package manager: .. code:: bash - sudo pip install yamllint + pip install --user yamllint If you prefer installing from source, you can run, from the source directory: .. code:: bash python setup.py sdist - sudo pip install dist/yamllint-*.tar.gz + pip install --user dist/yamllint-*.tar.gz Running yamllint ---------------- From e4e99f0aba5bc894712a720d8516db556e48acf1 Mon Sep 17 00:00:00 2001 From: Justin Foreman Date: Tue, 29 May 2018 13:25:49 -0400 Subject: [PATCH 04/15] docs: Update README for CentOS dependency --- README.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7756abc..4314f09 100644 --- a/README.rst +++ b/README.rst @@ -38,7 +38,8 @@ Screenshot Installation ^^^^^^^^^^^^ -On Fedora / CentOS: +On Fedora / CentOS (note: `EPEL `_ is +required on CentOS): .. code:: bash From 479f5802024cd85f07895219ad1c09089db6891c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Tue, 2 Oct 2018 18:55:07 +0200 Subject: [PATCH 05/15] CI: Fix tests failing on Travis for Python 2.6 Because installing dependencies for `coveralls` now fails with: Collecting pycparser (from cffi>=1.7->cryptography>=1.3.4; python_version <= "2.7" and extra == "secure"->urllib3[secure]; python_version < "3"->coveralls) [...] pycparser requires Python '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' but the running Python is 2.6.9 --- .travis.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 80506f2..39f7a27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,14 +9,19 @@ python: - 3.6 - nightly install: - - pip install pyyaml flake8 flake8-import-order coveralls + - pip install pyyaml flake8 flake8-import-order - if [[ $TRAVIS_PYTHON_VERSION == 2.6 ]]; then pip install unittest2; fi + - if [[ $TRAVIS_PYTHON_VERSION != 2.6 ]]; then pip install coveralls; fi - if [[ $TRAVIS_PYTHON_VERSION != 2* ]]; then pip install sphinx; fi - pip install . script: - if [[ $TRAVIS_PYTHON_VERSION != 2.6 ]]; then flake8 .; fi - yamllint --strict $(git ls-files '*.yaml' '*.yml') - - coverage run --source=yamllint setup.py test + - if [[ $TRAVIS_PYTHON_VERSION != 2.6 ]]; then + coverage run --source=yamllint setup.py test; + else + python setup.py test; + fi - if [[ $TRAVIS_PYTHON_VERSION != 2* ]]; then python setup.py build_sphinx; fi From aaa8777f1d6ce6eb321c1cb17599293ca5361b59 Mon Sep 17 00:00:00 2001 From: "Guido Wischrop (mgm tp)" <43027257+mgmgwi@users.noreply.github.com> Date: Thu, 4 Oct 2018 16:04:54 +0200 Subject: [PATCH 06/15] Add quoted-strings rule * taken from https://github.com/adrienverge/yamllint/pull/110 (submitted by @jurajseffer) * small fixes for generic and multi-line strings * fixes for comments from @adrienverge --- tests/rules/test_quoted_strings.py | 125 +++++++++++++++++++++++++++++ yamllint/conf/default.yaml | 1 + yamllint/rules/__init__.py | 2 + yamllint/rules/quoted_strings.py | 74 +++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 tests/rules/test_quoted_strings.py create mode 100644 yamllint/rules/quoted_strings.py diff --git a/tests/rules/test_quoted_strings.py b/tests/rules/test_quoted_strings.py new file mode 100644 index 0000000..d848639 --- /dev/null +++ b/tests/rules/test_quoted_strings.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2018 ClearScore +# +# 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 . + +from tests.common import RuleTestCase + + +class QuotedTestCase(RuleTestCase): + rule_id = 'quoted-strings' + + def test_disabled(self): + conf = 'quoted-strings: disable' + self.check('---\n' + 'foo: bar\n', conf) + self.check('---\n' + 'foo: "bar"\n', conf) + self.check('---\n' + 'foo: \'bar\'\n', conf) + self.check('---\n' + 'bar: 123\n', conf) + + def test_quote_type_any(self): + conf = 'quoted-strings: {quote-type: any}\n' + self.check('---\n' + 'string1: "foo"\n' + 'number1: 123\n' # fails + 'string2: foo\n' # fails + 'string3: \'bar\'\n' + 'string4: !!str genericstring\n' # fails + 'string5: !!str 456\n' # fails + 'string6: !!str "quotedgenericstring"\n' + 'binary: !!binary binstring\n' + 'integer: !!int intstring\n' + 'boolean1: !!bool boolstring\n' + 'boolean2: !!bool "quotedboolstring"\n', + conf, problem1=(3, 10), problem2=(4, 10), + problem3=(6, 16), problem4=(7, 16)) + self.check('---\n' + 'multiline string 1: |\n' + ' line 1\n' + ' line 2\n' + 'multiline string 2: >\n' + ' word 1\n' + ' word 2\n' + 'multiline string 3:\n' + ' word 1\n' + ' word 2\n' + 'multiline string 4:\n' + ' "word 1\\\n' + ' word 2"\n', + conf, problem1=(9, 3)) + + def test_quote_type_single(self): + conf = 'quoted-strings: {quote-type: single}\n' + self.check('---\n' + 'string1: "foo"\n' # fails + 'number1: 123\n' # fails + 'string2: foo\n' # fails + 'string3: \'bar\'\n' + 'string4: !!str genericstring\n' # fails + 'string5: !!str 456\n' # fails + 'string6: !!str "quotedgenericstring"\n' # fails + 'binary: !!binary binstring\n' + 'integer: !!int intstring\n' + 'boolean1: !!bool boolstring\n' + 'boolean2: !!bool "quotedboolstring"\n', + conf, problem1=(2, 10), problem2=(3, 10), problem3=(4, 10), + problem4=(6, 16), problem5=(7, 16), problem6=(8, 16)) + self.check('---\n' + 'multiline string 1: |\n' + ' line 1\n' + ' line 2\n' + 'multiline string 2: >\n' + ' word 1\n' + ' word 2\n' + 'multiline string 3:\n' + ' word 1\n' + ' word 2\n' + 'multiline string 4:\n' + ' "word 1\\\n' + ' word 2"\n', + conf, problem1=(9, 3), problem2=(12, 3)) + + def test_quote_type_double(self): + conf = 'quoted-strings: {quote-type: double}\n' + self.check('---\n' + 'string1: "foo"\n' + 'number1: 123\n' # fails + 'string2: foo\n' # fails + 'string3: \'bar\'\n' # fails + 'string4: !!str genericstring\n' # fails + 'string5: !!str 456\n' # fails + 'string6: !!str "quotedgenericstring"\n' + 'binary: !!binary binstring\n' + 'integer: !!int intstring\n' + 'boolean1: !!bool boolstring\n' + 'boolean2: !!bool "quotedboolstring"\n', + conf, problem1=(3, 10), problem2=(4, 10), problem3=(5, 10), + problem4=(6, 16), problem5=(7, 16)) + self.check('---\n' + 'multiline string 1: |\n' + ' line 1\n' + ' line 2\n' + 'multiline string 2: >\n' + ' word 1\n' + ' word 2\n' + 'multiline string 3:\n' + ' word 1\n' + ' word 2\n' + 'multiline string 4:\n' + ' "word 1\\\n' + ' word 2"\n', + conf, problem1=(9, 3)) diff --git a/yamllint/conf/default.yaml b/yamllint/conf/default.yaml index 8432c9a..fcece4d 100644 --- a/yamllint/conf/default.yaml +++ b/yamllint/conf/default.yaml @@ -32,6 +32,7 @@ rules: max: 2 max-start: 0 max-end: 0 + quoted-strings: disable empty-values: forbid-in-block-mappings: false forbid-in-flow-mappings: false diff --git a/yamllint/rules/__init__.py b/yamllint/rules/__init__.py index d08a326..a084d6e 100644 --- a/yamllint/rules/__init__.py +++ b/yamllint/rules/__init__.py @@ -33,6 +33,7 @@ from yamllint.rules import ( new_line_at_end_of_file, new_lines, octal_values, + quoted_strings, trailing_spaces, truthy, ) @@ -56,6 +57,7 @@ _RULES = { new_line_at_end_of_file.ID: new_line_at_end_of_file, new_lines.ID: new_lines, octal_values.ID: octal_values, + quoted_strings.ID: quoted_strings, trailing_spaces.ID: trailing_spaces, truthy.ID: truthy, } diff --git a/yamllint/rules/quoted_strings.py b/yamllint/rules/quoted_strings.py new file mode 100644 index 0000000..2380898 --- /dev/null +++ b/yamllint/rules/quoted_strings.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2018 ClearScore +# +# 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 . + +""" +Use this rule to forbid any string values that are not quoted. +You can also enforce the type of the quote used - single or double - using the +``quote-type`` option. + +**Note**: Multi-line strings (with ``|`` or ``>``) will not be checked. + +.. rubric:: Examples + +#. With ``quoted-strings: {quote-type: any}`` + + the following code snippet would **PASS**: + :: + + foo: "bar" + bar: 'foo' + number: 123 + boolean: true + + the following code snippet would **FAIL**: + :: + + foo: bar +""" + +import yaml + +from yamllint.linter import LintProblem + +ID = 'quoted-strings' +TYPE = 'token' +CONF = {'quote-type': ('any', 'single', 'double')} + + +def check(conf, token, prev, next, nextnext, context): + quote_type = conf['quote-type'] + + if prev and isinstance(prev, yaml.tokens.TagToken): + if prev.value[1] != "str": + # we ignore generic strings, e.g. somestring: !!str testtest + return + + if isinstance(token, yaml.tokens.ScalarToken): + if isinstance(prev, yaml.tokens.ValueToken) or \ + isinstance(prev, yaml.tokens.TagToken): + if ((not token.plain) and + ((token.style == "|") or (token.style == ">"))): + # we ignore multi-line strings + return + + if ((quote_type == 'single' and token.style != "'") or + (quote_type == 'double' and token.style != '"') or + (quote_type == 'any' and token.style is None)): + yield LintProblem( + token.start_mark.line + 1, + token.start_mark.column + 1, + "string value is not quoted with %s quotes" % (quote_type) + ) From d41b64aa976e6f788543f0666106cb7762b15031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 4 Oct 2018 16:10:56 +0200 Subject: [PATCH 07/15] yamllint version 1.12.0 --- CHANGELOG.rst | 6 ++++++ yamllint/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 71f522e..d04a2a6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ Changelog ========= +1.12.0 (2018-10-04) +------------------- + +- Add a new `quoted-strings` rule +- Update installation documentation for pip, CentOS, Debian, Ubuntu, Mac OS + 1.11.1 (2018-04-06) ------------------- diff --git a/yamllint/__init__.py b/yamllint/__init__.py index e864758..a9b524f 100644 --- a/yamllint/__init__.py +++ b/yamllint/__init__.py @@ -22,7 +22,7 @@ indentation, etc.""" APP_NAME = 'yamllint' -APP_VERSION = '1.11.1' +APP_VERSION = '1.12.0' APP_DESCRIPTION = __doc__ __author__ = u'Adrien Vergé' From e864f57d374ce4ee0259e783573999e0fe290ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 11 Oct 2018 15:27:58 +0200 Subject: [PATCH 08/15] docs: Fix missing quoted-strings module in documentation --- docs/rules.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/rules.rst b/docs/rules.rst index 3900c28..15abe4b 100644 --- a/docs/rules.rst +++ b/docs/rules.rst @@ -104,6 +104,11 @@ octal-values .. automodule:: yamllint.rules.octal_values +quoted-strings +-------------- + +.. automodule:: yamllint.rules.quoted_strings + trailing-spaces --------------- From 524d721f0d2b5881f1b24c46d74038b3e47bd163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Thu, 11 Oct 2018 15:35:26 +0200 Subject: [PATCH 09/15] Update .gitignore to exclude build/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2a3b93a..058ff7a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ __pycache__ /docs/_build /dist /yamllint.egg-info +/build From 8354d500162b70b134d9d4822a461f024c0f5c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Tue, 16 Oct 2018 18:47:26 +0200 Subject: [PATCH 10/15] quoted-strings: Fix broken rule Original implementation was completely broken. Documentation and actual behavior were different. Numbers and booleans were detected as wrong, as well as explicit types. Fixes #136 and #130. --- tests/rules/test_quoted_strings.py | 56 +++++++++++++++--------------- yamllint/rules/quoted_strings.py | 45 +++++++++++++----------- 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/tests/rules/test_quoted_strings.py b/tests/rules/test_quoted_strings.py index d848639..04ee492 100644 --- a/tests/rules/test_quoted_strings.py +++ b/tests/rules/test_quoted_strings.py @@ -34,19 +34,19 @@ class QuotedTestCase(RuleTestCase): def test_quote_type_any(self): conf = 'quoted-strings: {quote-type: any}\n' self.check('---\n' - 'string1: "foo"\n' - 'number1: 123\n' # fails - 'string2: foo\n' # fails + 'boolean1: true\n' + 'number1: 123\n' + 'string1: foo\n' # fails + 'string2: "foo"\n' 'string3: \'bar\'\n' - 'string4: !!str genericstring\n' # fails - 'string5: !!str 456\n' # fails + 'string4: !!str genericstring\n' + 'string5: !!str 456\n' 'string6: !!str "quotedgenericstring"\n' 'binary: !!binary binstring\n' 'integer: !!int intstring\n' - 'boolean1: !!bool boolstring\n' - 'boolean2: !!bool "quotedboolstring"\n', - conf, problem1=(3, 10), problem2=(4, 10), - problem3=(6, 16), problem4=(7, 16)) + 'boolean2: !!bool boolstring\n' + 'boolean3: !!bool "quotedboolstring"\n', + conf, problem=(4, 10)) self.check('---\n' 'multiline string 1: |\n' ' line 1\n' @@ -65,19 +65,19 @@ class QuotedTestCase(RuleTestCase): def test_quote_type_single(self): conf = 'quoted-strings: {quote-type: single}\n' self.check('---\n' - 'string1: "foo"\n' # fails - 'number1: 123\n' # fails - 'string2: foo\n' # fails + 'boolean1: true\n' + 'number1: 123\n' + 'string1: foo\n' # fails + 'string2: "foo"\n' # fails 'string3: \'bar\'\n' - 'string4: !!str genericstring\n' # fails - 'string5: !!str 456\n' # fails - 'string6: !!str "quotedgenericstring"\n' # fails + 'string4: !!str genericstring\n' + 'string5: !!str 456\n' + 'string6: !!str "quotedgenericstring"\n' 'binary: !!binary binstring\n' 'integer: !!int intstring\n' - 'boolean1: !!bool boolstring\n' - 'boolean2: !!bool "quotedboolstring"\n', - conf, problem1=(2, 10), problem2=(3, 10), problem3=(4, 10), - problem4=(6, 16), problem5=(7, 16), problem6=(8, 16)) + 'boolean2: !!bool boolstring\n' + 'boolean3: !!bool "quotedboolstring"\n', + conf, problem1=(4, 10), problem2=(5, 10)) self.check('---\n' 'multiline string 1: |\n' ' line 1\n' @@ -96,19 +96,19 @@ class QuotedTestCase(RuleTestCase): def test_quote_type_double(self): conf = 'quoted-strings: {quote-type: double}\n' self.check('---\n' - 'string1: "foo"\n' - 'number1: 123\n' # fails - 'string2: foo\n' # fails + 'boolean1: true\n' + 'number1: 123\n' + 'string1: foo\n' # fails + 'string2: "foo"\n' 'string3: \'bar\'\n' # fails - 'string4: !!str genericstring\n' # fails - 'string5: !!str 456\n' # fails + 'string4: !!str genericstring\n' + 'string5: !!str 456\n' 'string6: !!str "quotedgenericstring"\n' 'binary: !!binary binstring\n' 'integer: !!int intstring\n' - 'boolean1: !!bool boolstring\n' - 'boolean2: !!bool "quotedboolstring"\n', - conf, problem1=(3, 10), problem2=(4, 10), problem3=(5, 10), - problem4=(6, 16), problem5=(7, 16)) + 'boolean2: !!bool boolstring\n' + 'boolean3: !!bool "quotedboolstring"\n', + conf, problem1=(4, 10), problem2=(6, 10)) self.check('---\n' 'multiline string 1: |\n' ' line 1\n' diff --git a/yamllint/rules/quoted_strings.py b/yamllint/rules/quoted_strings.py index 2380898..711a627 100644 --- a/yamllint/rules/quoted_strings.py +++ b/yamllint/rules/quoted_strings.py @@ -16,8 +16,8 @@ """ Use this rule to forbid any string values that are not quoted. -You can also enforce the type of the quote used - single or double - using the -``quote-type`` option. +You can also enforce the type of the quote used using the ``quote-type`` option +(``single``, ``double`` or ``any``). **Note**: Multi-line strings (with ``|`` or ``>``) will not be checked. @@ -51,24 +51,27 @@ CONF = {'quote-type': ('any', 'single', 'double')} def check(conf, token, prev, next, nextnext, context): quote_type = conf['quote-type'] - if prev and isinstance(prev, yaml.tokens.TagToken): - if prev.value[1] != "str": - # we ignore generic strings, e.g. somestring: !!str testtest + if (isinstance(token, yaml.tokens.ScalarToken) and + isinstance(prev, (yaml.ValueToken, yaml.TagToken))): + # Ignore explicit types, e.g. !!str testtest or !!int 42 + if (prev and isinstance(prev, yaml.tokens.TagToken) and + prev.value[0] == '!!'): return - if isinstance(token, yaml.tokens.ScalarToken): - if isinstance(prev, yaml.tokens.ValueToken) or \ - isinstance(prev, yaml.tokens.TagToken): - if ((not token.plain) and - ((token.style == "|") or (token.style == ">"))): - # we ignore multi-line strings - return - - if ((quote_type == 'single' and token.style != "'") or - (quote_type == 'double' and token.style != '"') or - (quote_type == 'any' and token.style is None)): - yield LintProblem( - token.start_mark.line + 1, - token.start_mark.column + 1, - "string value is not quoted with %s quotes" % (quote_type) - ) + # Ignore numbers, booleans, etc. + resolver = yaml.resolver.Resolver() + if resolver.resolve(yaml.nodes.ScalarNode, token.value, + (True, False)) != 'tag:yaml.org,2002:str': + return + + # Ignore multi-line strings + if (not token.plain) and (token.style == "|" or token.style == ">"): + return + + if ((quote_type == 'single' and token.style != "'") or + (quote_type == 'double' and token.style != '"') or + (quote_type == 'any' and token.style is None)): + yield LintProblem( + token.start_mark.line + 1, + token.start_mark.column + 1, + "string value is not quoted with %s quotes" % (quote_type)) From dc4a9f4fff0c52944f1b285ab2088280276eb72d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Wed, 17 Oct 2018 10:22:32 +0200 Subject: [PATCH 11/15] yamllint version 1.12.1 --- CHANGELOG.rst | 6 ++++++ yamllint/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d04a2a6..c099fc2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ Changelog ========= +1.12.1 (2018-10-17) +------------------- + +- Fix the `quoted-strings` rule, broken implementation +- Fix missing documentation for the `quoted-strings` rule + 1.12.0 (2018-10-04) ------------------- diff --git a/yamllint/__init__.py b/yamllint/__init__.py index a9b524f..a61ec8a 100644 --- a/yamllint/__init__.py +++ b/yamllint/__init__.py @@ -22,7 +22,7 @@ indentation, etc.""" APP_NAME = 'yamllint' -APP_VERSION = '1.12.0' +APP_VERSION = '1.12.1' APP_DESCRIPTION = __doc__ __author__ = u'Adrien Vergé' From 3ef85739e3e4d4fb05999167ce2e1b97a63fc272 Mon Sep 17 00:00:00 2001 From: sedrubal Date: Thu, 18 Oct 2018 17:16:42 +0200 Subject: [PATCH 12/15] Use isinstance(x, y) instead of type(x) == y Fixes pylint C0123. --- yamllint/config.py | 16 ++++++++-------- yamllint/linter.py | 2 +- yamllint/rules/document_end.py | 14 ++++++++------ yamllint/rules/indentation.py | 4 ++-- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/yamllint/config.py b/yamllint/config.py index f9e4de8..3a3f3c7 100644 --- a/yamllint/config.py +++ b/yamllint/config.py @@ -52,7 +52,7 @@ class YamlLintConfig(object): assert isinstance(base_config, YamlLintConfig) for rule in self.rules: - if (type(self.rules[rule]) == dict and + if (isinstance(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]) @@ -70,7 +70,7 @@ class YamlLintConfig(object): except Exception as e: raise YamlLintConfigError('invalid config: %s' % e) - if type(conf) != dict: + if not isinstance(conf, dict): raise YamlLintConfigError('invalid config: not a dict') self.rules = conf.get('rules', {}) @@ -85,7 +85,7 @@ class YamlLintConfig(object): raise YamlLintConfigError('invalid config: %s' % e) if 'ignore' in conf: - if type(conf['ignore']) != str: + if not isinstance(conf['ignore'], str): raise YamlLintConfigError( 'invalid config: ignore should contain file patterns') self.ignore = pathspec.PathSpec.from_lines( @@ -107,10 +107,10 @@ def validate_rule_conf(rule, conf): elif conf == 'enable': conf = {} - if type(conf) == dict: + if isinstance(conf, dict): if ('ignore' in conf and - type(conf['ignore']) != pathspec.pathspec.PathSpec): - if type(conf['ignore']) != str: + not isinstance(conf['ignore'], pathspec.pathspec.PathSpec)): + if not isinstance(conf['ignore'], str): raise YamlLintConfigError( 'invalid config: ignore should contain file patterns') conf['ignore'] = pathspec.PathSpec.from_lines( @@ -130,14 +130,14 @@ def validate_rule_conf(rule, conf): raise YamlLintConfigError( 'invalid config: unknown option "%s" for rule "%s"' % (optkey, rule.ID)) - if type(options[optkey]) == tuple: + 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])) else: - if type(conf[optkey]) != options[optkey]: + if not isinstance(conf[optkey], options[optkey]): raise YamlLintConfigError( 'invalid config: option "%s" of "%s" should be %s' % (optkey, rule.ID, options[optkey].__name__)) diff --git a/yamllint/linter.py b/yamllint/linter.py index c8eff8d..aaf43e5 100644 --- a/yamllint/linter.py +++ b/yamllint/linter.py @@ -226,7 +226,7 @@ def run(input, conf, filepath=None): if conf.is_file_ignored(filepath): return () - if type(input) in (type(b''), type(u'')): # compat with Python 2 & 3 + if isinstance(input, (type(b''), type(u''))): # compat with Python 2 & 3 return _run(input, conf, filepath) elif hasattr(input, 'read'): # Python 2's file or Python 3's io.IOBase # We need to have everything in memory to parse correctly diff --git a/yamllint/rules/document_end.py b/yamllint/rules/document_end.py index 34323e4..8335a05 100644 --- a/yamllint/rules/document_end.py +++ b/yamllint/rules/document_end.py @@ -86,14 +86,16 @@ CONF = {'present': bool} def check(conf, token, prev, next, nextnext, context): if conf['present']: - if (isinstance(token, yaml.StreamEndToken) and - not (isinstance(prev, yaml.DocumentEndToken) or - isinstance(prev, yaml.StreamStartToken))): + is_stream_end = isinstance(token, yaml.StreamEndToken) + is_start = isinstance(token, yaml.DocumentStartToken) + prev_is_end_or_stream_start = isinstance( + prev, (yaml.DocumentEndToken, yaml.StreamStartToken) + ) + + if is_stream_end and not prev_is_end_or_stream_start: yield LintProblem(token.start_mark.line, 1, 'missing document end "..."') - elif (isinstance(token, yaml.DocumentStartToken) and - not (isinstance(prev, yaml.DocumentEndToken) or - isinstance(prev, yaml.StreamStartToken))): + elif is_start and not prev_is_end_or_stream_start: yield LintProblem(token.start_mark.line + 1, 1, 'missing document end "..."') diff --git a/yamllint/rules/indentation.py b/yamllint/rules/indentation.py index fb14faf..cf4ebc5 100644 --- a/yamllint/rules/indentation.py +++ b/yamllint/rules/indentation.py @@ -224,7 +224,7 @@ def check_scalar_indentation(conf, token, context): def compute_expected_indent(found_indent): def detect_indent(base_indent): - if type(context['spaces']) is not int: + if not isinstance(context['spaces'], int): context['spaces'] = found_indent - base_indent return base_indent + context['spaces'] @@ -312,7 +312,7 @@ def _check(conf, token, prev, next, nextnext, context): token.start_mark.line + 1 > context['cur_line']) def detect_indent(base_indent, next): - if type(context['spaces']) is not int: + if not isinstance(context['spaces'], int): context['spaces'] = next.start_mark.column - base_indent return base_indent + context['spaces'] From 5062b91cac1cd3d6bcc277bc8a3fe82a062097d9 Mon Sep 17 00:00:00 2001 From: sedrubal Date: Thu, 18 Oct 2018 17:02:23 +0200 Subject: [PATCH 13/15] cli: Add -f colored to force colors `-f standard` shows non-colored output, `-f colored` shows colored output, `-f auto` is the new default, it chooses `standard` or `colored` depending on terminal capabilities. --- tests/test_cli.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++- yamllint/cli.py | 7 +++--- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 341e3fc..6d570f3 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -351,7 +351,7 @@ class CommandLineTestCase(unittest.TestCase): '\n' % file)) self.assertEqual(err, '') - def test_run_colored_output(self): + def test_run_default_format_output_in_tty(self): file = os.path.join(self.wd, 'a.yaml') # Create a pseudo-TTY and redirect stdout to it @@ -383,3 +383,59 @@ class CommandLineTestCase(unittest.TestCase): 'no new line character at the end of file ' '\033[2m(new-line-at-end-of-file)\033[0m\n' '\n' % file)) + + def test_run_default_format_output_without_tty(self): + file = os.path.join(self.wd, 'a.yaml') + + sys.stdout, sys.stderr = StringIO(), StringIO() + with self.assertRaises(SystemExit) as ctx: + cli.run((file, )) + + self.assertEqual(ctx.exception.code, 1) + + out, err = sys.stdout.getvalue(), sys.stderr.getvalue() + self.assertEqual(out, ( + '%s\n' + ' 2:4 error trailing spaces (trailing-spaces)\n' + ' 3:4 error no new line character at the end of file ' + '(new-line-at-end-of-file)\n' + '\n' % file)) + self.assertEqual(err, '') + + def test_run_auto_output_without_tty_output(self): + file = os.path.join(self.wd, 'a.yaml') + + sys.stdout, sys.stderr = StringIO(), StringIO() + with self.assertRaises(SystemExit) as ctx: + cli.run((file, '--format', 'auto')) + + self.assertEqual(ctx.exception.code, 1) + + out, err = sys.stdout.getvalue(), sys.stderr.getvalue() + self.assertEqual(out, ( + '%s\n' + ' 2:4 error trailing spaces (trailing-spaces)\n' + ' 3:4 error no new line character at the end of file ' + '(new-line-at-end-of-file)\n' + '\n' % file)) + self.assertEqual(err, '') + + def test_run_format_colored(self): + file = os.path.join(self.wd, 'a.yaml') + + sys.stdout, sys.stderr = StringIO(), StringIO() + with self.assertRaises(SystemExit) as ctx: + cli.run((file, '--format', 'colored')) + + self.assertEqual(ctx.exception.code, 1) + + out, err = sys.stdout.getvalue(), sys.stderr.getvalue() + self.assertEqual(out, ( + '\033[4m%s\033[0m\n' + ' \033[2m2:4\033[0m \033[31merror\033[0m ' + 'trailing spaces \033[2m(trailing-spaces)\033[0m\n' + ' \033[2m3:4\033[0m \033[31merror\033[0m ' + 'no new line character at the end of file ' + '\033[2m(new-line-at-end-of-file)\033[0m\n' + '\n' % file)) + self.assertEqual(err, '') diff --git a/yamllint/cli.py b/yamllint/cli.py index 0faee16..5cb84fc 100644 --- a/yamllint/cli.py +++ b/yamllint/cli.py @@ -96,8 +96,8 @@ def run(argv=None): action='store', help='custom configuration (as YAML source)') parser.add_argument('-f', '--format', - choices=('parsable', 'standard'), default='standard', - help='format for parsing output') + choices=('parsable', 'standard', 'colored', 'auto'), + default='auto', help='format for parsing output') parser.add_argument('-s', '--strict', action='store_true', help='return non-zero exit code on warnings ' @@ -143,7 +143,8 @@ def run(argv=None): for problem in linter.run(f, conf, filepath): if args.format == 'parsable': print(Format.parsable(problem, file)) - elif supports_color(): + elif args.format == 'colored' or \ + (args.format == 'auto' and supports_color()): if first: print('\033[4m%s\033[0m' % file) first = False From 66adaee66c773b85d56a561bd10cf72af81d182e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Wed, 14 Nov 2018 19:02:52 +0100 Subject: [PATCH 14/15] docs: Add documentation on the new -f colored option --- docs/configuration.rst | 4 ++-- docs/quickstart.rst | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index 134172d..2557a4f 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -102,8 +102,8 @@ Errors and warnings ------------------- Problems detected by yamllint can be raised either as errors or as warnings. -The CLI will output them (with different colors when using the ``standard`` -output format). +The CLI will output them (with different colors when using the ``colored`` +output format, or ``auto`` when run from a terminal). By default the script will exit with a return code ``1`` *only when* there is one or more error(s). diff --git a/docs/quickstart.rst b/docs/quickstart.rst index eee4a2e..4d7692e 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -68,6 +68,10 @@ The output will look like (colors are not displayed here): 10:1 error too many blank lines (4 > 2) (empty-lines) 11:4 error too many spaces inside braces (braces) +By default, the output of yamllint is colored when run from a terminal, and pure +text in other cases. Add the ``-f standard`` arguments to force non-colored output. +Use the ``-f colored`` arguments to force colored output. + Add the ``-f parsable`` arguments if you need an output format parsable by a machine (for instance for :doc:`syntax highlighting in text editors `). The output will then look like: From 318a12bbe6a84d174c4d99aebf0b8877b605a999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Wed, 14 Nov 2018 19:04:58 +0100 Subject: [PATCH 15/15] yamllint version 1.13.0 --- CHANGELOG.rst | 7 +++++++ yamllint/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c099fc2..bf71899 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Changelog ========= +1.13.0 (2018-11-14) +------------------- + +- Use `isinstance(x, y)` instead of `type(x) == y` +- Add a new `-f colored` option +- Update documentation about colored output when run from CLI + 1.12.1 (2018-10-17) ------------------- diff --git a/yamllint/__init__.py b/yamllint/__init__.py index a61ec8a..ba6780a 100644 --- a/yamllint/__init__.py +++ b/yamllint/__init__.py @@ -22,7 +22,7 @@ indentation, etc.""" APP_NAME = 'yamllint' -APP_VERSION = '1.12.1' +APP_VERSION = '1.13.0' APP_DESCRIPTION = __doc__ __author__ = u'Adrien Vergé'