Merge tag 'v1.8.1' into packaging

packaging
Philipp Huebner 7 years ago
commit a4ab40c51a

@ -1,17 +1,20 @@
--- ---
language: python language: python
python: python:
- 2.6
- 2.7 - 2.7
- 3.3 - 3.3
- 3.4 - 3.4
- 3.5 - 3.5
- 3.6
- nightly - nightly
install: install:
- pip install pyyaml flake8 coveralls - pip install pyyaml flake8 flake8-import-order coveralls
- if [[ $TRAVIS_PYTHON_VERSION == 2.6 ]]; then pip install unittest2; fi
- pip install . - pip install .
script: script:
- flake8 . - if [[ $TRAVIS_PYTHON_VERSION != 2.6 ]]; then flake8 .; fi
- yamllint $(git ls-files '*.yaml' '*.yml') - yamllint --strict $(git ls-files '*.yaml' '*.yml')
- coverage run --source=yamllint setup.py test - coverage run --source=yamllint setup.py test
after_success: after_success:
coveralls coveralls

@ -0,0 +1,15 @@
Changelog
=========
1.8.1 (2017-07-04)
------------------
- Require pathspec >= 0.5.3
- Support Python 2.6
- Add a changelog
1.8.0 (2017-06-28)
------------------
- Refactor argparse with mutually_exclusive_group
- Add support to ignore paths in configuration

@ -44,7 +44,7 @@ On Fedora / CentOS:
sudo dnf install yamllint sudo dnf install yamllint
On Debian 9+ / Ubuntu 16.04+: On Debian 8+ / Ubuntu 16.04+:
.. code:: bash .. code:: bash
@ -119,6 +119,27 @@ or for a whole block:
consectetur : adipiscing elit consectetur : adipiscing elit
# yamllint enable # yamllint enable
Specific files can be ignored (totally or for some rules only) using a
``.gitignore``-style pattern:
.. code:: yaml
# For all rules
ignore: |
*.dont-lint-me.yaml
/bin/
!/bin/*.lint-me-anyway.yaml
rules:
key-duplicates:
ignore: |
generated
*.template.yaml
trailing-spaces:
ignore: |
*.ignore-trailing-spaces.yaml
/ascii-art/*
`Read more in the complete documentation! <https://yamllint.readthedocs.io/>`_ `Read more in the complete documentation! <https://yamllint.readthedocs.io/>`_
License License

@ -102,8 +102,69 @@ Errors and warnings
------------------- -------------------
Problems detected by yamllint can be raised either as errors or as 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).
In both cases, the script will output them (with different colors when using the By default the script will exit with a return code ``1`` *only when* there is one or
``standard`` output format), but the exit code can be different. More precisely, more error(s).
the script will exit will a failure code *only when* there is one or more
error(s). However if strict mode is enabled with the ``-s`` (or ``--strict``) option, the
return code will be:
* ``0`` if no errors or warnings occur
* ``1`` if one or more errors occur
* ``2`` if no errors occur, but one or more warnings occur
Ignoring paths
--------------
It is possible to exclude specific files or directories, so that the linter
doesn't process them.
You can either totally ignore files (they won't be looked at):
.. code-block:: yaml
extends: default
ignore: |
/this/specific/file.yaml
/all/this/directory/
*.template.yaml
or ignore paths only for specific rules:
.. code-block:: yaml
extends: default
rules:
trailing-spaces:
ignore: |
/this-file-has-trailing-spaces-but-it-is-OK.yaml
/generated/*.yaml
Note that this ``.gitignore``-style path pattern allows complex path
exclusion/inclusion, see the `pathspec README file
<https://pypi.python.org/pypi/pathspec>`_ for more details.
Here is a more complex example:
.. code-block:: yaml
# For all rules
ignore: |
*.dont-lint-me.yaml
/bin/
!/bin/*.lint-me-anyway.yaml
extends: default
rules:
key-duplicates:
ignore: |
generated
*.template.yaml
trailing-spaces:
ignore: |
*.ignore-trailing-spaces.yaml
/ascii-art/*

@ -32,7 +32,7 @@ or:
- This line is waaaaaaaaaay too long but yamllint will not report anything about it. - This line is waaaaaaaaaay too long but yamllint will not report anything about it.
This line will be checked by yamllint. This line will be checked by yamllint.
It it possible, although not recommend, to disabled **all** rules for a It is possible, although not recommend, to disabled **all** rules for a
specific line: specific line:
.. code-block:: yaml .. code-block:: yaml
@ -46,7 +46,7 @@ If you need to disable multiple rules, it is allowed to chain rules like this:
Disabling checks for all (or part of) the file Disabling checks for all (or part of) the file
---------------------------------------------- ----------------------------------------------
To prevent yamllint from reporting problems for the whoe file, or for a block of To prevent yamllint from reporting problems for the whole file, or for a block of
lines within the file, use ``# yamllint disable ...`` and ``# yamllint enable lines within the file, use ``# yamllint disable ...`` and ``# yamllint enable
...`` directive comments. For instance: ...`` directive comments. For instance:
@ -60,7 +60,7 @@ lines within the file, use ``# yamllint disable ...`` and ``# yamllint enable
- rest of the document... - rest of the document...
It it possible, although not recommend, to disabled **all** rules: It is possible, although not recommend, to disabled **all** rules:
.. code-block:: yaml .. code-block:: yaml

@ -10,7 +10,7 @@ On Fedora / CentOS:
sudo dnf install yamllint sudo dnf install yamllint
On Debian 9+ / Ubuntu 16.04+: On Debian 8+ / Ubuntu 16.04+:
.. code:: bash .. code:: bash

@ -9,8 +9,12 @@ text editor.
Vim Vim
--- ---
Assuming that the `syntastic <https://github.com/scrooloose/syntastic>`_ plugin Assuming that the `ALE <https://github.com/w0rp/ale>`_ plugin is
is installed, add to your ``.vimrc``: installed, yamllint is supported by default. It is automatically enabled when
editing YAML files.
If you instead use the `syntastic <https://github.com/scrooloose/syntastic>`_
plugin, add this to your ``.vimrc``:
:: ::
@ -23,6 +27,12 @@ Assuming that the `neomake <https://github.com/benekastah/neomake>`_ plugin is
installed, yamllint is supported by default. It is automatically enabled when installed, yamllint is supported by default. It is automatically enabled when
editing YAML files. editing YAML files.
Emacs
-----
If you are `flycheck <https://github.com/flycheck/flycheck>`_ user, you can use
`flycheck-yamllint <https://github.com/krzysztof-magosa/flycheck-yamllint>`_ integration.
Other text editors Other text editors
------------------ ------------------

@ -0,0 +1,11 @@
---
# For use with pre-commit.
# See usage instructions at http://pre-commit.com
- id: yamllint
name: yamllint
description: This hook runs yamllint.
entry: yamllint
language: python
files: \.(yaml|yml)$

@ -0,0 +1,5 @@
[bdist_wheel]
universal = 1
[flake8]
import-order-style = pep8

@ -46,7 +46,6 @@ setup(
entry_points={'console_scripts': ['yamllint=yamllint.cli:run']}, entry_points={'console_scripts': ['yamllint=yamllint.cli:run']},
package_data={'yamllint': ['conf/*.yaml'], package_data={'yamllint': ['conf/*.yaml'],
'tests': ['yaml-1.2-spec-examples/*']}, 'tests': ['yaml-1.2-spec-examples/*']},
install_requires=['pyyaml'], install_requires=['pathspec >=0.5.3', 'pyyaml'],
tests_require=['nose'], test_suite='tests',
test_suite='nose.collector',
) )

@ -14,7 +14,14 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest import os
import tempfile
import sys
try:
assert sys.version_info >= (2, 7)
import unittest
except:
import unittest2 as unittest
import yaml import yaml
@ -49,3 +56,21 @@ class RuleTestCase(unittest.TestCase):
real_problems = list(linter.run(source, self.build_fake_config(conf))) real_problems = list(linter.run(source, self.build_fake_config(conf)))
self.assertEqual(real_problems, expected_problems) self.assertEqual(real_problems, expected_problems)
def build_temp_workspace(files):
tempdir = tempfile.mkdtemp(prefix='yamllint-tests-')
for path, content in files.items():
path = os.path.join(tempdir, path)
if not os.path.exists(os.path.dirname(path)):
os.makedirs(os.path.dirname(path))
if type(content) is list:
os.mkdir(path)
else:
mode = 'wb' if isinstance(content, bytes) else 'w'
with open(path, mode) as f:
f.write(content)
return tempdir

@ -32,11 +32,19 @@ class ColonTestCase(RuleTestCase):
'dict7: { a: 1, b, c: 3 }\n', conf) 'dict7: { a: 1, b, c: 3 }\n', conf)
def test_min_spaces(self): def test_min_spaces(self):
conf = 'braces: {max-spaces-inside: -1, min-spaces-inside: 0}' conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 0\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: {}\n', conf) 'dict: {}\n', conf)
conf = 'braces: {max-spaces-inside: -1, min-spaces-inside: 1}' conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: {}\n', conf, problem=(2, 8)) 'dict: {}\n', conf, problem=(2, 8))
self.check('---\n' self.check('---\n'
@ -52,7 +60,11 @@ class ColonTestCase(RuleTestCase):
' b\n' ' b\n'
'}\n', conf) '}\n', conf)
conf = 'braces: {max-spaces-inside: -1, min-spaces-inside: 3}' conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 3\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: { a: 1, b }\n', conf, 'dict: { a: 1, b }\n', conf,
problem1=(2, 9), problem2=(2, 17)) problem1=(2, 9), problem2=(2, 17))
@ -60,7 +72,11 @@ class ColonTestCase(RuleTestCase):
'dict: { a: 1, b }\n', conf) 'dict: { a: 1, b }\n', conf)
def test_max_spaces(self): def test_max_spaces(self):
conf = 'braces: {max-spaces-inside: 0, min-spaces-inside: -1}' conf = ('braces:\n'
' max-spaces-inside: 0\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: {}\n', conf) 'dict: {}\n', conf)
self.check('---\n' self.check('---\n'
@ -79,7 +95,11 @@ class ColonTestCase(RuleTestCase):
' b\n' ' b\n'
'}\n', conf) '}\n', conf)
conf = 'braces: {max-spaces-inside: 3, min-spaces-inside: -1}' conf = ('braces:\n'
' max-spaces-inside: 3\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: { a: 1, b }\n', conf) 'dict: { a: 1, b }\n', conf)
self.check('---\n' self.check('---\n'
@ -87,7 +107,11 @@ class ColonTestCase(RuleTestCase):
problem1=(2, 11), problem2=(2, 23)) problem1=(2, 11), problem2=(2, 23))
def test_min_and_max_spaces(self): def test_min_and_max_spaces(self):
conf = 'braces: {max-spaces-inside: 0, min-spaces-inside: 0}' conf = ('braces:\n'
' max-spaces-inside: 0\n'
' min-spaces-inside: 0\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: {}\n', conf) 'dict: {}\n', conf)
self.check('---\n' self.check('---\n'
@ -95,14 +119,169 @@ class ColonTestCase(RuleTestCase):
self.check('---\n' self.check('---\n'
'dict: { a: 1, b}\n', conf, problem=(2, 10)) 'dict: { a: 1, b}\n', conf, problem=(2, 10))
conf = 'braces: {max-spaces-inside: 1, min-spaces-inside: 1}' conf = ('braces:\n'
' max-spaces-inside: 1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: {a: 1, b, c: 3 }\n', conf, problem=(2, 8)) 'dict: {a: 1, b, c: 3 }\n', conf, problem=(2, 8))
conf = 'braces: {max-spaces-inside: 2, min-spaces-inside: 0}' conf = ('braces:\n'
' max-spaces-inside: 2\n'
' min-spaces-inside: 0\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'dict: {a: 1, b, c: 3 }\n', conf) 'dict: {a: 1, b, c: 3 }\n', conf)
self.check('---\n' self.check('---\n'
'dict: { a: 1, b, c: 3 }\n', conf) 'dict: { a: 1, b, c: 3 }\n', conf)
self.check('---\n' self.check('---\n'
'dict: { a: 1, b, c: 3 }\n', conf, problem=(2, 10)) 'dict: { a: 1, b, c: 3 }\n', conf, problem=(2, 10))
def test_min_spaces_empty(self):
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 0\n'
' min-spaces-inside-empty: 0\n')
self.check('---\n'
'array: {}\n', conf)
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: {}\n', conf, problem=(2, 9))
self.check('---\n'
'array: { }\n', conf)
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: 3\n')
self.check('---\n'
'array: {}\n', conf, problem=(2, 9))
self.check('---\n'
'array: { }\n', conf)
def test_max_spaces_empty(self):
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 0\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n'
'array: {}\n', conf)
self.check('---\n'
'array: { }\n', conf, problem=(2, 9))
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n'
'array: {}\n', conf)
self.check('---\n'
'array: { }\n', conf)
self.check('---\n'
'array: { }\n', conf, problem=(2, 10))
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 3\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n'
'array: {}\n', conf)
self.check('---\n'
'array: { }\n', conf)
self.check('---\n'
'array: { }\n', conf, problem=(2, 12))
def test_min_and_max_spaces_empty(self):
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 2\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: {}\n', conf, problem=(2, 9))
self.check('---\n'
'array: { }\n', conf)
self.check('---\n'
'array: { }\n', conf)
self.check('---\n'
'array: { }\n', conf, problem=(2, 11))
def test_mixed_empty_nonempty(self):
conf = ('braces:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: 0\n'
' min-spaces-inside-empty: 0\n')
self.check('---\n'
'array: { a: 1, b }\n', conf)
self.check('---\n'
'array: {a: 1, b}\n', conf,
problem1=(2, 9), problem2=(2, 16))
self.check('---\n'
'array: {}\n', conf)
self.check('---\n'
'array: { }\n', conf,
problem1=(2, 9))
conf = ('braces:\n'
' max-spaces-inside: 0\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: { a: 1, b }\n', conf,
problem1=(2, 9), problem2=(2, 17))
self.check('---\n'
'array: {a: 1, b}\n', conf)
self.check('---\n'
'array: {}\n', conf,
problem1=(2, 9))
self.check('---\n'
'array: { }\n', conf)
conf = ('braces:\n'
' max-spaces-inside: 2\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: { a: 1, b }\n', conf)
self.check('---\n'
'array: {a: 1, b }\n', conf,
problem1=(2, 9), problem2=(2, 18))
self.check('---\n'
'array: {}\n', conf,
problem1=(2, 9))
self.check('---\n'
'array: { }\n', conf)
self.check('---\n'
'array: { }\n', conf,
problem1=(2, 11))
conf = ('braces:\n'
' max-spaces-inside: 1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: { a: 1, b }\n', conf)
self.check('---\n'
'array: {a: 1, b}\n', conf,
problem1=(2, 9), problem2=(2, 16))
self.check('---\n'
'array: {}\n', conf,
problem1=(2, 9))
self.check('---\n'
'array: { }\n', conf)

@ -32,11 +32,19 @@ class ColonTestCase(RuleTestCase):
'array7: [ a, b, c ]\n', conf) 'array7: [ a, b, c ]\n', conf)
def test_min_spaces(self): def test_min_spaces(self):
conf = 'brackets: {max-spaces-inside: -1, min-spaces-inside: 0}' conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 0\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: []\n', conf) 'array: []\n', conf)
conf = 'brackets: {max-spaces-inside: -1, min-spaces-inside: 1}' conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: []\n', conf, problem=(2, 9)) 'array: []\n', conf, problem=(2, 9))
self.check('---\n' self.check('---\n'
@ -51,7 +59,11 @@ class ColonTestCase(RuleTestCase):
' b\n' ' b\n'
']\n', conf) ']\n', conf)
conf = 'brackets: {max-spaces-inside: -1, min-spaces-inside: 3}' conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 3\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: [ a, b ]\n', conf, 'array: [ a, b ]\n', conf,
problem1=(2, 10), problem2=(2, 15)) problem1=(2, 10), problem2=(2, 15))
@ -59,7 +71,11 @@ class ColonTestCase(RuleTestCase):
'array: [ a, b ]\n', conf) 'array: [ a, b ]\n', conf)
def test_max_spaces(self): def test_max_spaces(self):
conf = 'brackets: {max-spaces-inside: 0, min-spaces-inside: -1}' conf = ('brackets:\n'
' max-spaces-inside: 0\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: []\n', conf) 'array: []\n', conf)
self.check('---\n' self.check('---\n'
@ -78,7 +94,11 @@ class ColonTestCase(RuleTestCase):
' b\n' ' b\n'
']\n', conf) ']\n', conf)
conf = 'brackets: {max-spaces-inside: 3, min-spaces-inside: -1}' conf = ('brackets:\n'
' max-spaces-inside: 3\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: [ a, b ]\n', conf) 'array: [ a, b ]\n', conf)
self.check('---\n' self.check('---\n'
@ -86,7 +106,11 @@ class ColonTestCase(RuleTestCase):
problem1=(2, 12), problem2=(2, 21)) problem1=(2, 12), problem2=(2, 21))
def test_min_and_max_spaces(self): def test_min_and_max_spaces(self):
conf = 'brackets: {max-spaces-inside: 0, min-spaces-inside: 0}' conf = ('brackets:\n'
' max-spaces-inside: 0\n'
' min-spaces-inside: 0\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: []\n', conf) 'array: []\n', conf)
self.check('---\n' self.check('---\n'
@ -94,14 +118,169 @@ class ColonTestCase(RuleTestCase):
self.check('---\n' self.check('---\n'
'array: [ a, b]\n', conf, problem=(2, 11)) 'array: [ a, b]\n', conf, problem=(2, 11))
conf = 'brackets: {max-spaces-inside: 1, min-spaces-inside: 1}' conf = ('brackets:\n'
' max-spaces-inside: 1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: [a, b, c ]\n', conf, problem=(2, 9)) 'array: [a, b, c ]\n', conf, problem=(2, 9))
conf = 'brackets: {max-spaces-inside: 2, min-spaces-inside: 0}' conf = ('brackets:\n'
' max-spaces-inside: 2\n'
' min-spaces-inside: 0\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n' self.check('---\n'
'array: [a, b, c ]\n', conf) 'array: [a, b, c ]\n', conf)
self.check('---\n' self.check('---\n'
'array: [ a, b, c ]\n', conf) 'array: [ a, b, c ]\n', conf)
self.check('---\n' self.check('---\n'
'array: [ a, b, c ]\n', conf, problem=(2, 11)) 'array: [ a, b, c ]\n', conf, problem=(2, 11))
def test_min_spaces_empty(self):
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 0\n'
' min-spaces-inside-empty: 0\n')
self.check('---\n'
'array: []\n', conf)
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: []\n', conf, problem=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: -1\n'
' min-spaces-inside-empty: 3\n')
self.check('---\n'
'array: []\n', conf, problem=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)
def test_max_spaces_empty(self):
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 0\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [ ]\n', conf, problem=(2, 9))
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [ ]\n', conf)
self.check('---\n'
'array: [ ]\n', conf, problem=(2, 10))
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 3\n'
' min-spaces-inside-empty: -1\n')
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [ ]\n', conf)
self.check('---\n'
'array: [ ]\n', conf, problem=(2, 12))
def test_min_and_max_spaces_empty(self):
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 2\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: []\n', conf, problem=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)
self.check('---\n'
'array: [ ]\n', conf)
self.check('---\n'
'array: [ ]\n', conf, problem=(2, 11))
def test_mixed_empty_nonempty(self):
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: 0\n'
' min-spaces-inside-empty: 0\n')
self.check('---\n'
'array: [ a, b ]\n', conf)
self.check('---\n'
'array: [a, b]\n', conf,
problem1=(2, 9), problem2=(2, 13))
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [ ]\n', conf,
problem1=(2, 9))
conf = ('brackets:\n'
' max-spaces-inside: 0\n'
' min-spaces-inside: -1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: [ a, b ]\n', conf,
problem1=(2, 9), problem2=(2, 14))
self.check('---\n'
'array: [a, b]\n', conf)
self.check('---\n'
'array: []\n', conf,
problem1=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)
conf = ('brackets:\n'
' max-spaces-inside: 2\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: [ a, b ]\n', conf)
self.check('---\n'
'array: [a, b ]\n', conf,
problem1=(2, 9), problem2=(2, 15))
self.check('---\n'
'array: []\n', conf,
problem1=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)
self.check('---\n'
'array: [ ]\n', conf,
problem1=(2, 11))
conf = ('brackets:\n'
' max-spaces-inside: 1\n'
' min-spaces-inside: 1\n'
' max-spaces-inside-empty: 1\n'
' min-spaces-inside-empty: 1\n')
self.check('---\n'
'array: [ a, b ]\n', conf)
self.check('---\n'
'array: [a, b]\n', conf,
problem1=(2, 9), problem2=(2, 13))
self.check('---\n'
'array: []\n', conf,
problem1=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)

@ -43,7 +43,7 @@ class CommentsTestCase(RuleTestCase):
def test_starting_space(self): def test_starting_space(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: yes\n' ' require-starting-space: true\n'
' min-spaces-from-content: -1\n' ' min-spaces-from-content: -1\n'
'comments-indentation: disable\n') 'comments-indentation: disable\n')
self.check('---\n' self.check('---\n'
@ -82,7 +82,7 @@ class CommentsTestCase(RuleTestCase):
def test_spaces_from_content(self): def test_spaces_from_content(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: no\n' ' require-starting-space: false\n'
' min-spaces-from-content: 2\n') ' min-spaces-from-content: 2\n')
self.check('---\n' self.check('---\n'
'# comment\n' '# comment\n'
@ -104,7 +104,7 @@ class CommentsTestCase(RuleTestCase):
def test_both(self): def test_both(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: yes\n' ' require-starting-space: true\n'
' min-spaces-from-content: 2\n' ' min-spaces-from-content: 2\n'
'comments-indentation: disable\n') 'comments-indentation: disable\n')
self.check('---\n' self.check('---\n'
@ -134,7 +134,7 @@ class CommentsTestCase(RuleTestCase):
def test_empty_comment(self): def test_empty_comment(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: yes\n' ' require-starting-space: true\n'
' min-spaces-from-content: 2\n') ' min-spaces-from-content: 2\n')
self.check('---\n' self.check('---\n'
'# This is paragraph 1.\n' '# This is paragraph 1.\n'
@ -146,13 +146,13 @@ class CommentsTestCase(RuleTestCase):
def test_first_line(self): def test_first_line(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: yes\n' ' require-starting-space: true\n'
' min-spaces-from-content: 2\n') ' min-spaces-from-content: 2\n')
self.check('# comment\n', conf) self.check('# comment\n', conf)
def test_last_line(self): def test_last_line(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: yes\n' ' require-starting-space: true\n'
' min-spaces-from-content: 2\n' ' min-spaces-from-content: 2\n'
'new-line-at-end-of-file: disable\n') 'new-line-at-end-of-file: disable\n')
self.check('# comment with no newline char:\n' self.check('# comment with no newline char:\n'
@ -160,7 +160,7 @@ class CommentsTestCase(RuleTestCase):
def test_multi_line_scalar(self): def test_multi_line_scalar(self):
conf = ('comments:\n' conf = ('comments:\n'
' require-starting-space: yes\n' ' require-starting-space: true\n'
' min-spaces-from-content: 2\n' ' min-spaces-from-content: 2\n'
'trailing-spaces: disable\n') 'trailing-spaces: disable\n')
self.check('---\n' self.check('---\n'

@ -31,7 +31,7 @@ class DocumentEndTestCase(RuleTestCase):
' document: end\n', conf) ' document: end\n', conf)
def test_required(self): def test_required(self):
conf = 'document-end: {present: yes}' conf = 'document-end: {present: true}'
self.check('', conf) self.check('', conf)
self.check('\n', conf) self.check('\n', conf)
self.check('---\n' self.check('---\n'
@ -43,7 +43,7 @@ class DocumentEndTestCase(RuleTestCase):
' document: end\n', conf, problem=(3, 1)) ' document: end\n', conf, problem=(3, 1))
def test_forbidden(self): def test_forbidden(self):
conf = 'document-end: {present: no}' conf = 'document-end: {present: false}'
self.check('---\n' self.check('---\n'
'with:\n' 'with:\n'
' document: end\n' ' document: end\n'
@ -53,7 +53,7 @@ class DocumentEndTestCase(RuleTestCase):
' document: end\n', conf) ' document: end\n', conf)
def test_multiple_documents(self): def test_multiple_documents(self):
conf = ('document-end: {present: yes}\n' conf = ('document-end: {present: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('---\n' self.check('---\n'
'first: document\n' 'first: document\n'

@ -28,7 +28,7 @@ class DocumentStartTestCase(RuleTestCase):
'key: val\n', conf) 'key: val\n', conf)
def test_required(self): def test_required(self):
conf = ('document-start: {present: yes}\n' conf = ('document-start: {present: true}\n'
'empty-lines: disable\n') 'empty-lines: disable\n')
self.check('', conf) self.check('', conf)
self.check('\n', conf) self.check('\n', conf)
@ -44,7 +44,7 @@ class DocumentStartTestCase(RuleTestCase):
'key: val\n', conf) 'key: val\n', conf)
def test_forbidden(self): def test_forbidden(self):
conf = ('document-start: {present: no}\n' conf = ('document-start: {present: false}\n'
'empty-lines: disable\n') 'empty-lines: disable\n')
self.check('', conf) self.check('', conf)
self.check('key: val\n', conf) self.check('key: val\n', conf)
@ -62,7 +62,7 @@ class DocumentStartTestCase(RuleTestCase):
'key: val\n', conf, problem=(2, 1)) 'key: val\n', conf, problem=(2, 1))
def test_multiple_documents(self): def test_multiple_documents(self):
conf = 'document-start: {present: yes}' conf = 'document-start: {present: true}'
self.check('---\n' self.check('---\n'
'first: document\n' 'first: document\n'
'...\n' '...\n'
@ -85,7 +85,7 @@ class DocumentStartTestCase(RuleTestCase):
'third: document\n', conf, problem=(4, 1, 'syntax')) 'third: document\n', conf, problem=(4, 1, 'syntax'))
def test_directives(self): def test_directives(self):
conf = 'document-start: {present: yes}' conf = 'document-start: {present: true}'
self.check('%YAML 1.2\n' self.check('%YAML 1.2\n'
'---\n' '---\n'
'doc: ument\n' 'doc: ument\n'

@ -549,7 +549,7 @@ class IndentationTestCase(RuleTestCase):
'...\n', conf) '...\n', conf)
def test_one_space(self): def test_one_space(self):
conf = 'indentation: {spaces: 1, indent-sequences: no}' conf = 'indentation: {spaces: 1, indent-sequences: false}'
self.check('---\n' self.check('---\n'
'object:\n' 'object:\n'
' k1:\n' ' k1:\n'
@ -562,7 +562,7 @@ class IndentationTestCase(RuleTestCase):
' - name: Linux\n' ' - name: Linux\n'
' date: 1991\n' ' date: 1991\n'
'...\n', conf) '...\n', conf)
conf = 'indentation: {spaces: 1, indent-sequences: yes}' conf = 'indentation: {spaces: 1, indent-sequences: true}'
self.check('---\n' self.check('---\n'
'object:\n' 'object:\n'
' k1:\n' ' k1:\n'
@ -577,7 +577,7 @@ class IndentationTestCase(RuleTestCase):
'...\n', conf) '...\n', conf)
def test_two_spaces(self): def test_two_spaces(self):
conf = 'indentation: {spaces: 2, indent-sequences: no}' conf = 'indentation: {spaces: 2, indent-sequences: false}'
self.check('---\n' self.check('---\n'
'object:\n' 'object:\n'
' k1:\n' ' k1:\n'
@ -590,7 +590,7 @@ class IndentationTestCase(RuleTestCase):
' - name: Linux\n' ' - name: Linux\n'
' date: 1991\n' ' date: 1991\n'
'...\n', conf) '...\n', conf)
conf = 'indentation: {spaces: 2, indent-sequences: yes}' conf = 'indentation: {spaces: 2, indent-sequences: true}'
self.check('---\n' self.check('---\n'
'object:\n' 'object:\n'
' k1:\n' ' k1:\n'
@ -605,7 +605,7 @@ class IndentationTestCase(RuleTestCase):
'...\n', conf) '...\n', conf)
def test_three_spaces(self): def test_three_spaces(self):
conf = 'indentation: {spaces: 3, indent-sequences: no}' conf = 'indentation: {spaces: 3, indent-sequences: false}'
self.check('---\n' self.check('---\n'
'object:\n' 'object:\n'
' k1:\n' ' k1:\n'
@ -618,7 +618,7 @@ class IndentationTestCase(RuleTestCase):
' - name: Linux\n' ' - name: Linux\n'
' date: 1991\n' ' date: 1991\n'
'...\n', conf) '...\n', conf)
conf = 'indentation: {spaces: 3, indent-sequences: yes}' conf = 'indentation: {spaces: 3, indent-sequences: true}'
self.check('---\n' self.check('---\n'
'object:\n' 'object:\n'
' k1:\n' ' k1:\n'
@ -632,7 +632,7 @@ class IndentationTestCase(RuleTestCase):
' date: 1991\n' ' date: 1991\n'
'...\n', conf) '...\n', conf)
def test_consistent(self): def test_consistent_spaces(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' indent-sequences: whatever}\n' ' indent-sequences: whatever}\n'
'document-start: disable\n') 'document-start: disable\n')
@ -713,6 +713,142 @@ class IndentationTestCase(RuleTestCase):
'- b\n' '- b\n'
'- c\n', conf) '- c\n', conf)
def test_consistent_spaces_and_indent_sequences(self):
conf = 'indentation: {spaces: consistent, indent-sequences: true}'
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(3, 1))
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(7, 5))
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf, problem1=(7, 1))
conf = 'indentation: {spaces: consistent, indent-sequences: false}'
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(7, 5))
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(7, 3))
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf, problem1=(3, 3))
conf = ('indentation: {spaces: consistent,\n'
' indent-sequences: consistent}')
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(7, 5))
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf, problem1=(7, 1))
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf)
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(7, 5))
conf = 'indentation: {spaces: consistent, indent-sequences: whatever}'
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf)
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf)
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf)
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem1=(7, 5))
def test_indent_sequences_whatever(self): def test_indent_sequences_whatever(self):
conf = 'indentation: {spaces: 4, indent-sequences: whatever}' conf = 'indentation: {spaces: 4, indent-sequences: whatever}'
self.check('---\n' self.check('---\n'
@ -1130,7 +1266,7 @@ class IndentationTestCase(RuleTestCase):
problem=(2, 3)) problem=(2, 3))
def test_multi_lines(self): def test_multi_lines(self):
conf = 'indentation: {spaces: consistent, indent-sequences: yes}' conf = 'indentation: {spaces: consistent, indent-sequences: true}'
self.check('---\n' self.check('---\n'
'long_string: >\n' 'long_string: >\n'
' bla bla blah\n' ' bla bla blah\n'
@ -1438,7 +1574,7 @@ class IndentationTestCase(RuleTestCase):
'- !!map # Block collection\n' '- !!map # Block collection\n'
' foo: bar\n', conf) ' foo: bar\n', conf)
conf = 'indentation: {spaces: consistent, indent-sequences: no}' conf = 'indentation: {spaces: consistent, indent-sequences: false}'
self.check('---\n' self.check('---\n'
'sequence: !!seq\n' 'sequence: !!seq\n'
'- entry\n' '- entry\n'
@ -1505,7 +1641,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_basics_plain(self): def test_basics_plain(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n' ' check-multi-line-strings: false}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('multi\n' self.check('multi\n'
'line\n', conf) 'line\n', conf)
@ -1534,7 +1670,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_check_multi_line_plain(self): def test_check_multi_line_plain(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('multi\n' self.check('multi\n'
' line\n', conf, problem=(2, 2)) ' line\n', conf, problem=(2, 2))
@ -1557,7 +1693,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_basics_quoted(self): def test_basics_quoted(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n' ' check-multi-line-strings: false}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('"multi\n' self.check('"multi\n'
' line"\n', conf) ' line"\n', conf)
@ -1588,7 +1724,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_check_multi_line_quoted(self): def test_check_multi_line_quoted(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('"multi\n' self.check('"multi\n'
'line"\n', conf, problem=(2, 1)) 'line"\n', conf, problem=(2, 1))
@ -1644,7 +1780,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_basics_folded_style(self): def test_basics_folded_style(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n' ' check-multi-line-strings: false}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('>\n' self.check('>\n'
' multi\n' ' multi\n'
@ -1682,7 +1818,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_check_multi_line_folded_style(self): def test_check_multi_line_folded_style(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('>\n' self.check('>\n'
' multi\n' ' multi\n'
@ -1723,7 +1859,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_basics_literal_style(self): def test_basics_literal_style(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n' ' check-multi-line-strings: false}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('|\n' self.check('|\n'
' multi\n' ' multi\n'
@ -1761,7 +1897,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_check_multi_line_literal_style(self): def test_check_multi_line_literal_style(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('|\n' self.check('|\n'
' multi\n' ' multi\n'
@ -1805,7 +1941,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_paragraph_plain(self): def test_paragraph_plain(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('- long text: very "long"\n' self.check('- long text: very "long"\n'
' \'string\' with\n' ' \'string\' with\n'
@ -1827,7 +1963,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_paragraph_double_quoted(self): def test_paragraph_double_quoted(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('- long text: "very \\"long\\"\n' self.check('- long text: "very \\"long\\"\n'
' \'string\' with\n' ' \'string\' with\n'
@ -1855,7 +1991,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_paragraph_single_quoted(self): def test_paragraph_single_quoted(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('- long text: \'very "long"\n' self.check('- long text: \'very "long"\n'
' \'\'string\'\' with\n' ' \'\'string\'\' with\n'
@ -1883,7 +2019,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_paragraph_folded(self): def test_paragraph_folded(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('- long text: >\n' self.check('- long text: >\n'
' very "long"\n' ' very "long"\n'
@ -1901,7 +2037,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_paragraph_literal(self): def test_paragraph_literal(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('- long text: |\n' self.check('- long text: |\n'
' very "long"\n' ' very "long"\n'
@ -1919,7 +2055,7 @@ class ScalarIndentationTestCase(RuleTestCase):
def test_consistent(self): def test_consistent(self):
conf = ('indentation: {spaces: consistent,\n' conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n' ' check-multi-line-strings: true}\n'
'document-start: disable\n') 'document-start: disable\n')
self.check('multi\n' self.check('multi\n'
'line\n', conf) 'line\n', conf)

@ -66,7 +66,7 @@ class LineLengthTestCase(RuleTestCase):
self.check('---\n' + 81 * ' ' + '\n', conf, problem=(2, 81)) self.check('---\n' + 81 * ' ' + '\n', conf, problem=(2, 81))
def test_non_breakable_word(self): def test_non_breakable_word(self):
conf = 'line-length: {max: 20, allow-non-breakable-words: yes}' conf = 'line-length: {max: 20, allow-non-breakable-words: true}'
self.check('---\n' + 30 * 'A' + '\n', conf) self.check('---\n' + 30 * 'A' + '\n', conf)
self.check('---\n' self.check('---\n'
'this:\n' 'this:\n'
@ -91,7 +91,7 @@ class LineLengthTestCase(RuleTestCase):
'long_line: http://localhost/very/very/long/url\n', conf, 'long_line: http://localhost/very/very/long/url\n', conf,
problem=(2, 21)) problem=(2, 21))
conf = 'line-length: {max: 20, allow-non-breakable-words: no}' conf = 'line-length: {max: 20, allow-non-breakable-words: false}'
self.check('---\n' + 30 * 'A' + '\n', conf, problem=(2, 21)) self.check('---\n' + 30 * 'A' + '\n', conf, problem=(2, 21))
self.check('---\n' self.check('---\n'
'this:\n' 'this:\n'
@ -116,7 +116,7 @@ class LineLengthTestCase(RuleTestCase):
'long_line: http://localhost/very/very/long/url\n' 'long_line: http://localhost/very/very/long/url\n'
'...\n', conf, problem=(2, 21)) '...\n', conf, problem=(2, 21))
conf = ('line-length: {max: 20, allow-non-breakable-words: yes}\n' conf = ('line-length: {max: 20, allow-non-breakable-words: true}\n'
'trailing-spaces: disable') 'trailing-spaces: disable')
self.check('---\n' self.check('---\n'
'loooooooooong+word+and+some+space+at+the+end \n', 'loooooooooong+word+and+some+space+at+the+end \n',
@ -124,7 +124,7 @@ class LineLengthTestCase(RuleTestCase):
def test_non_breakable_inline_mappings(self): def test_non_breakable_inline_mappings(self):
conf = 'line-length: {max: 20, ' \ conf = 'line-length: {max: 20, ' \
'allow-non-breakable-inline-mappings: yes}' 'allow-non-breakable-inline-mappings: true}'
self.check('---\n' self.check('---\n'
'long_line: http://localhost/very/very/long/url\n' 'long_line: http://localhost/very/very/long/url\n'
'long line: http://localhost/very/very/long/url\n', conf) 'long line: http://localhost/very/very/long/url\n', conf)
@ -137,7 +137,7 @@ class LineLengthTestCase(RuleTestCase):
conf, problem1=(2, 21), problem2=(3, 21)) conf, problem1=(2, 21), problem2=(3, 21))
conf = ('line-length: {max: 20,' conf = ('line-length: {max: 20,'
' allow-non-breakable-inline-mappings: yes}\n' ' allow-non-breakable-inline-mappings: true}\n'
'trailing-spaces: disable') 'trailing-spaces: disable')
self.check('---\n' self.check('---\n'
'long_line: and+some+space+at+the+end \n', 'long_line: and+some+space+at+the+end \n',
@ -150,7 +150,7 @@ class LineLengthTestCase(RuleTestCase):
conf, problem=(2, 21)) conf, problem=(2, 21))
# See https://github.com/adrienverge/yamllint/issues/21 # See https://github.com/adrienverge/yamllint/issues/21
conf = 'line-length: {allow-non-breakable-inline-mappings: yes}' conf = 'line-length: {allow-non-breakable-inline-mappings: true}'
self.check('---\n' self.check('---\n'
'content: |\n' 'content: |\n'
' {% this line is' + 99 * ' really' + ' long %}\n', ' {% this line is' + 99 * ' really' + ' long %}\n',

@ -23,61 +23,59 @@ import locale
import os import os
import pty import pty
import shutil import shutil
import tempfile
import unittest
import sys import sys
try:
assert sys.version_info >= (2, 7)
import unittest
except:
import unittest2 as unittest
from yamllint import cli from yamllint import cli
from tests.common import build_temp_workspace
@unittest.skipIf(sys.version_info < (2, 7), 'Python 2.6 not supported')
class CommandLineTestCase(unittest.TestCase): class CommandLineTestCase(unittest.TestCase):
def setUp(self): @classmethod
self.wd = tempfile.mkdtemp(prefix='yamllint-tests-') def setUpClass(cls):
super(CommandLineTestCase, cls).setUpClass()
# .yaml file at root
with open(os.path.join(self.wd, 'a.yaml'), 'w') as f: cls.wd = build_temp_workspace({
f.write('---\n' # .yaml file at root
'- 1 \n' 'a.yaml': '---\n'
'- 2') '- 1 \n'
'- 2',
# .yml file at root # file with only one warning
open(os.path.join(self.wd, 'empty.yml'), 'w').close() 'warn.yaml': 'key: value\n',
# .yml file at root
# file in dir 'empty.yml': '',
os.mkdir(os.path.join(self.wd, 'sub')) # file in dir
with open(os.path.join(self.wd, 'sub', 'ok.yaml'), 'w') as f: 'sub/ok.yaml': '---\n'
f.write('---\n' 'key: value\n',
'key: value\n') # file in very nested dir
's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml': '---\n'
# file in very nested dir 'key: value\n'
dir = self.wd 'key: other value\n',
for i in range(15): # empty dir
dir = os.path.join(dir, 's') 'empty-dir': [],
os.mkdir(dir) # non-YAML file
with open(os.path.join(dir, 'file.yaml'), 'w') as f: 'no-yaml.json': '---\n'
f.write('---\n' 'key: value\n',
'key: value\n' # non-ASCII chars
'key: other value\n') 'non-ascii/utf-8': (
u'---\n'
# empty dir u'- hétérogénéité\n'
os.mkdir(os.path.join(self.wd, 'empty-dir')) u'# 19.99 €\n'
u'- お早う御座います。\n'
# non-YAML file u'# الأَبْجَدِيَّة العَرَبِيَّة\n').encode('utf-8'),
with open(os.path.join(self.wd, 'no-yaml.json'), 'w') as f: })
f.write('---\n'
'key: value\n') @classmethod
def tearDownClass(cls):
# non-ASCII chars super(CommandLineTestCase, cls).tearDownClass()
os.mkdir(os.path.join(self.wd, 'non-ascii'))
with open(os.path.join(self.wd, 'non-ascii', 'utf-8'), 'wb') as f: shutil.rmtree(cls.wd)
f.write((u'---\n'
u'- hétérogénéité\n'
u'# 19.99 €\n'
u'- お早う御座います。\n'
u'# الأَبْجَدِيَّة العَرَبِيَّة\n').encode('utf-8'))
def tearDown(self):
shutil.rmtree(self.wd)
def test_find_files_recursively(self): def test_find_files_recursively(self):
self.assertEqual( self.assertEqual(
@ -85,7 +83,8 @@ class CommandLineTestCase(unittest.TestCase):
[os.path.join(self.wd, 'a.yaml'), [os.path.join(self.wd, 'a.yaml'),
os.path.join(self.wd, 'empty.yml'), os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'),
os.path.join(self.wd, 'sub/ok.yaml')], os.path.join(self.wd, 'sub/ok.yaml'),
os.path.join(self.wd, 'warn.yaml')],
) )
items = [os.path.join(self.wd, 'sub/ok.yaml'), items = [os.path.join(self.wd, 'sub/ok.yaml'),
@ -140,8 +139,11 @@ class CommandLineTestCase(unittest.TestCase):
out, err = sys.stdout.getvalue(), sys.stderr.getvalue() out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '') self.assertEqual(out, '')
self.assertRegexpMatches(err, r'^Options --config-file and ' self.assertRegexpMatches(
r'--config-data cannot be used') err.splitlines()[-1],
r'^yamllint: error: argument -d\/--config-data: '
r'not allowed with argument -c\/--config-file$'
)
def test_run_with_bad_config(self): def test_run_with_bad_config(self):
sys.stdout, sys.stderr = StringIO(), StringIO() sys.stdout, sys.stderr = StringIO(), StringIO()
@ -247,6 +249,24 @@ class CommandLineTestCase(unittest.TestCase):
'(new-line-at-end-of-file)\n') % (file, file)) '(new-line-at-end-of-file)\n') % (file, file))
self.assertEqual(err, '') self.assertEqual(err, '')
def test_run_one_warning(self):
file = os.path.join(self.wd, 'warn.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-f', 'parsable', file))
self.assertEqual(ctx.exception.code, 0)
def test_run_warning_in_strict_mode(self):
file = os.path.join(self.wd, 'warn.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-f', 'parsable', '--strict', file))
self.assertEqual(ctx.exception.code, 2)
def test_run_one_ok_file(self): def test_run_one_ok_file(self):
file = os.path.join(self.wd, 'sub', 'ok.yaml') file = os.path.join(self.wd, 'sub', 'ok.yaml')

@ -14,10 +14,24 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
import os
import shutil
import sys
try:
assert sys.version_info >= (2, 7)
import unittest
except:
import unittest2 as unittest
from yamllint import cli
from yamllint import config from yamllint import config
from tests.common import build_temp_workspace
class SimpleConfigTestCase(unittest.TestCase): class SimpleConfigTestCase(unittest.TestCase):
def test_parse_config(self): def test_parse_config(self):
@ -30,7 +44,7 @@ class SimpleConfigTestCase(unittest.TestCase):
self.assertEqual(new.rules['colons']['max-spaces-before'], 0) self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
self.assertEqual(new.rules['colons']['max-spaces-after'], 1) self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
self.assertEqual(len(new.enabled_rules()), 1) self.assertEqual(len(new.enabled_rules(None)), 1)
def test_invalid_conf(self): def test_invalid_conf(self):
with self.assertRaises(config.YamlLintConfigError): with self.assertRaises(config.YamlLintConfigError):
@ -62,6 +76,45 @@ class SimpleConfigTestCase(unittest.TestCase):
' max-spaces-after: 1\n' ' max-spaces-after: 1\n'
' abcdef: yes\n') ' abcdef: yes\n')
def test_yes_no_for_booleans(self):
c = config.YamlLintConfig('rules:\n'
' indentation:\n'
' spaces: 2\n'
' indent-sequences: true\n'
' check-multi-line-strings: false\n')
self.assertEqual(c.rules['indentation']['indent-sequences'], True)
self.assertEqual(c.rules['indentation']['check-multi-line-strings'],
False)
c = config.YamlLintConfig('rules:\n'
' indentation:\n'
' spaces: 2\n'
' indent-sequences: yes\n'
' check-multi-line-strings: false\n')
self.assertEqual(c.rules['indentation']['indent-sequences'], True)
self.assertEqual(c.rules['indentation']['check-multi-line-strings'],
False)
c = config.YamlLintConfig('rules:\n'
' indentation:\n'
' spaces: 2\n'
' indent-sequences: whatever\n'
' check-multi-line-strings: false\n')
self.assertEqual(c.rules['indentation']['indent-sequences'],
'whatever')
self.assertEqual(c.rules['indentation']['check-multi-line-strings'],
False)
with self.assertRaisesRegexp(
config.YamlLintConfigError,
'invalid config: option "indent-sequences" of "indentation" '
'should be in '):
c = config.YamlLintConfig('rules:\n'
' indentation:\n'
' spaces: 2\n'
' indent-sequences: YES!\n'
' check-multi-line-strings: false\n')
def test_validate_rule_conf(self): def test_validate_rule_conf(self):
class Rule(object): class Rule(object):
ID = 'fake' ID = 'fake'
@ -131,7 +184,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(new.rules['colons']['max-spaces-after'], 1) self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2) self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 2) self.assertEqual(len(new.enabled_rules(None)), 2)
def test_extend_remove_rule(self): def test_extend_remove_rule(self):
old = config.YamlLintConfig('rules:\n' old = config.YamlLintConfig('rules:\n'
@ -148,7 +201,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(new.rules['colons'], False) self.assertEqual(new.rules['colons'], False)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2) self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 1) self.assertEqual(len(new.enabled_rules(None)), 1)
def test_extend_edit_rule(self): def test_extend_edit_rule(self):
old = config.YamlLintConfig('rules:\n' old = config.YamlLintConfig('rules:\n'
@ -168,7 +221,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(new.rules['colons']['max-spaces-after'], 4) self.assertEqual(new.rules['colons']['max-spaces-after'], 4)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2) self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 2) self.assertEqual(len(new.enabled_rules(None)), 2)
def test_extend_reenable_rule(self): def test_extend_reenable_rule(self):
old = config.YamlLintConfig('rules:\n' old = config.YamlLintConfig('rules:\n'
@ -186,7 +239,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(new.rules['colons']['max-spaces-after'], 1) self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2) self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 2) self.assertEqual(len(new.enabled_rules(None)), 2)
class ExtendedLibraryConfigTestCase(unittest.TestCase): class ExtendedLibraryConfigTestCase(unittest.TestCase):
@ -231,3 +284,94 @@ class ExtendedLibraryConfigTestCase(unittest.TestCase):
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys())) self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
for rule in new.rules: for rule in new.rules:
self.assertEqual(new.rules[rule], old.rules[rule]) self.assertEqual(new.rules[rule], old.rules[rule])
class IgnorePathConfigTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
super(IgnorePathConfigTestCase, cls).setUpClass()
bad_yaml = ('---\n'
'- key: val1\n'
' key: val2\n'
'- trailing space \n'
'- lonely hyphen\n')
cls.wd = build_temp_workspace({
'bin/file.lint-me-anyway.yaml': bad_yaml,
'bin/file.yaml': bad_yaml,
'file-at-root.yaml': bad_yaml,
'file.dont-lint-me.yaml': bad_yaml,
'ign-dup/file.yaml': bad_yaml,
'ign-dup/sub/dir/file.yaml': bad_yaml,
'ign-trail/file.yaml': bad_yaml,
'include/ign-dup/sub/dir/file.yaml': bad_yaml,
's/s/ign-trail/file.yaml': bad_yaml,
's/s/ign-trail/s/s/file.yaml': bad_yaml,
's/s/ign-trail/s/s/file2.lint-me-anyway.yaml': bad_yaml,
'.yamllint': 'ignore: |\n'
' *.dont-lint-me.yaml\n'
' /bin/\n'
' !/bin/*.lint-me-anyway.yaml\n'
'\n'
'extends: default\n'
'\n'
'rules:\n'
' key-duplicates:\n'
' ignore: |\n'
' /ign-dup\n'
' trailing-spaces:\n'
' ignore: |\n'
' ign-trail\n'
' !*.lint-me-anyway.yaml\n',
})
cls.backup_wd = os.getcwd()
os.chdir(cls.wd)
@classmethod
def tearDownClass(cls):
super(IgnorePathConfigTestCase, cls).tearDownClass()
os.chdir(cls.backup_wd)
shutil.rmtree(cls.wd)
@unittest.skipIf(sys.version_info < (2, 7), 'Python 2.6 not supported')
def test_run_with_ignored_path(self):
sys.stdout = StringIO()
with self.assertRaises(SystemExit):
cli.run(('-f', 'parsable', '.'))
out = sys.stdout.getvalue()
out = '\n'.join(sorted(out.splitlines()))
keydup = '[error] duplication of key "key" in mapping (key-duplicates)'
trailing = '[error] trailing spaces (trailing-spaces)'
hyphen = '[error] too many spaces after hyphen (hyphens)'
self.assertEqual(out, '\n'.join((
'./bin/file.lint-me-anyway.yaml:3:3: ' + keydup,
'./bin/file.lint-me-anyway.yaml:4:17: ' + trailing,
'./bin/file.lint-me-anyway.yaml:5:5: ' + hyphen,
'./file-at-root.yaml:3:3: ' + keydup,
'./file-at-root.yaml:4:17: ' + trailing,
'./file-at-root.yaml:5:5: ' + hyphen,
'./ign-dup/file.yaml:4:17: ' + trailing,
'./ign-dup/file.yaml:5:5: ' + hyphen,
'./ign-dup/sub/dir/file.yaml:4:17: ' + trailing,
'./ign-dup/sub/dir/file.yaml:5:5: ' + hyphen,
'./ign-trail/file.yaml:3:3: ' + keydup,
'./ign-trail/file.yaml:5:5: ' + hyphen,
'./include/ign-dup/sub/dir/file.yaml:3:3: ' + keydup,
'./include/ign-dup/sub/dir/file.yaml:4:17: ' + trailing,
'./include/ign-dup/sub/dir/file.yaml:5:5: ' + hyphen,
'./s/s/ign-trail/file.yaml:3:3: ' + keydup,
'./s/s/ign-trail/file.yaml:5:5: ' + hyphen,
'./s/s/ign-trail/s/s/file.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file.yaml:5:5: ' + hyphen,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen,
)))

@ -15,8 +15,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import io import io
import sys
import unittest try:
assert sys.version_info >= (2, 7)
import unittest
except:
import unittest2 as unittest
from yamllint.config import YamlLintConfig from yamllint.config import YamlLintConfig
from yamllint import linter from yamllint import linter

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017 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 subprocess
import tempfile
import sys
try:
assert sys.version_info >= (2, 7)
import unittest
except:
import unittest2 as unittest
@unittest.skipIf(sys.version_info < (2, 7), 'Python 2.6 not supported')
class ModuleTestCase(unittest.TestCase):
def setUp(self):
self.wd = tempfile.mkdtemp(prefix='yamllint-tests-')
# file with only one warning
with open(os.path.join(self.wd, 'warn.yaml'), 'w') as f:
f.write('key: value\n')
# file in dir
os.mkdir(os.path.join(self.wd, 'sub'))
with open(os.path.join(self.wd, 'sub', 'nok.yaml'), 'w') as f:
f.write('---\n'
'list: [ 1, 1, 2, 3, 5, 8] \n')
def tearDown(self):
shutil.rmtree(self.wd)
def test_run_module_no_args(self):
with self.assertRaises(subprocess.CalledProcessError) as ctx:
subprocess.check_output(['python', '-m', 'yamllint'],
stderr=subprocess.STDOUT)
self.assertEqual(ctx.exception.returncode, 2)
self.assertRegexpMatches(ctx.exception.output.decode(),
r'^usage: yamllint')
def test_run_module_on_bad_dir(self):
with self.assertRaises(subprocess.CalledProcessError) as ctx:
subprocess.check_output(['python', '-m', 'yamllint',
'/does/not/exist'],
stderr=subprocess.STDOUT)
self.assertRegexpMatches(ctx.exception.output.decode(),
r'No such file or directory')
def test_run_module_on_file(self):
out = subprocess.check_output(
['python', '-m', 'yamllint', os.path.join(self.wd, 'warn.yaml')])
lines = out.decode().splitlines()
self.assertIn('/warn.yaml', lines[0])
self.assertEqual('\n'.join(lines[1:]),
' 1:1 warning missing document start "---"'
' (document-start)\n')
def test_run_module_on_dir(self):
with self.assertRaises(subprocess.CalledProcessError) as ctx:
subprocess.check_output(['python', '-m', 'yamllint', self.wd])
self.assertEqual(ctx.exception.returncode, 1)
files = ctx.exception.output.decode().split('\n\n')
self.assertIn(
'/warn.yaml\n'
' 1:1 warning missing document start "---"'
' (document-start)',
files[0])
self.assertIn(
'/sub/nok.yaml\n'
' 2:9 error too many spaces inside brackets'
' (brackets)\n'
' 2:27 error trailing spaces (trailing-spaces)',
files[1])

@ -14,7 +14,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest import sys
try:
assert sys.version_info >= (2, 7)
import unittest
except:
import unittest2 as unittest
import yaml import yaml

@ -48,6 +48,7 @@ from tests.common import RuleTestCase
class SpecificationTestCase(RuleTestCase): class SpecificationTestCase(RuleTestCase):
rule_id = None rule_id = None
conf_general = ('document-start: disable\n' conf_general = ('document-start: disable\n'
'comments: {min-spaces-from-content: 1}\n' 'comments: {min-spaces-from-content: 1}\n'
'braces: {min-spaces-inside: 1, max-spaces-inside: 1}\n' 'braces: {min-spaces-inside: 1, max-spaces-inside: 1}\n'
@ -66,7 +67,7 @@ conf_overrides = {
'example-2.18': ('empty-lines: {max-end: 1}\n'), 'example-2.18': ('empty-lines: {max-end: 1}\n'),
'example-2.19': ('empty-lines: {max-end: 1}\n'), 'example-2.19': ('empty-lines: {max-end: 1}\n'),
'example-2.28': ('empty-lines: {max-end: 3}\n'), 'example-2.28': ('empty-lines: {max-end: 3}\n'),
'example-5.3': ('indentation: {indent-sequences: no}\n' 'example-5.3': ('indentation: {indent-sequences: false}\n'
'colons: {max-spaces-before: 1}\n'), 'colons: {max-spaces-before: 1}\n'),
'example-6.4': ('trailing-spaces: disable\n'), 'example-6.4': ('trailing-spaces: disable\n'),
'example-6.5': ('trailing-spaces: disable\n'), 'example-6.5': ('trailing-spaces: disable\n'),
@ -114,11 +115,11 @@ conf_overrides = {
'example-8.14': ('colons: {max-spaces-before: 1}\n'), 'example-8.14': ('colons: {max-spaces-before: 1}\n'),
'example-8.16': ('indentation: {spaces: 1}\n'), 'example-8.16': ('indentation: {spaces: 1}\n'),
'example-8.17': ('indentation: disable\n'), 'example-8.17': ('indentation: disable\n'),
'example-8.20': ('indentation: {indent-sequences: no}\n' 'example-8.20': ('indentation: {indent-sequences: false}\n'
'colons: {max-spaces-before: 1}\n'), 'colons: {max-spaces-before: 1}\n'),
'example-8.22': ('indentation: disable\n'), 'example-8.22': ('indentation: disable\n'),
'example-10.1': ('colons: {max-spaces-before: 2}\n'), 'example-10.1': ('colons: {max-spaces-before: 2}\n'),
'example-10.2': ('indentation: {indent-sequences: no}\n'), 'example-10.2': ('indentation: {indent-sequences: false}\n'),
'example-10.8': ('truthy: disable\n'), 'example-10.8': ('truthy: disable\n'),
'example-10.9': ('truthy: disable\n'), 'example-10.9': ('truthy: disable\n'),
} }
@ -133,6 +134,7 @@ def _gen_test(buffer, conf):
self.check(buffer, conf) self.check(buffer, conf)
return test return test
# The following tests are blacklisted (i.e. will not be checked against # The following tests are blacklisted (i.e. will not be checked against
# yamllint), because pyyaml is currently not able to parse the contents # yamllint), because pyyaml is currently not able to parse the contents
# (using yaml.parse()). # (using yaml.parse()).

@ -22,7 +22,7 @@ indentation, etc."""
APP_NAME = 'yamllint' APP_NAME = 'yamllint'
APP_VERSION = '1.5.0' APP_VERSION = '1.8.1'
APP_DESCRIPTION = __doc__ APP_DESCRIPTION = __doc__
__author__ = u'Adrien Vergé' __author__ = u'Adrien Vergé'

@ -0,0 +1,4 @@
from yamllint.cli import run
if __name__ == '__main__':
run()

@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function from __future__ import print_function
import os.path import os.path
import sys import sys
@ -22,6 +23,7 @@ import argparse
from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION
from yamllint.config import YamlLintConfig, YamlLintConfigError from yamllint.config import YamlLintConfig, YamlLintConfigError
from yamllint.linter import PROBLEM_LEVELS
from yamllint import linter from yamllint import linter
@ -77,14 +79,20 @@ def run(argv=None):
description=APP_DESCRIPTION) description=APP_DESCRIPTION)
parser.add_argument('files', metavar='FILE_OR_DIR', nargs='+', parser.add_argument('files', metavar='FILE_OR_DIR', nargs='+',
help='files to check') help='files to check')
parser.add_argument('-c', '--config-file', dest='config_file', config_group = parser.add_mutually_exclusive_group()
action='store', help='path to a custom configuration') config_group.add_argument('-c', '--config-file', dest='config_file',
parser.add_argument('-d', '--config-data', dest='config_data', action='store',
action='store', help='path to a custom configuration')
help='custom configuration (as YAML source)') config_group.add_argument('-d', '--config-data', dest='config_data',
action='store',
help='custom configuration (as YAML source)')
parser.add_argument('-f', '--format', parser.add_argument('-f', '--format',
choices=('parsable', 'standard'), default='standard', choices=('parsable', 'standard'), default='standard',
help='format for parsing output') help='format for parsing output')
parser.add_argument('-s', '--strict',
action='store_true',
help='return non-zero exit code on warnings '
'as well as errors')
parser.add_argument('-v', '--version', action='version', parser.add_argument('-v', '--version', action='version',
version='%s %s' % (APP_NAME, APP_VERSION)) version='%s %s' % (APP_NAME, APP_VERSION))
@ -92,11 +100,6 @@ def run(argv=None):
args = parser.parse_args(argv) args = parser.parse_args(argv)
if args.config_file is not None and args.config_data is not None:
print('Options --config-file and --config-data cannot be used '
'simultaneously.', file=sys.stderr)
sys.exit(-1)
# User-global config is supposed to be in ~/.config/yamllint/config # User-global config is supposed to be in ~/.config/yamllint/config
if 'XDG_CONFIG_HOME' in os.environ: if 'XDG_CONFIG_HOME' in os.environ:
user_global_config = os.path.join( user_global_config = os.path.join(
@ -121,13 +124,14 @@ def run(argv=None):
print(e, file=sys.stderr) print(e, file=sys.stderr)
sys.exit(-1) sys.exit(-1)
return_code = 0 max_level = 0
for file in find_files_recursively(args.files): for file in find_files_recursively(args.files):
filepath = file[2:] if file.startswith('./') else file
try: try:
first = True first = True
with open(file) as f: with open(file) as f:
for problem in linter.run(f, conf): for problem in linter.run(f, conf, filepath):
if args.format == 'parsable': if args.format == 'parsable':
print(Format.parsable(problem, file)) print(Format.parsable(problem, file))
elif sys.stdout.isatty(): elif sys.stdout.isatty():
@ -143,13 +147,19 @@ def run(argv=None):
print(Format.standard(problem, file)) print(Format.standard(problem, file))
if return_code == 0 and problem.level == 'error': max_level = max(max_level, PROBLEM_LEVELS[problem.level])
return_code = 1
if not first and args.format != 'parsable': if not first and args.format != 'parsable':
print('') print('')
except EnvironmentError as e: except EnvironmentError as e:
print(e, file=sys.stderr) print(e, file=sys.stderr)
return_code = -1 sys.exit(-1)
if max_level == PROBLEM_LEVELS['error']:
return_code = 1
elif max_level == PROBLEM_LEVELS['warning']:
return_code = 2 if args.strict else 0
else:
return_code = 0
sys.exit(return_code) sys.exit(return_code)

@ -4,9 +4,13 @@ rules:
braces: braces:
min-spaces-inside: 0 min-spaces-inside: 0
max-spaces-inside: 0 max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
brackets: brackets:
min-spaces-inside: 0 min-spaces-inside: 0
max-spaces-inside: 0 max-spaces-inside: 0
min-spaces-inside-empty: -1
max-spaces-inside-empty: -1
colons: colons:
max-spaces-before: 0 max-spaces-before: 0
max-spaces-after: 1 max-spaces-after: 1
@ -16,14 +20,14 @@ rules:
max-spaces-after: 1 max-spaces-after: 1
comments: comments:
level: warning level: warning
require-starting-space: yes require-starting-space: true
min-spaces-from-content: 2 min-spaces-from-content: 2
comments-indentation: comments-indentation:
level: warning level: warning
document-end: disable document-end: disable
document-start: document-start:
level: warning level: warning
present: yes present: true
empty-lines: empty-lines:
max: 2 max: 2
max-start: 0 max-start: 0
@ -32,13 +36,13 @@ rules:
max-spaces-after: 1 max-spaces-after: 1
indentation: indentation:
spaces: consistent spaces: consistent
indent-sequences: yes indent-sequences: true
check-multi-line-strings: no check-multi-line-strings: false
key-duplicates: enable key-duplicates: enable
line-length: line-length:
max: 80 max: 80
allow-non-breakable-words: yes allow-non-breakable-words: true
allow-non-breakable-inline-mappings: no allow-non-breakable-inline-mappings: false
new-line-at-end-of-file: enable new-line-at-end-of-file: enable
new-lines: new-lines:
type: unix type: unix

@ -25,5 +25,5 @@ rules:
indent-sequences: consistent indent-sequences: consistent
line-length: line-length:
level: warning level: warning
allow-non-breakable-inline-mappings: yes allow-non-breakable-inline-mappings: true
truthy: disable truthy: disable

@ -16,6 +16,7 @@
import os.path import os.path
import pathspec
import yaml import yaml
import yamllint.rules import yamllint.rules
@ -29,6 +30,8 @@ class YamlLintConfig(object):
def __init__(self, content=None, file=None): def __init__(self, content=None, file=None):
assert (content is None) ^ (file is None) assert (content is None) ^ (file is None)
self.ignore = None
if file is not None: if file is not None:
with open(file) as f: with open(file) as f:
content = f.read() content = f.read()
@ -36,9 +39,14 @@ class YamlLintConfig(object):
self.parse(content) self.parse(content)
self.validate() self.validate()
def enabled_rules(self): def is_file_ignored(self, filepath):
return self.ignore and self.ignore.match_file(filepath)
def enabled_rules(self, filepath):
return [yamllint.rules.get(id) for id, val in self.rules.items() return [yamllint.rules.get(id) for id, val in self.rules.items()
if val is not False] if val is not False and (
filepath is None or 'ignore' not in val or
not val['ignore'].match_file(filepath))]
def extend(self, base_config): def extend(self, base_config):
assert isinstance(base_config, YamlLintConfig) assert isinstance(base_config, YamlLintConfig)
@ -53,6 +61,9 @@ class YamlLintConfig(object):
self.rules = base_config.rules self.rules = base_config.rules
if base_config.ignore is not None:
self.ignore = base_config.ignore
def parse(self, raw_content): def parse(self, raw_content):
try: try:
conf = yaml.safe_load(raw_content) conf = yaml.safe_load(raw_content)
@ -73,6 +84,13 @@ class YamlLintConfig(object):
except Exception as e: except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e) raise YamlLintConfigError('invalid config: %s' % e)
if 'ignore' in conf:
if type(conf['ignore']) != str:
raise YamlLintConfigError(
'invalid config: ignore should be a list of patterns')
self.ignore = pathspec.PathSpec.from_lines(
'gitwildmatch', conf['ignore'].splitlines())
def validate(self): def validate(self):
for id in self.rules: for id in self.rules:
try: try:
@ -90,6 +108,14 @@ def validate_rule_conf(rule, conf):
conf = {} conf = {}
if type(conf) == dict: if type(conf) == dict:
if ('ignore' in conf and
type(conf['ignore']) != pathspec.pathspec.PathSpec):
if type(conf['ignore']) != str:
raise YamlLintConfigError(
'invalid config: ignore should be a list of patterns')
conf['ignore'] = pathspec.PathSpec.from_lines(
'gitwildmatch', conf['ignore'].splitlines())
if 'level' not in conf: if 'level' not in conf:
conf['level'] = 'error' conf['level'] = 'error'
elif conf['level'] not in ('error', 'warning'): elif conf['level'] not in ('error', 'warning'):
@ -98,7 +124,7 @@ def validate_rule_conf(rule, conf):
options = getattr(rule, 'CONF', {}) options = getattr(rule, 'CONF', {})
for optkey in conf: for optkey in conf:
if optkey == 'level': if optkey in ('ignore', 'level'):
continue continue
if optkey not in options: if optkey not in options:
raise YamlLintConfigError( raise YamlLintConfigError(

@ -21,6 +21,16 @@ import yaml
from yamllint import parser from yamllint import parser
PROBLEM_LEVELS = {
0: None,
1: 'warning',
2: 'error',
None: 0,
'warning': 1,
'error': 2,
}
class LintProblem(object): class LintProblem(object):
"""Represents a linting problem found by yamllint.""" """Represents a linting problem found by yamllint."""
def __init__(self, line, column, desc='<no description>', rule=None): def __init__(self, line, column, desc='<no description>', rule=None):
@ -53,8 +63,8 @@ class LintProblem(object):
return '%d:%d: %s' % (self.line, self.column, self.message) return '%d:%d: %s' % (self.line, self.column, self.message)
def get_costemic_problems(buffer, conf): def get_cosmetic_problems(buffer, conf, filepath):
rules = conf.enabled_rules() rules = conf.enabled_rules(filepath)
# Split token rules from line rules # Split token rules from line rules
token_rules = [r for r in rules if r.TYPE == 'token'] token_rules = [r for r in rules if r.TYPE == 'token']
@ -175,7 +185,7 @@ def get_syntax_error(buffer):
return problem return problem
def _run(buffer, conf): def _run(buffer, conf, filepath):
assert hasattr(buffer, '__getitem__'), \ assert hasattr(buffer, '__getitem__'), \
'_run() argument must be a buffer, not a stream' '_run() argument must be a buffer, not a stream'
@ -183,7 +193,7 @@ def _run(buffer, conf):
# right line # right line
syntax_error = get_syntax_error(buffer) syntax_error = get_syntax_error(buffer)
for problem in get_costemic_problems(buffer, conf): for problem in get_cosmetic_problems(buffer, conf, filepath):
# Insert the syntax error (if any) at the right place... # Insert the syntax error (if any) at the right place...
if (syntax_error and syntax_error.line <= problem.line and if (syntax_error and syntax_error.line <= problem.line and
syntax_error.column <= problem.column): syntax_error.column <= problem.column):
@ -205,7 +215,7 @@ def _run(buffer, conf):
yield syntax_error yield syntax_error
def run(input, conf): def run(input, conf, filepath=None):
"""Lints a YAML source. """Lints a YAML source.
Returns a generator of LintProblem objects. Returns a generator of LintProblem objects.
@ -213,11 +223,14 @@ def run(input, conf):
:param input: buffer, string or stream to read from :param input: buffer, string or stream to read from
:param conf: yamllint configuration object :param conf: yamllint configuration object
""" """
if conf.is_file_ignored(filepath):
return ()
if type(input) in (type(b''), type(u'')): # compat with Python 2 & 3 if type(input) in (type(b''), type(u'')): # compat with Python 2 & 3
return _run(input, conf) return _run(input, conf, filepath)
elif hasattr(input, 'read'): # Python 2's file or Python 3's io.IOBase elif hasattr(input, 'read'): # Python 2's file or Python 3's io.IOBase
# We need to have everything in memory to parse correctly # We need to have everything in memory to parse correctly
content = input.read() content = input.read()
return _run(content, conf) return _run(content, conf, filepath)
else: else:
raise TypeError('input should be a string or a stream') raise TypeError('input should be a string or a stream')

@ -23,6 +23,10 @@ Use this rule to control the number of spaces inside braces (``{`` and ``}``).
braces. braces.
* ``max-spaces-inside`` defines the maximal number of spaces allowed inside * ``max-spaces-inside`` defines the maximal number of spaces allowed inside
braces. braces.
* ``min-spaces-inside-empty`` defines the minimal number of spaces required
inside empty braces.
* ``max-spaces-inside-empty`` defines the maximal number of spaces allowed
inside empty braces.
.. rubric:: Examples .. rubric:: Examples
@ -59,6 +63,30 @@ Use this rule to control the number of spaces inside braces (``{`` and ``}``).
:: ::
object: {key1: 4, key2: 8 } object: {key1: 4, key2: 8 }
#. With ``braces: {min-spaces-inside-empty: 0, max-spaces-inside-empty: 0}``
the following code snippet would **PASS**:
::
object: {}
the following code snippet would **FAIL**:
::
object: { }
#. With ``braces: {min-spaces-inside-empty: 1, max-spaces-inside-empty: -1}``
the following code snippet would **PASS**:
::
object: { }
the following code snippet would **FAIL**:
::
object: {}
""" """
@ -70,11 +98,27 @@ from yamllint.rules.common import spaces_after, spaces_before
ID = 'braces' ID = 'braces'
TYPE = 'token' TYPE = 'token'
CONF = {'min-spaces-inside': int, CONF = {'min-spaces-inside': int,
'max-spaces-inside': int} 'max-spaces-inside': int,
'min-spaces-inside-empty': int,
'max-spaces-inside-empty': int}
def check(conf, token, prev, next, nextnext, context): def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.FlowMappingStartToken): if (isinstance(token, yaml.FlowMappingStartToken) and
isinstance(next, yaml.FlowMappingEndToken)):
problem = spaces_after(token, prev, next,
min=(conf['min-spaces-inside-empty']
if conf['min-spaces-inside-empty'] != -1
else conf['min-spaces-inside']),
max=(conf['max-spaces-inside-empty']
if conf['max-spaces-inside-empty'] != -1
else conf['max-spaces-inside']),
min_desc='too few spaces inside empty braces',
max_desc='too many spaces inside empty braces')
if problem is not None:
yield problem
elif isinstance(token, yaml.FlowMappingStartToken):
problem = spaces_after(token, prev, next, problem = spaces_after(token, prev, next,
min=conf['min-spaces-inside'], min=conf['min-spaces-inside'],
max=conf['max-spaces-inside'], max=conf['max-spaces-inside'],

@ -24,6 +24,10 @@ Use this rule to control the number of spaces inside brackets (``[`` and
brackets. brackets.
* ``max-spaces-inside`` defines the maximal number of spaces allowed inside * ``max-spaces-inside`` defines the maximal number of spaces allowed inside
brackets. brackets.
* ``min-spaces-inside-empty`` defines the minimal number of spaces required
inside empty brackets.
* ``max-spaces-inside-empty`` defines the maximal number of spaces allowed
inside empty brackets.
.. rubric:: Examples .. rubric:: Examples
@ -60,6 +64,30 @@ Use this rule to control the number of spaces inside brackets (``[`` and
:: ::
object: [1, 2, abc ] object: [1, 2, abc ]
#. With ``brackets: {min-spaces-inside-empty: 0, max-spaces-inside-empty: 0}``
the following code snippet would **PASS**:
::
object: []
the following code snippet would **FAIL**:
::
object: [ ]
#. With ``brackets: {min-spaces-inside-empty: 1, max-spaces-inside-empty: -1}``
the following code snippet would **PASS**:
::
object: [ ]
the following code snippet would **FAIL**:
::
object: []
""" """
@ -71,11 +99,28 @@ from yamllint.rules.common import spaces_after, spaces_before
ID = 'brackets' ID = 'brackets'
TYPE = 'token' TYPE = 'token'
CONF = {'min-spaces-inside': int, CONF = {'min-spaces-inside': int,
'max-spaces-inside': int} 'max-spaces-inside': int,
'min-spaces-inside-empty': int,
'max-spaces-inside-empty': int}
def check(conf, token, prev, next, nextnext, context): def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.FlowSequenceStartToken): if (isinstance(token, yaml.FlowSequenceStartToken) and
isinstance(next, yaml.FlowSequenceEndToken)):
problem = spaces_after(token, prev, next,
min=(conf['min-spaces-inside-empty']
if conf['min-spaces-inside-empty'] != -1
else conf['min-spaces-inside']),
max=(conf['max-spaces-inside-empty']
if conf['max-spaces-inside-empty'] != -1
else conf['max-spaces-inside']),
min_desc='too few spaces inside empty brackets',
max_desc=('too many spaces inside empty '
'brackets'))
if problem is not None:
yield problem
elif isinstance(token, yaml.FlowSequenceStartToken):
problem = spaces_after(token, prev, next, problem = spaces_after(token, prev, next,
min=conf['min-spaces-inside'], min=conf['min-spaces-inside'],
max=conf['max-spaces-inside'], max=conf['max-spaces-inside'],

@ -20,14 +20,14 @@ Use this rule to control the position and formatting of comments.
.. rubric:: Options .. rubric:: Options
* Use ``require-starting-space`` to require a space character right after the * Use ``require-starting-space`` to require a space character right after the
``#``. Set to ``yes`` to enable, ``no`` to disable. ``#``. Set to ``true`` to enable, ``false`` to disable.
* ``min-spaces-from-content`` is used to visually separate inline comments from * ``min-spaces-from-content`` is used to visually separate inline comments from
content. It defines the minimal required number of spaces between a comment content. It defines the minimal required number of spaces between a comment
and its preceding content. and its preceding content.
.. rubric:: Examples .. rubric:: Examples
#. With ``comments: {require-starting-space: yes}`` #. With ``comments: {require-starting-space: true}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::

@ -19,12 +19,12 @@ Use this rule to require or forbid the use of document end marker (``...``).
.. rubric:: Options .. rubric:: Options
* Set ``present`` to ``yes`` when the document end marker is required, or to * Set ``present`` to ``true`` when the document end marker is required, or to
``no`` when it is forbidden. ``false`` when it is forbidden.
.. rubric:: Examples .. rubric:: Examples
#. With ``document-end: {present: yes}`` #. With ``document-end: {present: true}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::
@ -49,7 +49,7 @@ Use this rule to require or forbid the use of document end marker (``...``).
- is: another one - is: another one
... ...
#. With ``document-end: {present: no}`` #. With ``document-end: {present: false}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::

@ -19,12 +19,12 @@ Use this rule to require or forbid the use of document start marker (``---``).
.. rubric:: Options .. rubric:: Options
* Set ``present`` to ``yes`` when the document start marker is required, or to * Set ``present`` to ``true`` when the document start marker is required, or to
``no`` when it is forbidden. ``false`` when it is forbidden.
.. rubric:: Examples .. rubric:: Examples
#. With ``document-start: {present: yes}`` #. With ``document-start: {present: true}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::
@ -45,7 +45,7 @@ Use this rule to require or forbid the use of document start marker (``---``).
- this - this
- is: another one - is: another one
#. With ``document-start: {present: no}`` #. With ``document-start: {present: false}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::

@ -25,12 +25,12 @@ Use this rule to control the indentation.
same within the file. same within the file.
* ``indent-sequences`` defines whether block sequences should be indented or * ``indent-sequences`` defines whether block sequences should be indented or
not (when in a mapping, this indentation is not mandatory -- some people not (when in a mapping, this indentation is not mandatory -- some people
perceive the ``-`` as part of the indentation). Possible values: ``yes``, perceive the ``-`` as part of the indentation). Possible values: ``true``,
``no``, ``whatever`` and ``consistent``. ``consistent`` requires either all ``false``, ``whatever`` and ``consistent``. ``consistent`` requires either
block sequences to be indented, or none to be. ``whatever`` means either all block sequences to be indented, or none to be. ``whatever`` means either
indenting or not indenting individual block sequences is OK. indenting or not indenting individual block sequences is OK.
* ``check-multi-line-strings`` defines whether to lint indentation in * ``check-multi-line-strings`` defines whether to lint indentation in
multi-line strings. Set to ``yes`` to enable, ``no`` to disable. multi-line strings. Set to ``true`` to enable, ``false`` to disable.
.. rubric:: Examples .. rubric:: Examples
@ -99,7 +99,7 @@ Use this rule to control the indentation.
Russian: Russian:
dolls dolls
#. With ``indentation: {spaces: 2, indent-sequences: no}`` #. With ``indentation: {spaces: 2, indent-sequences: false}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::
@ -152,7 +152,7 @@ Use this rule to control the indentation.
- spaghetti - spaghetti
- sauce - sauce
#. With ``indentation: {spaces: 4, check-multi-line-strings: yes}`` #. With ``indentation: {spaces: 4, check-multi-line-strings: true}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::
@ -469,7 +469,19 @@ def _check(conf, token, prev, next, nextnext, context):
if context['indent-sequences'] is False: if context['indent-sequences'] is False:
indent = context['stack'][-1].indent indent = context['stack'][-1].indent
elif context['indent-sequences'] is True: elif context['indent-sequences'] is True:
indent = detect_indent(context['stack'][-1].indent, next) if (context['spaces'] == 'consistent' and
next.start_mark.column -
context['stack'][-1].indent == 0):
# In this case, the block sequence item is not indented
# (while it should be), but we don't know yet the
# indentation it should have (because `spaces` is
# `consistent` and its value has not been computed yet
# -- this is probably the beginning of the document).
# So we choose an arbitrary value (2).
indent = 2
else:
indent = detect_indent(context['stack'][-1].indent,
next)
else: # 'whatever' or 'consistent' else: # 'whatever' or 'consistent'
if next.start_mark.column == context['stack'][-1].indent: if next.start_mark.column == context['stack'][-1].indent:
# key: # key:

@ -22,7 +22,7 @@ Use this rule to set a limit to lines length.
* ``max`` defines the maximal (inclusive) length of lines. * ``max`` defines the maximal (inclusive) length of lines.
* ``allow-non-breakable-words`` is used to allow non breakable words (without * ``allow-non-breakable-words`` is used to allow non breakable words (without
spaces inside) to overflow the limit. This is useful for long URLs, for spaces inside) to overflow the limit. This is useful for long URLs, for
instance. Use ``yes`` to allow, ``no`` to forbid. instance. Use ``true`` to allow, ``false`` to forbid.
* ``allow-non-breakable-inline-mappings`` implies ``allow-non-breakable-words`` * ``allow-non-breakable-inline-mappings`` implies ``allow-non-breakable-words``
and extends it to also allow non-breakable words in inline mappings. and extends it to also allow non-breakable words in inline mappings.
@ -44,7 +44,7 @@ Use this rule to set a limit to lines length.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. tempor incididunt ut labore et dolore magna aliqua.
#. With ``line-length: {max: 60, allow-non-breakable-words: yes}`` #. With ``line-length: {max: 60, allow-non-breakable-words: true}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::
@ -68,15 +68,15 @@ Use this rule to set a limit to lines length.
- foobar: http://localhost/very/very/very/very/very/very/very/very/long/url - foobar: http://localhost/very/very/very/very/very/very/very/very/long/url
#. With ``line-length: {max: 60, allow-non-breakable-words: yes, #. With ``line-length: {max: 60, allow-non-breakable-words: true,
allow-non-breakable-inline-mappings: yes}`` allow-non-breakable-inline-mappings: true}``
the following code snippet would **PASS**: the following code snippet would **PASS**:
:: ::
- foobar: http://localhost/very/very/very/very/very/very/very/very/long/url - foobar: http://localhost/very/very/very/very/very/very/very/very/long/url
#. With ``line-length: {max: 60, allow-non-breakable-words: no}`` #. With ``line-length: {max: 60, allow-non-breakable-words: false}``
the following code snippet would **FAIL**: the following code snippet would **FAIL**:
:: ::

@ -17,9 +17,9 @@
""" """
Use this rule to forbid truthy values that are not quoted nor explicitly typed. Use this rule to forbid truthy values that are not quoted nor explicitly typed.
This would prevent YAML parsers to tranform ``[yes, FALSE, Off]`` into ``[true, This would prevent YAML parsers from transforming ``[yes, FALSE, Off]`` into
false, false]`` or ``{y: 1, yes: 2, on: 3, true: 4, True: 5}`` into ``{y: 1, ``[true, false, false]`` or ``{y: 1, yes: 2, on: 3, true: 4, True: 5}`` into
true: 5}``. ``{y: 1, true: 5}``.
.. rubric:: Examples .. rubric:: Examples

Loading…
Cancel
Save