Compare commits

...

48 Commits

Author SHA1 Message Date
Adrien Vergé
d8d1d92545 yamllint version 1.1.0 2016-03-04 17:03:38 +01:00
Adrien Vergé
7688567faa cli: Add the -d option to provide inline conf 2016-03-04 16:53:26 +01:00
Adrien Vergé
4e188f8801 Conf: Add a new pre-defined conf 'relaxed'
It is more tolerant than 'default'.
2016-03-04 16:50:40 +01:00
Adrien Vergé
5693b1dddf Rules: indentation: Add 'consistent' option for 'spaces'
Using `spaces: consistent` allows any number of spaces, as long as it
remains the same within the file.
2016-03-04 16:03:53 +01:00
Adrien Vergé
fa420499c7 Config: Allow types in multiple choices
For instance, allow rules with:

    CONF = {'choice': (int, 'hardcoded-string'),
            'string-or-bool': (str, bool)}
2016-03-04 16:03:46 +01:00
Adrien Vergé
adefe38a0d yamllint version 1.0.4 2016-03-04 12:48:31 +01:00
Adrien Vergé
7e11082353 Distribution: Restore spec examples in package_data
Put `tests/yaml-1.2-spec-examples/*` back in `setup.py`'s `package_data`
because they need to be installed when running `python setup.py build`,
so Debian packaging script `dh_auto_test -O--buildsystem=pybuild`
doesn't fail.

See also commit e6dc67f.
2016-03-04 12:33:56 +01:00
Adrien Vergé
29c1c60143 Tests: Use absolute path to spec examples 2016-03-04 12:15:26 +01:00
Adrien Vergé
b879e9a98f Distribution: Add LICENSE and README to manifest 2016-02-26 09:57:06 +01:00
Adrien Vergé
5956b20545 yamllint version 1.0.3 2016-02-25 14:48:13 +01:00
Adrien Vergé
10ad302e2f Tests: Explicit encoding for spec examples
YAML specification examples contain unusual characters, let's explicit
`encoding='utf-8'` to prevent bugs.
2016-02-25 10:44:05 +01:00
Adrien Vergé
73d9322813 linter: Test run on str, unicode, bytes and stream
Previously it was not tested, and broke on Python 2 `unicode` inputs.
2016-02-25 10:41:17 +01:00
Adrien Vergé
ca0ebe4583 yamllint version 1.0.2 2016-02-24 21:21:02 +01:00
Adrien Vergé
e6dc67fd0a Distribution: Add MANIFEST.in
`yamllint/conf/*.yml` remains in `setup.py`'s `package_data` because it
needs to be installed when running `pip install .`.

`docs/*` and `tests/yaml-1.2-spec-examples/*` just need to be packaged,
they can go in the manifest.
2016-02-24 21:18:48 +01:00
Adrien Vergé
611a560082 yamllint version 1.0.1 2016-02-19 19:39:52 +01:00
Adrien Vergé
83384fa4cf Doc: Fix man page redundant description 2016-02-19 19:34:20 +01:00
Adrien Vergé
3ab3784a75 cli: Remove shebang
A shebang is present at the beginning of file, it dates from the time
when `yamllint/cli.py` was `bin/yamllint`, i.e. an executable launcher.
Since this is not the case anymore (see `entry_points` section in
`setup.py`), let's remove it.
2016-02-19 19:17:49 +01:00
Adrien Vergé
2f75e92a66 Doc: Add a configuration example in README 2016-02-19 10:37:52 +01:00
Adrien Vergé
64caa95b6a yamllint version 1.0.0 2016-02-19 10:15:23 +01:00
Adrien Vergé
fff09fa2df Distribution: Ship example files from spec in sdist
Closes: #1
2016-02-19 10:14:59 +01:00
Adrien Vergé
316bee8c98 yamllint version 0.7.2 2016-02-05 11:28:15 +01:00
Adrien Vergé
6c8af97a40 Tests: unblacklist remaining spec examples
Since !!tags are now supported.
2016-02-05 11:14:37 +01:00
Adrien Vergé
647d84ff94 Rules: indentation: Handle tags 2016-02-05 11:13:44 +01:00
Adrien Vergé
8eb0d0ad74 Tests: unblacklist spec example 7.16
As is it supported -- it just lacks some indentation.
2016-02-05 09:52:09 +01:00
Adrien Vergé
4bc3d5a01c Rules: indentation: Handle anchors 2016-02-04 22:10:40 +01:00
Adrien Vergé
48c7d65c54 parser: Provide nextnext for token rules
Because the indentation rule sometimes needs to look two tokens forward
(in case of anchors for instance).
2016-02-04 22:10:40 +01:00
Adrien Vergé
62fa4cbe39 Tests: indentation: Test the indent stack
The "indentation stack" is iteratively built by the `check()` function
of the indentation rule. It is important, since everything in the rule
relies on it.

This patch adds tests to make sure the stack is correctly built for some
known structures.
2016-02-04 22:10:40 +01:00
Adrien Vergé
8d38d349ac Rules: indentation: Rewrite stack generation
"Indentation stack" generation was not done properly, hence did not work
in all cases. This commit does a cleaner rewriting.
2016-02-04 21:47:08 +01:00
Adrien Vergé
3f264806b9 yamllint version 0.7.1 2016-02-03 14:43:09 +01:00
Adrien Vergé
9a82b99d4b Rules: indentation: Fix multi-line flows
To detect this as correct indentations:

    top:
      rules: [
        {
          foo: 1
        },
        {
          foo: 2
          bar: [
            a, b, c
          ],
        },
      ]
2016-02-03 12:05:22 +01:00
Adrien Vergé
ba140ad42c Tests: Remove ghost character from YAML spec example 2016-02-01 23:27:49 +01:00
Adrien Vergé
0e04ee29e6 Doc: Update description 2016-02-01 23:03:25 +01:00
Adrien Vergé
ba9d86d645 yamllint version 0.7.0 2016-02-01 22:43:42 +01:00
Adrien Vergé
3f4f13e848 Doc: Update screenshot to include 'key-duplicates' 2016-02-01 22:41:56 +01:00
Adrien Vergé
f6bab05e8a Rules: Add the 'key-duplicates' rule 2016-02-01 22:26:18 +01:00
Adrien Vergé
c16eec4681 Style: Fix indentation not multiple of four 2016-02-01 21:36:35 +01:00
Adrien Vergé
68618be4cc Rules: indentation: Handle sets
Sets are like mappings, that do not contain values. Example:

    set:
      ? key one
      ? key two
      ? [non, scalar, key]
2016-02-01 17:52:46 +01:00
Adrien Vergé
431a379c81 Tests: Add tests from YAML 1.2 specification
Write all examples from http://www.yaml.org/spec/1.2/spec.html in
independent files in tests/yaml-1.2-spec-examples; and test them with
yamllint.
2016-02-01 17:05:22 +01:00
Adrien Vergé
6b5948c06b Tests: Reorganize common and global tests 2016-02-01 16:56:32 +01:00
Adrien Vergé
dd163ed551 Rules: indentation: Fix flow sequences with multi-line scalars
Typically sequences like this:

    ["multi
      line 1", "multi
                line 2"]
2016-02-01 16:56:32 +01:00
Adrien Vergé
14c99da2bb Tests: Add test cases for empty flows 2016-02-01 16:56:32 +01:00
Adrien Vergé
cae100071a Rules: indentation: Add support for cleared sequence entries
The following construction is valid YAML, and its indentation should be
correctly handled:

    - this is
    -
      a
    -
      sequence:
        with cleared entries
2016-02-01 14:59:52 +01:00
Adrien Vergé
7cb7b4f669 Rules: commas: Add 'min-spaces-after'
Since such constructions are allowed and valid YAML:

    - [one,two, three,four]

this commit adds a `min-spaces-after` option that defaults to 1.
2016-02-01 12:13:10 +01:00
Adrien Vergé
d2b5f69309 Doc: Update Vim integration documentation
Since it has been merged into Syntastic:
https://github.com/scrooloose/syntastic/commit/8c4dadc
https://github.com/scrooloose/syntastic/pull/1675
2016-01-26 17:20:22 +01:00
Adrien Vergé
a7d39b5492 yamllint version 0.6.0 2016-01-25 11:03:00 +01:00
Adrien Vergé
4410bc3e23 Rules: indentation: Fix check-multi-line-strings
For strings that continue on next line at a lower indentation level:

    Blaise Pascal: Je vous écris une longue lettre parce que
      je n'ai pas le temps d'en écrire une courte.
2016-01-25 11:01:42 +01:00
Adrien Vergé
97c446907c Rules: line-length: Add option allow-non-breakable-words 2016-01-24 22:46:10 +01:00
Adrien Vergé
376a6ed484 Doc: Enhance short description 2016-01-24 18:40:48 +01:00
184 changed files with 2820 additions and 250 deletions

3
MANIFEST.in Normal file
View File

@@ -0,0 +1,3 @@
include LICENSE
include README.rst
include docs/*

View File

@@ -3,6 +3,10 @@ yamllint
A linter for YAML files.
yamllint does not only check for syntax validity, but for weirdnesses like key
repetition and cosmetic problems such as lines length, trailing spaces,
indentation, etc.
.. image::
https://travis-ci.org/adrienverge/yamllint.svg?branch=master
:target: https://travis-ci.org/adrienverge/yamllint
@@ -53,6 +57,9 @@ Usage
.. code:: bash
# Use a pre-defined lint configuration
yamllint -d relaxed file.yml
# Use a custom lint configuration
yamllint -c ~/myconfig file.yml
@@ -60,3 +67,19 @@ Usage
# Output a parsable format (for syntax checking in editors like Vim, emacs...)
yamllint -f parsable file.yml
Configuration example
^^^^^^^^^^^^^^^^^^^^^
.. code:: yaml
extends: default
rules:
# 80 chars should be enough, but don't fail if a line is longer
line-length:
max: 80
level: warning
# don't bother me with this rule
indentation: disable

View File

@@ -38,6 +38,5 @@ htmlhelp_basename = 'yamllintdoc'
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'yamllint', u'yamllint Documentation',
[u'Adrien Vergé'], 1)
('index', 'yamllint', '', [u'Adrien Vergé'], 1)
]

View File

@@ -8,7 +8,7 @@ settings can be gathered in a configuration file.
To use a custom configuration file, either name it ``.yamllint`` in your working
directory, or use the ``-c`` option:
::
.. code:: bash
yamllint -c ~/myconfig file.yml
@@ -22,6 +22,15 @@ Unless told otherwise, yamllint uses its ``default`` configuration:
Details on rules can be found on :doc:`the rules page <rules>`.
There is another pre-defined configuration named ``relaxed``. As its name
suggests, it is more tolerant.
It can be chosen using:
.. code:: bash
yamllint -d relaxed file.yml
Extending the default configuration
-----------------------------------
@@ -50,7 +59,7 @@ strict on block sequences indentation:
extends: default
rules:
# 80 should be enough, but don't fail if a line is longer
# 80 chars should be enough, but don't fail if a line is longer
line-length:
max: 80
level: warning
@@ -63,6 +72,21 @@ strict on block sequences indentation:
indentation:
indent-sequences: whatever
Custom configuration without a config file
------------------------------------------
It is possible -- although not recommended -- to pass custom configuration
options to yamllint with the ``-d`` (short for ``--config-data``) option.
Its content can either be the name of a pre-defined conf (example: ``default``
or ``relaxed``) or a serialized YAML object describing the configuration.
For instance:
.. code:: bash
yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" file.yml
Errors and warnings
-------------------

View File

@@ -1,7 +1,7 @@
yamllint documentation
======================
A linter for YAML files.
.. automodule:: yamllint
Screenshot
----------

View File

@@ -38,15 +38,18 @@ The output will look like (colors are not displayed here):
::
file.yml
6:2 warning missing starting space in comment (comments)
57:1 error trailing spaces (trailing-spaces)
60:3 error wrong indentation: expected 4 but found 2 (indentation)
1:4 error trailing spaces (trailing-spaces)
4:4 error wrong indentation: expected 4 but found 3 (indentation)
5:4 error duplication of key "id-00042" in mapping (key-duplicates)
6:6 warning comment not indented like content (comments-indentation)
12:6 error too many spaces after hyphen (hyphens)
15:12 error too many spaces before comma (commas)
other-file.yml
other-file.yaml
1:1 warning missing document start "---" (document-start)
9:81 error line too long (84 > 80 characters) (line-length)
31:1 error too many blank lines (4 > 2) (empty-lines)
37:12 error too many spaces inside braces (braces)
6:81 error line too long (87 > 80 characters) (line-length)
10:1 error too many blank lines (4 > 2) (empty-lines)
11:4 error too many spaces inside braces (braces)
Add the ``-f parsable`` arguments if you need an output format parsable by a
machine (for instance for :doc:`syntax highlighting in text editors

View File

@@ -69,6 +69,11 @@ indentation
.. automodule:: yamllint.rules.indentation
key-duplicates
--------------
.. automodule:: yamllint.rules.key_duplicates
line-length
-----------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -14,7 +14,7 @@ is installed, add to your ``.vimrc``:
::
TODO
let g:syntastic_yaml_checkers = ['yamllint']
Neovim
------

View File

@@ -24,12 +24,13 @@ setup(
name=APP_NAME,
version=APP_VERSION,
author=__author__,
description=APP_DESCRIPTION,
description=APP_DESCRIPTION.split('\n')[0],
long_description=APP_DESCRIPTION,
license=__license__,
keywords=['yaml', 'lint', 'linter', 'syntax', 'checker'],
url='https://github.com/adrienverge/yamllint',
classifiers=[
'Development Status :: 4 - Beta',
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
@@ -43,7 +44,8 @@ setup(
packages=find_packages(),
entry_points={'console_scripts': ['yamllint=yamllint.cli:run']},
package_data={'yamllint': ['conf/*.yml']},
package_data={'yamllint': ['conf/*.yml'],
'tests': ['yaml-1.2-spec-examples/*']},
install_requires=['pyyaml'],
tests_require=['nose'],
test_suite='nose.collector',

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class ColonTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class ColonTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class ColonTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class CommaTestCase(RuleTestCase):
@@ -33,9 +33,25 @@ class CommaTestCase(RuleTestCase):
' key2: val2,\n'
'}\n'
'...\n', conf)
self.check('---\n'
'- [one, two , three,four]\n'
'- {five,six , seven, eight}\n'
'- [\n'
' nine, ten\n'
' , eleven\n'
' ,twelve\n'
']\n'
'- {\n'
' thirteen: 13, fourteen\n'
' , fifteen: 15\n'
' ,sixteen: 16\n'
'}\n', conf)
def test_before_enabled(self):
conf = 'commas: {max-spaces-before: 0, max-spaces-after: -1}'
def test_before_max(self):
conf = ('commas:\n'
' max-spaces-before: 0\n'
' min-spaces-after: 0\n'
' max-spaces-after: -1\n')
self.check('---\n'
'array: [1, 2, 3, 4]\n'
'...\n', conf)
@@ -75,8 +91,51 @@ class CommaTestCase(RuleTestCase):
' key2: val2 ,\n'
'}\n', conf, problem=(4, 13))
def test_before_max(self):
conf = 'commas: {max-spaces-before: 3, max-spaces-after: -1}'
def test_before_max_with_comma_on_new_line(self):
conf = ('commas:\n'
' max-spaces-before: 0\n'
' min-spaces-after: 0\n'
' max-spaces-after: -1\n')
self.check('---\n'
'flow-seq: [1, 2, 3\n'
' , 4, 5, 6]\n'
'...\n', conf, problem=(3, 11))
self.check('---\n'
'flow-map: {a: 1, b: 2\n'
' , c: 3}\n'
'...\n', conf, problem=(3, 11))
conf = ('commas:\n'
' max-spaces-before: 0\n'
' min-spaces-after: 0\n'
' max-spaces-after: -1\n'
'indentation: disable\n')
self.check('---\n'
'flow-seq: [1, 2, 3\n'
' , 4, 5, 6]\n'
'...\n', conf, problem=(3, 9))
self.check('---\n'
'flow-map: {a: 1, b: 2\n'
' , c: 3}\n'
'...\n', conf, problem=(3, 9))
self.check('---\n'
'[\n'
'1,\n'
'2\n'
', 3\n'
']\n', conf, problem=(5, 1))
self.check('---\n'
'{\n'
'a: 1,\n'
'b: 2\n'
', c: 3\n'
'}\n', conf, problem=(5, 1))
def test_before_max_3(self):
conf = ('commas:\n'
' max-spaces-before: 3\n'
' min-spaces-after: 0\n'
' max-spaces-after: -1\n')
self.check('---\n'
'array: [1 , 2, 3 , 4]\n'
'...\n', conf)
@@ -90,8 +149,32 @@ class CommaTestCase(RuleTestCase):
' key: val,\n'
']\n', conf, problem=(4, 11))
def test_after_enabled(self):
conf = 'commas: {max-spaces-before: -1, max-spaces-after: 1}'
def test_after_min(self):
conf = ('commas:\n'
' max-spaces-before: -1\n'
' min-spaces-after: 1\n'
' max-spaces-after: -1\n')
self.check('---\n'
'- [one, two , three,four]\n'
'- {five,six , seven, eight}\n'
'- [\n'
' nine, ten\n'
' , eleven\n'
' ,twelve\n'
']\n'
'- {\n'
' thirteen: 13, fourteen\n'
' , fifteen: 15\n'
' ,sixteen: 16\n'
'}\n', conf,
problem1=(2, 21), problem2=(3, 9),
problem3=(7, 4), problem4=(12, 4))
def test_after_max(self):
conf = ('commas:\n'
' max-spaces-before: -1\n'
' min-spaces-after: 0\n'
' max-spaces-after: 1\n')
self.check('---\n'
'array: [1, 2, 3, 4]\n'
'...\n', conf)
@@ -124,8 +207,11 @@ class CommaTestCase(RuleTestCase):
' key1: val1, key2: [val2, val3]\n'
'}\n', conf, problem1=(3, 16), problem2=(3, 30))
def test_after_max(self):
conf = 'commas: {max-spaces-before: -1, max-spaces-after: 3}'
def test_after_max_3(self):
conf = ('commas:\n'
' max-spaces-before: -1\n'
' min-spaces-after: 1\n'
' max-spaces-after: 3\n')
self.check('---\n'
'array: [1, 2, 3, 4]\n'
'...\n', conf)
@@ -137,7 +223,10 @@ class CommaTestCase(RuleTestCase):
'...\n', conf, problem1=(2, 31), problem2=(2, 49))
def test_both_before_and_after(self):
conf = 'commas: {max-spaces-before: 0, max-spaces-after: 1}'
conf = ('commas:\n'
' max-spaces-before: 0\n'
' min-spaces-after: 1\n'
' max-spaces-after: 1\n')
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e , f: [g, h]}\n'
'array: [\n'
@@ -152,36 +241,25 @@ class CommaTestCase(RuleTestCase):
problem1=(2, 12), problem2=(2, 16), problem3=(2, 31),
problem4=(2, 36), problem5=(2, 50), problem6=(4, 8),
problem7=(5, 11), problem8=(8, 13))
def test_comma_on_new_line(self):
conf = 'commas: {max-spaces-before: 0, max-spaces-after: 1}'
self.check('---\n'
'flow-seq: [1, 2, 3\n'
' , 4, 5, 6]\n'
'...\n', conf, problem=(3, 11))
self.check('---\n'
'flow-map: {a: 1, b: 2\n'
' , c: 3}\n'
'...\n', conf, problem=(3, 11))
conf = ('commas: {max-spaces-before: 0, max-spaces-after: 1}\n'
conf = ('commas:\n'
' max-spaces-before: 0\n'
' min-spaces-after: 1\n'
' max-spaces-after: 1\n'
'indentation: disable\n')
self.check('---\n'
'flow-seq: [1, 2, 3\n'
' , 4, 5, 6]\n'
'...\n', conf, problem=(3, 9))
self.check('---\n'
'flow-map: {a: 1, b: 2\n'
' , c: 3}\n'
'...\n', conf, problem=(3, 9))
self.check('---\n'
'[\n'
'1,\n'
'2\n'
', 3\n'
']\n', conf, problem=(5, 1))
self.check('---\n'
'{\n'
'a: 1,\n'
'b: 2\n'
', c: 3\n'
'}\n', conf, problem=(5, 1))
'- [one, two , three,four]\n'
'- {five,six , seven, eight}\n'
'- [\n'
' nine, ten\n'
' , eleven\n'
' ,twelve\n'
']\n'
'- {\n'
' thirteen: 13, fourteen\n'
' , fifteen: 15\n'
' ,sixteen: 16\n'
'}\n', conf,
problem1=(2, 12), problem2=(2, 21), problem3=(3, 9),
problem4=(3, 12), problem5=(5, 9), problem6=(6, 2),
problem7=(7, 2), problem8=(7, 4), problem9=(10, 17),
problem10=(11, 2), problem11=(12, 2), problem12=(12, 4))

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class CommentsTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class CommentsIndentationTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class DocumentEndTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class DocumentStartTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class EmptyLinesTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class HyphenTestCase(RuleTestCase):

View File

@@ -14,7 +14,372 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
from yamllint.parser import token_generator
from yamllint.rules.indentation import check
class IndentationStackTestCase(RuleTestCase):
# This test suite checks that the "indentation stack" built by the
# indentation rule is valid. It is important, since everything else in the
# rule relies on this stack.
maxDiff = None
def format_stack(self, stack):
"""Transform the stack at a given moment into a printable string like:
B_MAP:0 KEY:0 VAL:5
"""
return ' '.join(map(str, stack[1:]))
def full_stack(self, source):
conf = {'spaces': 2, 'indent-sequences': True,
'check-multi-line-strings': False}
context = {}
output = ''
for elem in token_generator(source):
list(check(conf, elem.curr, elem.prev, elem.next, elem.nextnext,
context))
token_type = (elem.curr.__class__.__name__
.replace('Token', '')
.replace('Block', 'B').replace('Flow', 'F')
.replace('Sequence', 'Seq')
.replace('Mapping', 'Map'))
if token_type in ('StreamStart', 'StreamEnd'):
continue
output += '%9s %s\n' % (token_type,
self.format_stack(context['stack']))
return output
def test_simple_mapping(self):
self.assertMultiLineEqual(
self.full_stack('key: val\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:5\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack(' key: val\n'),
'BMapStart B_MAP:5\n'
' Key B_MAP:5 KEY:5\n'
' Scalar B_MAP:5 KEY:5\n'
' Value B_MAP:5 KEY:5 VAL:10\n'
' Scalar B_MAP:5\n'
' BEnd \n')
def test_simple_sequence(self):
self.assertMultiLineEqual(
self.full_stack('- 1\n'
'- 2\n'
'- 3\n'),
'BSeqStart B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Scalar B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Scalar B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Scalar B_SEQ:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('key:\n'
' - 1\n'
' - 2\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
'BSeqStart B_MAP:0 KEY:0 VAL:2 B_SEQ:2\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:2\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:2\n'
' BEnd B_MAP:0\n'
' BEnd \n')
def test_non_indented_sequences(self):
# There seems to be a bug in pyyaml: depending on the indentation, a
# sequence does not produce the same tokens. More precisely, the
# following YAML:
# usr:
# - lib
# produces a BlockSequenceStartToken and a BlockEndToken around the
# "lib" sequence, whereas the following:
# usr:
# - lib
# does not (both two tokens are omitted).
# So, yamllint must create fake 'B_SEQ'. This test makes sure it does.
self.assertMultiLineEqual(
self.full_stack('usr:\n'
' - lib\n'
'var: cache\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
'BSeqStart B_MAP:0 KEY:0 VAL:2 B_SEQ:2\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:2\n'
' BEnd B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:5\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('usr:\n'
'- lib\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
# missing BSeqStart here
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
' Scalar B_MAP:0\n'
# missing BEnd here
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('usr:\n'
'- lib\n'
'var: cache\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
# missing BSeqStart here
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
' Scalar B_MAP:0\n'
# missing BEnd here
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:5\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('usr:\n'
'- []\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
# missing BSeqStart here
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
'FSeqStart B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 F_SEQ:3\n'
' FSeqEnd B_MAP:0\n'
# missing BEnd here
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('usr:\n'
'- k:\n'
' v\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
# missing BSeqStart here
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
'BMapStart B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_MAP:2\n'
' Key B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_MAP:2 KEY:2\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_MAP:2 KEY:2\n'
' Value B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_MAP:2 KEY:2 VAL:4\n' # noqa
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_MAP:2\n'
' BEnd B_MAP:0\n'
# missing BEnd here
' BEnd \n')
def test_flows(self):
self.assertMultiLineEqual(
self.full_stack('usr: [\n'
' {k:\n'
' v}\n'
' ]\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:5\n'
'FSeqStart B_MAP:0 KEY:0 VAL:5 F_SEQ:2\n'
'FMapStart B_MAP:0 KEY:0 VAL:5 F_SEQ:2 F_MAP:3\n'
' Key B_MAP:0 KEY:0 VAL:5 F_SEQ:2 F_MAP:3 KEY:3\n'
' Scalar B_MAP:0 KEY:0 VAL:5 F_SEQ:2 F_MAP:3 KEY:3\n'
' Value B_MAP:0 KEY:0 VAL:5 F_SEQ:2 F_MAP:3 KEY:3 VAL:5\n'
' Scalar B_MAP:0 KEY:0 VAL:5 F_SEQ:2 F_MAP:3\n'
' FMapEnd B_MAP:0 KEY:0 VAL:5 F_SEQ:2\n'
' FSeqEnd B_MAP:0\n'
' BEnd \n')
def test_anchors(self):
self.assertMultiLineEqual(
self.full_stack('key: &anchor value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:5\n'
' Anchor B_MAP:0 KEY:0 VAL:5\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('key: &anchor\n'
' value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
' Anchor B_MAP:0 KEY:0 VAL:2\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('- &anchor value\n'),
'BSeqStart B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Anchor B_SEQ:0 B_ENT:2\n'
' Scalar B_SEQ:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('- &anchor\n'
' value\n'),
'BSeqStart B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Anchor B_SEQ:0 B_ENT:2\n'
' Scalar B_SEQ:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('- &anchor\n'
' - 1\n'
' - 2\n'),
'BSeqStart B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Anchor B_SEQ:0 B_ENT:2\n'
'BSeqStart B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEntry B_SEQ:0 B_ENT:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEntry B_SEQ:0 B_ENT:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEnd B_SEQ:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('&anchor key:\n'
' value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Anchor B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('pre:\n'
' &anchor1 0\n'
'&anchor2 key:\n'
' value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
' Anchor B_MAP:0 KEY:0 VAL:2\n'
' Scalar B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Anchor B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('sequence: &anchor\n'
'- entry\n'
'- &anchor\n'
' - nested\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
' Anchor B_MAP:0 KEY:0 VAL:2\n'
# missing BSeqStart here
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:0\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
' Anchor B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
'BSeqStart B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEnd B_MAP:0\n'
# missing BEnd here
' BEnd \n')
def test_tags(self):
self.assertMultiLineEqual(
self.full_stack('key: !!tag value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:5\n'
' Tag B_MAP:0 KEY:0 VAL:5\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('- !!map # Block collection\n'
' foo : bar\n'),
'BSeqStart B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Tag B_SEQ:0 B_ENT:2\n'
'BMapStart B_SEQ:0 B_ENT:2 B_MAP:2\n'
' Key B_SEQ:0 B_ENT:2 B_MAP:2 KEY:2\n'
' Scalar B_SEQ:0 B_ENT:2 B_MAP:2 KEY:2\n'
' Value B_SEQ:0 B_ENT:2 B_MAP:2 KEY:2 VAL:8\n'
' Scalar B_SEQ:0 B_ENT:2 B_MAP:2\n'
' BEnd B_SEQ:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('- !!seq\n'
' - nested item\n'),
'BSeqStart B_SEQ:0\n'
' BEntry B_SEQ:0 B_ENT:2\n'
' Tag B_SEQ:0 B_ENT:2\n'
'BSeqStart B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEntry B_SEQ:0 B_ENT:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEnd B_SEQ:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('sequence: !!seq\n'
'- entry\n'
'- !!seq\n'
' - nested\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
' Scalar B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:2\n'
' Tag B_MAP:0 KEY:0 VAL:2\n'
# missing BSeqStart here
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:0\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
' Tag B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2\n'
'BSeqStart B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEntry B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_SEQ:2 B_ENT:4\n'
' Scalar B_MAP:0 KEY:0 VAL:2 B_SEQ:0 B_ENT:2 B_SEQ:2\n'
' BEnd B_MAP:0\n'
# missing BEnd here
' BEnd \n')
class IndentationTestCase(RuleTestCase):
@@ -131,6 +496,87 @@ class IndentationTestCase(RuleTestCase):
' date: 1991\n'
'...\n', conf)
def test_consistent(self):
conf = ('indentation: {spaces: consistent,\n'
' indent-sequences: whatever}\n'
'document-start: disable\n')
self.check('---\n'
'object:\n'
' k1:\n'
' - a\n'
' - b\n'
' k2: v2\n'
' k3:\n'
' - name: Unix\n'
' date: 1969\n'
' - name: Linux\n'
' date: 1991\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' k1:\n'
' - a\n'
' - b\n'
' k2: v2\n'
' k3:\n'
' - name: Unix\n'
' date: 1969\n'
' - name: Linux\n'
' date: 1991\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' k1:\n'
' - a\n'
' - b\n'
' k2: v2\n'
' k3:\n'
' - name: Unix\n'
' date: 1969\n'
' - name: Linux\n'
' date: 1991\n'
'...\n', conf)
self.check('first is not indented:\n'
' value is indented\n', conf)
self.check('first is not indented:\n'
' value:\n'
' is indented\n', conf)
self.check('- first is already indented:\n'
' value is indented too\n', conf)
self.check('- first is already indented:\n'
' value:\n'
' is indented too\n', conf)
self.check('- first is already indented:\n'
' value:\n'
' is indented too\n', conf, problem=(3, 14))
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem=(7, 5))
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)
def test_indent_sequences_whatever(self):
conf = 'indentation: {spaces: 4, indent-sequences: whatever}'
self.check('---\n'
@@ -169,7 +615,9 @@ class IndentationTestCase(RuleTestCase):
'- b\n'
'- c\n', conf, problem=(6, 1, 'syntax'))
def test_flow_mappings(self):
def test_direct_flows(self):
# flow: [ ...
# ]
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'a: {x: 1,\n'
@@ -183,10 +631,46 @@ class IndentationTestCase(RuleTestCase):
'a: {x: 1,\n'
' y,\n'
' z: 1}\n', conf, problem=(3, 6))
self.check('---\n'
'a: {x: 1,\n'
' y, z: 1}\n', conf, problem=(3, 3))
self.check('---\n'
'a: {x: 1,\n'
' y, z: 1\n'
'}\n', conf)
self.check('---\n'
'a: {x: 1,\n'
' y, z: 1\n'
'}\n', conf, problem=(3, 3))
self.check('---\n'
'a: [x,\n'
' y,\n'
' z]\n', conf)
self.check('---\n'
'a: [x,\n'
' y,\n'
' z]\n', conf, problem=(3, 4))
self.check('---\n'
'a: [x,\n'
' y,\n'
' z]\n', conf, problem=(3, 6))
self.check('---\n'
'a: [x,\n'
' y, z]\n', conf, problem=(3, 3))
self.check('---\n'
'a: [x,\n'
' y, z\n'
']\n', conf)
self.check('---\n'
'a: [x,\n'
' y, z\n'
']\n', conf, problem=(3, 3))
def test_broken_flows(self):
# flow: [
# ...
# ]
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'a: {\n'
' x: 1,\n'
@@ -206,25 +690,6 @@ class IndentationTestCase(RuleTestCase):
' x: 1,\n'
' y, z: 1\n'
' }\n', conf, problem=(5, 3))
def test_flow_sequences(self):
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'a: [x,\n'
' y,\n'
' z]\n', conf)
self.check('---\n'
'a: [x,\n'
' y,\n'
' z]\n', conf, problem=(3, 4))
self.check('---\n'
'a: [x,\n'
' y,\n'
' z]\n', conf, problem=(3, 6))
self.check('---\n'
'a: [x,\n'
' y, z\n'
']\n', conf, problem=(3, 3))
self.check('---\n'
'a: [\n'
' x,\n'
@@ -244,6 +709,138 @@ class IndentationTestCase(RuleTestCase):
' x,\n'
' y, z\n'
' ]\n', conf, problem=(5, 3))
self.check('---\n'
'obj: {\n'
' a: 1,\n'
' b: 2,\n'
' c: 3\n'
'}\n', conf, problem1=(4, 4), problem2=(5, 2))
self.check('---\n'
'list: [\n'
' 1,\n'
' 2,\n'
' 3\n'
']\n', conf, problem1=(4, 4), problem2=(5, 2))
self.check('---\n'
'top:\n'
' rules: [\n'
' 1, 2,\n'
' ]\n', conf)
self.check('---\n'
'top:\n'
' rules: [\n'
' 1, 2,\n'
']\n'
' rulez: [\n'
' 1, 2,\n'
' ]\n', conf, problem1=(5, 1), problem2=(8, 5))
self.check('---\n'
'top:\n'
' rules:\n'
' here: {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf)
self.check('---\n'
'top:\n'
' rules:\n'
' here: {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n'
' there: {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf, problem1=(7, 7), problem2=(11, 3))
def test_cleared_flows(self):
# flow:
# [
# ...
# ]
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'top:\n'
' rules:\n'
' {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf)
self.check('---\n'
'top:\n'
' rules:\n'
' {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf, problem=(5, 8))
self.check('---\n'
'top:\n'
' rules:\n'
' {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf, problem=(4, 4))
self.check('---\n'
'top:\n'
' rules:\n'
' {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf, problem=(7, 4))
self.check('---\n'
'top:\n'
' rules:\n'
' {\n'
' foo: 1,\n'
' bar: 2\n'
' }\n', conf, problem=(7, 6))
self.check('---\n'
'top:\n'
' [\n'
' a, b, c\n'
' ]\n', conf)
self.check('---\n'
'top:\n'
' [\n'
' a, b, c\n'
' ]\n', conf, problem=(4, 6))
self.check('---\n'
'top:\n'
' [\n'
' a, b, c\n'
' ]\n', conf, problem=(3, 4))
self.check('---\n'
'top:\n'
' [\n'
' a, b, c\n'
' ]\n', conf, problem=(5, 4))
self.check('---\n'
'top:\n'
' rules: [\n'
' {\n'
' foo: 1\n'
' },\n'
' {\n'
' foo: 2,\n'
' bar: [\n'
' a, b, c\n'
' ],\n'
' },\n'
' ]\n', conf)
self.check('---\n'
'top:\n'
' rules: [\n'
' {\n'
' foo: 1\n'
' },\n'
' {\n'
' foo: 2,\n'
' bar: [\n'
' a, b, c\n'
' ],\n'
' },\n'
']\n', conf, problem1=(5, 6), problem2=(6, 6),
problem3=(9, 9), problem4=(11, 7), problem5=(13, 1))
def test_under_indented(self):
conf = 'indentation: {spaces: 2, indent-sequences: yes}'
@@ -438,21 +1035,6 @@ class IndentationTestCase(RuleTestCase):
'document-start: disable\n')
self.check(' a: 1\n', conf, problem=(1, 3))
def test_broken_inline_flows(self):
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'obj: {\n'
' a: 1,\n'
' b: 2,\n'
' c: 3\n'
'}\n', conf, problem1=(4, 4), problem2=(5, 2))
self.check('---\n'
'list: [\n'
' 1,\n'
' 2,\n'
' 3\n'
']\n', conf, problem1=(4, 4), problem2=(5, 2))
def test_explicit_block_mappings(self):
conf = 'indentation: {spaces: 4}'
self.check('---\n'
@@ -489,6 +1071,140 @@ class IndentationTestCase(RuleTestCase):
' value\n'
'...\n', conf, problem1=(4, 10), problem2=(6, 8))
def test_clear_sequence_item(self):
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'-\n'
' string\n'
'-\n'
' map: ping\n'
'-\n'
' - sequence\n'
' -\n'
' nested\n'
' -\n'
' >\n'
' multi\n'
' line\n'
'...\n', conf)
self.check('---\n'
'-\n'
' string\n'
'-\n'
' string\n', conf, problem1=(3, 2), problem2=(5, 4))
self.check('---\n'
'-\n'
' map: ping\n'
'-\n'
' map: ping\n', conf, problem1=(3, 2), problem2=(5, 4))
self.check('---\n'
'-\n'
' - sequence\n'
'-\n'
' - sequence\n', conf, problem1=(3, 2), problem2=(5, 4))
self.check('---\n'
'-\n'
' -\n'
' nested\n'
' -\n'
' nested\n', conf, problem1=(4, 4), problem2=(6, 6))
self.check('---\n'
'-\n'
' -\n'
' >\n'
' multi\n'
' line\n'
'...\n', conf, problem=(4, 6))
def test_anchors(self):
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'key: &anchor value\n', conf)
self.check('---\n'
'key: &anchor\n'
' value\n', conf)
self.check('---\n'
'- &anchor value\n', conf)
self.check('---\n'
'- &anchor\n'
' value\n', conf)
self.check('---\n'
'key: &anchor [1,\n'
' 2]\n', conf)
self.check('---\n'
'key: &anchor\n'
' [1,\n'
' 2]\n', conf)
self.check('---\n'
'key: &anchor\n'
' - 1\n'
' - 2\n', conf)
self.check('---\n'
'- &anchor [1,\n'
' 2]\n', conf)
self.check('---\n'
'- &anchor\n'
' [1,\n'
' 2]\n', conf)
self.check('---\n'
'- &anchor\n'
' - 1\n'
' - 2\n', conf)
self.check('---\n'
'key:\n'
' &anchor1\n'
' value\n', conf)
self.check('---\n'
'pre:\n'
' &anchor1 0\n'
'&anchor2 key:\n'
' value\n', conf)
self.check('---\n'
'machine0:\n'
' /etc/hosts: &ref-etc-hosts\n'
' content:\n'
' - 127.0.0.1: localhost\n'
' - ::1: localhost\n'
' mode: 0644\n'
'machine1:\n'
' /etc/hosts: *ref-etc-hosts\n', conf)
self.check('---\n'
'list:\n'
' - k: v\n'
' - &a truc\n'
' - &b\n'
' truc\n'
' - k: *a\n', conf)
def test_tags(self):
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'-\n'
' "flow in block"\n'
'- >\n'
' Block scalar\n'
'- !!map # Block collection\n'
' foo: bar\n', conf)
conf = 'indentation: {spaces: 2, indent-sequences: no}'
self.check('---\n'
'sequence: !!seq\n'
'- entry\n'
'- !!seq\n'
' - nested\n', conf)
self.check('---\n'
'mapping: !!map\n'
' foo: bar\n'
'Block style: !!map\n'
' Clark: Evans\n'
' Ingy: döt Net\n'
' Oren: Ben-Kiki\n', conf)
self.check('---\n'
'Flow style: !!map {Clark: Evans, Ingy: döt Net}\n'
'Block style: !!seq\n'
'- Clark Evans\n'
'- Ingy döt Net\n', conf)
class ScalarIndentationTestCase(RuleTestCase):
rule_id = 'indentation'
@@ -507,7 +1223,7 @@ class ScalarIndentationTestCase(RuleTestCase):
self.check('a key: multi\n'
' line\n', conf)
self.check('a key: multi\n'
' line\n', conf, problem=(2, 3))
' line\n', conf)
self.check('a key: multi\n'
' line\n', conf)
self.check('a key:\n'
@@ -528,6 +1244,8 @@ class ScalarIndentationTestCase(RuleTestCase):
' line\n', conf, problem=(2, 2))
self.check('- multi\n'
' line\n', conf, problem=(2, 4))
self.check('a key: multi\n'
' line\n', conf, problem=(2, 3))
self.check('a key: multi\n'
' line\n', conf, problem=(2, 9))
self.check('a key:\n'
@@ -546,24 +1264,13 @@ class ScalarIndentationTestCase(RuleTestCase):
'document-start: disable\n')
self.check('"multi\n'
' line"\n', conf)
self.check('"multi\n'
'line"\n', conf, problem=(2, 1))
self.check('- "multi\n'
' line"\n', conf)
self.check('- "multi\n'
' line"\n', conf, problem=(2, 3))
self.check('a key: "multi\n'
' line"\n', conf)
self.check('a key: "multi\n'
' line"\n', conf, problem=(2, 3))
self.check('a key: "multi\n'
' line"\n', conf, problem=(2, 8))
self.check('a key:\n'
' "multi\n'
' line"\n', conf)
self.check('a key:\n'
' "multi\n'
' line"\n', conf, problem=(3, 3))
self.check('- jinja2: "{% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
@@ -575,16 +1282,33 @@ class ScalarIndentationTestCase(RuleTestCase):
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}"\n', conf)
self.check('["this is a very long line\n'
' that needs to be split",\n'
' "other line"]\n', conf)
self.check('["multi\n'
' line 1", "multi\n'
' line 2"]\n', conf)
def test_check_multi_line_quoted(self):
conf = ('indentation: {spaces: 2, check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('"multi\n'
'line"\n', conf, problem=(2, 1))
self.check('"multi\n'
' line"\n', conf, problem=(2, 3))
self.check('- "multi\n'
' line"\n', conf, problem=(2, 3))
self.check('- "multi\n'
' line"\n', conf, problem=(2, 5))
self.check('a key: "multi\n'
' line"\n', conf, problem=(2, 3))
self.check('a key: "multi\n'
' line"\n', conf, problem=(2, 8))
self.check('a key: "multi\n'
' line"\n', conf, problem=(2, 10))
self.check('a key:\n'
' "multi\n'
' line"\n', conf, problem=(3, 3))
self.check('a key:\n'
' "multi\n'
' line"\n', conf, problem=(3, 5))
@@ -601,6 +1325,24 @@ class ScalarIndentationTestCase(RuleTestCase):
' {{ chef }}\n'
' {% endif %}"\n', conf,
problem1=(3, 8), problem2=(5, 8))
self.check('["this is a very long line\n'
' that needs to be split",\n'
' "other line"]\n', conf)
self.check('["this is a very long line\n'
' that needs to be split",\n'
' "other line"]\n', conf, problem=(2, 2))
self.check('["this is a very long line\n'
' that needs to be split",\n'
' "other line"]\n', conf, problem=(2, 4))
self.check('["multi\n'
' line 1", "multi\n'
' line 2"]\n', conf)
self.check('["multi\n'
' line 1", "multi\n'
' line 2"]\n', conf, problem=(3, 12))
self.check('["multi\n'
' line 1", "multi\n'
' line 2"]\n', conf, problem=(3, 14))
def test_basics_folded_style(self):
conf = ('indentation: {spaces: 2, check-multi-line-strings: no}\n'
@@ -867,3 +1609,39 @@ class ScalarIndentationTestCase(RuleTestCase):
' paragraph gap, \\n and\n'
' spaces.\n', conf,
problem1=(3, 6), problem2=(5, 7), problem3=(6, 8))
def test_consistent(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('multi\n'
'line\n', conf)
self.check('multi\n'
' line\n', conf, problem=(2, 2))
self.check('- multi\n'
' line\n', conf)
self.check('- multi\n'
' line\n', conf, problem=(2, 4))
self.check('a key: multi\n'
' line\n', conf, problem=(2, 3))
self.check('a key: multi\n'
' line\n', conf, problem=(2, 9))
self.check('a key:\n'
' multi\n'
' line\n', conf, problem=(3, 4))
self.check('- C code: void main() {\n'
' printf("foo");\n'
' }\n', conf, problem=(2, 15))
self.check('- C code:\n'
' void main() {\n'
' printf("foo");\n'
' }\n', conf, problem=(3, 9))
self.check('>\n'
' multi\n'
' line\n', conf)
self.check('>\n'
' multi\n'
' line\n', conf)
self.check('>\n'
' multi\n'
' line\n', conf, problem=(3, 7))

View File

@@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016 Adrien Vergé
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.common import RuleTestCase
class KeyDuplicatesTestCase(RuleTestCase):
rule_id = 'key-duplicates'
def test_disabled(self):
conf = 'key-duplicates: disable'
self.check('---\n'
'block mapping:\n'
' key: a\n'
' otherkey: b\n'
' key: c\n', conf)
self.check('---\n'
'flow mapping:\n'
' {key: a, otherkey: b, key: c}\n', conf)
self.check('---\n'
'duplicated twice:\n'
' - k: a\n'
' ok: b\n'
' k: c\n'
' k: d\n', conf)
self.check('---\n'
'duplicated twice:\n'
' - {k: a, ok: b, k: c, k: d}\n', conf)
self.check('---\n'
'multiple duplicates:\n'
' a: 1\n'
' b: 2\n'
' c: 3\n'
' d: 4\n'
' d: 5\n'
' b: 6\n', conf)
self.check('---\n'
'multiple duplicates:\n'
' {a: 1, b: 2, c: 3, d: 4, d: 5, b: 6}\n', conf)
self.check('---\n'
'at: root\n'
'multiple: times\n'
'at: root\n', conf)
self.check('---\n'
'nested but OK:\n'
' a: {a: {a: 1}}\n'
' b:\n'
' b: 2\n'
' c: 3\n', conf)
self.check('---\n'
'nested duplicates:\n'
' a: {a: 1, a: 1}\n'
' b:\n'
' c: 3\n'
' d: 4\n'
' d: 4\n'
' b: 2\n', conf)
self.check('---\n'
'duplicates with many styles: 1\n'
'"duplicates with many styles": 1\n'
'\'duplicates with many styles\': 1\n'
'? duplicates with many styles\n'
': 1\n'
'? >-\n'
' duplicates with\n'
' many styles\n'
': 1\n', conf)
def test_enabled(self):
conf = 'key-duplicates: {}'
self.check('---\n'
'block mapping:\n'
' key: a\n'
' otherkey: b\n'
' key: c\n', conf,
problem=(5, 3))
self.check('---\n'
'flow mapping:\n'
' {key: a, otherkey: b, key: c}\n', conf,
problem=(3, 25))
self.check('---\n'
'duplicated twice:\n'
' - k: a\n'
' ok: b\n'
' k: c\n'
' k: d\n', conf,
problem1=(5, 5), problem2=(6, 5))
self.check('---\n'
'duplicated twice:\n'
' - {k: a, ok: b, k: c, k: d}\n', conf,
problem1=(3, 19), problem2=(3, 25))
self.check('---\n'
'multiple duplicates:\n'
' a: 1\n'
' b: 2\n'
' c: 3\n'
' d: 4\n'
' d: 5\n'
' b: 6\n', conf,
problem1=(7, 3), problem2=(8, 3))
self.check('---\n'
'multiple duplicates:\n'
' {a: 1, b: 2, c: 3, d: 4, d: 5, b: 6}\n', conf,
problem1=(3, 28), problem2=(3, 34))
self.check('---\n'
'at: root\n'
'multiple: times\n'
'at: root\n', conf,
problem=(4, 1))
self.check('---\n'
'nested but OK:\n'
' a: {a: {a: 1}}\n'
' b:\n'
' b: 2\n'
' c: 3\n', conf)
self.check('---\n'
'nested duplicates:\n'
' a: {a: 1, a: 1}\n'
' b:\n'
' c: 3\n'
' d: 4\n'
' d: 4\n'
' b: 2\n', conf,
problem1=(3, 13), problem2=(7, 5), problem3=(8, 3))
self.check('---\n'
'duplicates with many styles: 1\n'
'"duplicates with many styles": 1\n'
'\'duplicates with many styles\': 1\n'
'? duplicates with many styles\n'
': 1\n'
'? >-\n'
' duplicates with\n'
' many styles\n'
': 1\n', conf,
problem1=(3, 1), problem2=(4, 1), problem3=(5, 3),
problem4=(7, 3))
def test_key_tokens_in_flow_sequences(self):
conf = 'key-duplicates: {}'
self.check('---\n'
'[\n'
' flow: sequence, with, key: value, mappings\n'
']\n', conf)

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class LineLengthTestCase(RuleTestCase):
@@ -43,17 +43,17 @@ class LineLengthTestCase(RuleTestCase):
self.check('---\n', conf)
self.check(80 * 'a', conf)
self.check('---\n' + 80 * 'a' + '\n', conf)
self.check(81 * 'a', conf, problem=(1, 81))
self.check('---\n' + 81 * 'a' + '\n', conf, problem=(2, 81))
self.check(1000 * 'b', conf, problem=(1, 81))
self.check('---\n' + 1000 * 'b' + '\n', conf, problem=(2, 81))
self.check(16 * 'aaaa ' + 'z', conf, problem=(1, 81))
self.check('---\n' + 16 * 'aaaa ' + 'z' + '\n', conf, problem=(2, 81))
self.check(1000 * 'word ' + 'end', conf, problem=(1, 81))
self.check('---\n' + 1000 * 'word ' + 'end\n', conf, problem=(2, 81))
def test_max_length_10(self):
conf = ('line-length: {max: 10}\n'
'new-line-at-end-of-file: disable\n')
self.check('---\nABCDEFGHIJ', conf)
self.check('---\nABCDEFGHIJK', conf, problem=(2, 11))
self.check('---\nABCDEFGHIJK\n', conf, problem=(2, 11))
self.check('---\nABCD EFGHI', conf)
self.check('---\nABCD EFGHIJ', conf, problem=(2, 11))
self.check('---\nABCD EFGHIJ\n', conf, problem=(2, 11))
def test_spaces(self):
conf = ('line-length: {max: 80}\n'
@@ -61,3 +61,36 @@ class LineLengthTestCase(RuleTestCase):
'trailing-spaces: disable\n')
self.check('---\n' + 81 * ' ', conf, problem=(2, 81))
self.check('---\n' + 81 * ' ' + '\n', conf, problem=(2, 81))
def test_non_breakable_word(self):
conf = 'line-length: {max: 20, allow-non-breakable-words: yes}'
self.check('---\n' + 30 * 'A' + '\n', conf)
self.check('---\n'
'this:\n'
' is:\n'
' - a:\n'
' http://localhost/very/long/url\n'
'...\n', conf)
self.check('---\n'
'this:\n'
' is:\n'
' - a:\n'
' # http://localhost/very/long/url\n'
' comment\n'
'...\n', conf)
conf = 'line-length: {max: 20, allow-non-breakable-words: no}'
self.check('---\n' + 30 * 'A' + '\n', conf, problem=(2, 21))
self.check('---\n'
'this:\n'
' is:\n'
' - a:\n'
' http://localhost/very/long/url\n'
'...\n', conf, problem=(5, 21))
self.check('---\n'
'this:\n'
' is:\n'
' - a:\n'
' # http://localhost/very/long/url\n'
' comment\n'
'...\n', conf, problem=(5, 21))

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class NewLineAtEndOfFileTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class NewLinesTestCase(RuleTestCase):

View File

@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class TrailingSpacesTestCase(RuleTestCase):

View File

@@ -58,6 +58,53 @@ class SimpleConfigTestCase(unittest.TestCase):
' max-spaces-after: 1\n'
' abcdef: yes\n')
def test_validate_rule_conf(self):
class Rule(object):
ID = 'fake'
self.assertEqual(config.validate_rule_conf(Rule, False), False)
self.assertEqual(config.validate_rule_conf(Rule, 'disable'), False)
config.validate_rule_conf(Rule, {'level': 'error'})
config.validate_rule_conf(Rule, {'level': 'warning'})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'level': 'warn'})
Rule.CONF = {'length': int}
config.validate_rule_conf(Rule, {'length': 8})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'height': 8})
Rule.CONF = {'a': bool, 'b': int}
config.validate_rule_conf(Rule, {'a': True, 'b': 0})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'a': True})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'b': 0})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'a': 1, 'b': 0})
Rule.CONF = {'choice': (True, 88, 'str')}
config.validate_rule_conf(Rule, {'choice': True})
config.validate_rule_conf(Rule, {'choice': 88})
config.validate_rule_conf(Rule, {'choice': 'str'})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'choice': False})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'choice': 99})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'choice': 'abc'})
Rule.CONF = {'choice': (int, 'hardcoded')}
config.validate_rule_conf(Rule, {'choice': 42})
config.validate_rule_conf(Rule, {'choice': 'hardcoded'})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'choice': False})
self.assertRaises(config.YamlLintConfigError,
config.validate_rule_conf, Rule, {'choice': 'abc'})
class ExtendedConfigTestCase(unittest.TestCase):
def test_extend_add_rule(self):

46
tests/test_linter.py Normal file
View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016 Adrien Vergé
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import io
import unittest
from yamllint.config import YamlLintConfig
from yamllint import linter
class LinterTestCase(unittest.TestCase):
def fake_config(self):
return YamlLintConfig('extends: default')
def test_run_on_string(self):
linter.run('test: document', self.fake_config())
def test_run_on_bytes(self):
linter.run(b'test: document', self.fake_config())
def test_run_on_unicode(self):
linter.run(u'test: document', self.fake_config())
def test_run_on_stream(self):
linter.run(io.StringIO(u'hello'), self.fake_config())
def test_run_on_int(self):
self.assertRaises(TypeError, linter.run, 42, self.fake_config())
def test_run_on_list(self):
self.assertRaises(TypeError, linter.run,
['h', 'e', 'l', 'l', 'o'], self.fake_config())

186
tests/test_spec_examples.py Normal file
View File

@@ -0,0 +1,186 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016 Adrien Vergé
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from io import open
import os
from tests.common import RuleTestCase
# This file checks examples from YAML 1.2 specification [1] against yamllint.
#
# [1]: http://www.yaml.org/spec/1.2/spec.html
#
# Example files generated with:
#
# from bs4 import BeautifulSoup
# with open('spec.html', encoding='iso-8859-1') as f:
# soup = BeautifulSoup(f, 'lxml')
# for ex in soup.find_all('div', class_='example'):
# title = ex.find('p', class_='title').find('b').get_text()
# id = '-'.join(title.split('\xa0')[:2])[:-1].lower()
# span = ex.find('span', class_='database')
# for br in span.find_all("br"):
# br.replace_with("\n")
# text = text.replace('\u2193', '') # downwards arrow
# text = text.replace('\u21d3', '') # double downwards arrow
# text = text.replace('\u00b7', ' ') # visible space
# text = text.replace('\u21d4', '') # byte order mark
# text = text.replace('\u2192', '\t') # right arrow
# text = text.replace('\u00b0', '') # empty scalar
# with open('tests/yaml-1.2-spec-examples/%s' % id, 'w',
# encoding='utf-8') as g:
# g.write(text)
class SpecificationTestCase(RuleTestCase):
rule_id = None
conf_general = ('document-start: disable\n'
'comments: {min-spaces-from-content: 1}\n'
'braces: {min-spaces-inside: 1, max-spaces-inside: 1}\n'
'brackets: {min-spaces-inside: 1, max-spaces-inside: 1}\n')
conf_overrides = {
'example-2.2': ('colons: {max-spaces-after: 2}\n'),
'example-2.4': ('colons: {max-spaces-after: 3}\n'),
'example-2.5': ('empty-lines: {max-end: 2}\n'
'brackets: {min-spaces-inside: 0, max-spaces-inside: 2}\n'
'commas: {max-spaces-before: -1}\n'),
'example-2.6': ('braces: {min-spaces-inside: 0, max-spaces-inside: 0}\n'
'indentation: disable\n'),
'example-2.12': ('empty-lines: {max-end: 1}\n'
'colons: {max-spaces-before: -1}\n'),
'example-2.16': ('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.28': ('empty-lines: {max-end: 3}\n'),
'example-5.3': ('indentation: {indent-sequences: no}\n'
'colons: {max-spaces-before: 1}\n'),
'example-6.4': ('trailing-spaces: disable\n'),
'example-6.5': ('trailing-spaces: disable\n'),
'example-6.6': ('trailing-spaces: disable\n'),
'example-6.7': ('trailing-spaces: disable\n'),
'example-6.8': ('trailing-spaces: disable\n'),
'example-6.10': ('empty-lines: {max-end: 2}\n'
'trailing-spaces: disable\n'
'comments-indentation: disable\n'),
'example-6.11': ('empty-lines: {max-end: 1}\n'
'comments-indentation: disable\n'),
'example-6.13': ('comments-indentation: disable\n'),
'example-6.14': ('comments-indentation: disable\n'),
'example-6.23': ('colons: {max-spaces-before: 1}\n'),
'example-7.4': ('colons: {max-spaces-before: 1}\n'
'indentation: disable\n'),
'example-7.5': ('trailing-spaces: disable\n'),
'example-7.6': ('trailing-spaces: disable\n'),
'example-7.7': ('indentation: disable\n'),
'example-7.8': ('colons: {max-spaces-before: 1}\n'
'indentation: disable\n'),
'example-7.9': ('trailing-spaces: disable\n'),
'example-7.11': ('colons: {max-spaces-before: 1}\n'
'indentation: disable\n'),
'example-7.13': ('brackets: {min-spaces-inside: 0, max-spaces-inside: 1}\n'
'commas: {max-spaces-before: 1, min-spaces-after: 0}\n'),
'example-7.14': ('indentation: disable\n'),
'example-7.15': ('braces: {min-spaces-inside: 0, max-spaces-inside: 1}\n'
'commas: {max-spaces-before: 1, min-spaces-after: 0}\n'
'colons: {max-spaces-before: 1}\n'),
'example-7.16': ('indentation: disable\n'),
'example-7.17': ('indentation: disable\n'),
'example-7.18': ('indentation: disable\n'),
'example-7.19': ('indentation: disable\n'),
'example-7.20': ('colons: {max-spaces-before: 1}\n'
'indentation: disable\n'),
'example-8.1': ('empty-lines: {max-end: 1}\n'),
'example-8.2': ('trailing-spaces: disable\n'),
'example-8.5': ('comments-indentation: disable\n'
'trailing-spaces: disable\n'),
'example-8.6': ('empty-lines: {max-end: 1}\n'),
'example-8.7': ('empty-lines: {max-end: 1}\n'),
'example-8.8': ('trailing-spaces: disable\n'),
'example-8.9': ('empty-lines: {max-end: 1}\n'),
'example-8.14': ('colons: {max-spaces-before: 1}\n'),
'example-8.16': ('indentation: {spaces: 1}\n'),
'example-8.17': ('indentation: disable\n'),
'example-8.20': ('indentation: {indent-sequences: no}\n'
'colons: {max-spaces-before: 1}\n'),
'example-8.22': ('indentation: disable\n'),
'example-10.1': ('colons: {max-spaces-before: 2}\n'),
'example-10.2': ('indentation: {indent-sequences: no}\n'),
}
files = os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)),
'yaml-1.2-spec-examples'))
assert len(files) == 132
def _gen_test(buffer, conf):
def test(self):
self.check(buffer, conf)
return test
# The following tests are blacklisted (i.e. will not be checked against
# yamllint), because pyyaml is currently not able to parse the contents
# (using yaml.parse()).
pyyaml_blacklist = (
'example-2.11',
'example-2.23',
'example-2.24',
'example-2.27',
'example-5.10',
'example-5.12',
'example-5.13',
'example-5.14',
'example-5.6',
'example-6.1',
'example-6.12',
'example-6.15',
'example-6.17',
'example-6.18',
'example-6.19',
'example-6.2',
'example-6.20',
'example-6.21',
'example-6.22',
'example-6.24',
'example-6.25',
'example-6.26',
'example-6.27',
'example-6.3',
'example-7.1',
'example-7.10',
'example-7.12',
'example-7.17',
'example-7.2',
'example-7.21',
'example-7.22',
'example-7.3',
'example-8.18',
'example-8.19',
'example-8.21',
'example-8.3',
'example-9.3',
'example-9.4',
'example-9.5',
)
for file in files:
if file in pyyaml_blacklist:
continue
with open('tests/yaml-1.2-spec-examples/' + file, encoding='utf-8') as f:
conf = conf_general + conf_overrides.get(file, '')
setattr(SpecificationTestCase, 'test_' + file,
_gen_test(f.read(), conf))

View File

@@ -14,13 +14,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from tests.rules.common import RuleTestCase
from tests.common import RuleTestCase
class YamlLintTestCase(RuleTestCase):
rule_id = None # syntax error
def test_lint(self):
def test_syntax_errors(self):
self.check('---\n'
'this is not: valid: YAML\n', None, problem=(2, 19))
self.check('---\n'
@@ -29,13 +29,21 @@ class YamlLintTestCase(RuleTestCase):
'this is an error: [\n'
'\n'
'...\n', None, problem=(6, 1))
def test_directives(self):
self.check('%YAML 1.2\n'
'%TAG ! tag:clarkevans.com,2002:\n'
'doc: ument\n'
'...\n', None, problem=(3, 1))
def test_empty_flows(self):
self.check('---\n'
'- []\n'
'- {}\n'
'- [\n'
']\n'
'- {\n'
'}\n'
'...\n', None)
def test_explicit_mapping(self):
self.check('---\n'
'? key\n'
@@ -67,3 +75,20 @@ class YamlLintTestCase(RuleTestCase):
' Atlanta Braves]\n'
': [2001-07-02, 2001-08-12,\n'
' 2001-08-14]\n', None)
def test_sets(self):
self.check('---\n'
'? key one\n'
'? key two\n'
'? [non, scalar, key]\n'
'? key with value\n'
': value\n'
'...\n', None)
self.check('---\n'
'? - multi\n'
' - line\n'
' - keys\n'
'? in:\n'
' a:\n'
' set\n'
'...\n', None)

View File

@@ -0,0 +1,6 @@
Block style: !!map
Clark : Evans
Ingy : döt Net
Oren : Ben-Kiki
Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }

View File

@@ -0,0 +1,6 @@
Block style: !!seq
- Clark Evans
- Ingy döt Net
- Oren Ben-Kiki
Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]

View File

@@ -0,0 +1,4 @@
Block style: !!str |-
String: just a theory.
Flow style: !!str "String: just a theory."

View File

@@ -0,0 +1,2 @@
!!null null: value for null key
key with null value: !!null null

View File

@@ -0,0 +1,2 @@
YAML is a superset of JSON: !!bool true
Pluto is a planet: !!bool false

View File

@@ -0,0 +1,3 @@
negative: !!int -12
zero: !!int 0
positive: !!int 34

View File

@@ -0,0 +1,5 @@
negative: !!float -1
zero: !!float 0
positive: !!float 2.3e4
infinity: !!float .inf
not a number: !!float .nan

View File

@@ -0,0 +1,5 @@
A null: null
Booleans: [ true, false ]
Integers: [ 0, -0, 3, -19 ]
Floats: [ 0., -0.0, 12e03, -2E+05 ]
Invalid: [ True, Null, 0o7, 0x3A, +12.3 ]

View File

@@ -0,0 +1,7 @@
A null: null
Also a null: # Empty
Not a null: ""
Booleans: [ true, True, false, FALSE ]
Integers: [ 0, 0o7, 0x3A, -19 ]
Floats: [ 0., -0.0, .5, +12e03, -2E+05 ]
Also floats: [ .inf, -.Inf, +.INF, .NAN ]

View File

@@ -0,0 +1,3 @@
- Mark McGwire
- Sammy Sosa
- Ken Griffey

View File

@@ -0,0 +1,8 @@
---
hr:
- Mark McGwire
# Following node labeled SS
- &SS Sammy Sosa
rbi:
- *SS # Subsequent occurrence
- Ken Griffey

View File

@@ -0,0 +1,9 @@
? - Detroit Tigers
- Chicago cubs
:
- 2001-07-23
? [ New York Yankees,
Atlanta Braves ]
: [ 2001-07-02, 2001-08-12,
2001-08-14 ]

View File

@@ -0,0 +1,9 @@
---
# Products purchased
- item : Super Hoop
quantity: 1
- item : Basketball
quantity: 4
- item : Big Shoes
quantity: 1

View File

@@ -0,0 +1,4 @@
# ASCII Art
--- |
\//||\/||
// || ||__

View File

@@ -0,0 +1,4 @@
--- >
Mark McGwire's
year was crippled
by a knee injury.

View File

@@ -0,0 +1,8 @@
>
Sammy Sosa completed another
fine season with great stats.
63 Home Runs
0.288 Batting Average
What a year!

View File

@@ -0,0 +1,8 @@
name: Mark McGwire
accomplishment: >
Mark set a major league
home run record in 1998.
stats: |
65 Home Runs
0.278 Batting Average

View File

@@ -0,0 +1,7 @@
unicode: "Sosa did fine.\u263A"
control: "\b1998\t1999\t2000\n"
hex esc: "\x0d\x0a is \r\n"
single: '"Howdy!" he cried.'
quoted: ' # Not a ''comment''.'
tie-fighter: '|\-*-/|'

View File

@@ -0,0 +1,7 @@
plain:
This unquoted scalar
spans many lines.
quoted: "So does this
quoted scalar.\n"

View File

@@ -0,0 +1,5 @@
canonical: 12345
decimal: +12345
octal: 0o14
hexadecimal: 0xC

View File

@@ -0,0 +1,3 @@
hr: 65 # Home runs
avg: 0.278 # Batting average
rbi: 147 # Runs Batted In

View File

@@ -0,0 +1,5 @@
canonical: 1.23015e+3
exponential: 12.3015e+02
fixed: 1230.15
negative infinity: -.inf
not a number: .NaN

View File

@@ -0,0 +1,3 @@
null:
booleans: [ true, false ]
string: '012345'

View File

@@ -0,0 +1,4 @@
canonical: 2001-12-15T02:59:43.1Z
iso8601: 2001-12-14t21:59:43.10-05:00
spaced: 2001-12-14 21:59:43.10 -5
date: 2002-12-14

View File

@@ -0,0 +1,14 @@
---
not-date: !!str 2002-04-28
picture: !!binary |
R0lGODlhDAAMAIQAAP//9/X
17unp5WZmZgAAAOfn515eXv
Pz7Y6OjuDg4J+fn5OTk6enp
56enmleECcgggoBADs=
application specific tag: !something |
The semantics of the tag
above may be different for
different documents.

View File

@@ -0,0 +1,14 @@
%TAG ! tag:clarkevans.com,2002:
--- !shape
# Use the ! handle for presenting
# tag:clarkevans.com,2002:circle
- !circle
center: &ORIGIN {x: 73, y: 129}
radius: 7
- !line
start: *ORIGIN
finish: { x: 89, y: 102 }
- !label
start: *ORIGIN
color: 0xFFEEBB
text: Pretty vector drawing.

View File

@@ -0,0 +1,7 @@
# Sets are represented as a
# Mapping where each key is
# associated with a null value
--- !!set
? Mark McGwire
? Sammy Sosa
? Ken Griff

View File

@@ -0,0 +1,7 @@
# Ordered maps are represented as
# A sequence of mappings, with
# each mapping having one key
--- !!omap
- Mark McGwire: 65
- Sammy Sosa: 63
- Ken Griffy: 58

View File

@@ -0,0 +1,29 @@
--- !<tag:clarkevans.com,2002:invoice>
invoice: 34843
date : 2001-01-23
bill-to: &id001
given : Chris
family : Dumars
address:
lines: |
458 Walkman Dr.
Suite #292
city : Royal Oak
state : MI
postal : 48046
ship-to: *id001
product:
- sku : BL394D
quantity : 4
description : Basketball
price : 450.00
- sku : BL4438H
quantity : 1
description : Super Hoop
price : 2392.00
tax : 251.42
total: 4443.52
comments:
Late afternoon is best.
Backup contact is Nancy
Billsmer @ 338-4338.

View File

@@ -0,0 +1,29 @@
---
Time: 2001-11-23 15:01:42 -5
User: ed
Warning:
This is an error message
for the log file
---
Time: 2001-11-23 15:02:31 -5
User: ed
Warning:
A slightly different error
message.
---
Date: 2001-11-23 15:03:17 -5
User: ed
Fatal:
Unknown variable "bar"
Stack:
- file: TopClass.py
line: 23
code: |
x = MoreObject("345\n")
- file: MoreClass.py
line: 58
code: |-
foo = bar

View File

@@ -0,0 +1,8 @@
american:
- Boston Red Sox
- Detroit Tigers
- New York Yankees
national:
- New York Mets
- Chicago Cubs
- Atlanta Braves

View File

@@ -0,0 +1,8 @@
-
name: Mark McGwire
hr: 65
avg: 0.278
-
name: Sammy Sosa
hr: 63
avg: 0.288

View File

@@ -0,0 +1,5 @@
- [name , hr, avg ]
- [Mark McGwire, 65, 0.278]
- [Sammy Sosa , 63, 0.288]

View File

@@ -0,0 +1,5 @@
Mark McGwire: {hr: 65, avg: 0.278}
Sammy Sosa: {
hr: 63,
avg: 0.288
}

View File

@@ -0,0 +1,10 @@
# Ranking of 1998 home runs
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# Team ranking
---
- Chicago Cubs
- St Louis Cardinals

View File

@@ -0,0 +1,10 @@
---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
---
time: 20:03:47
player: Sammy Sosa
action: grand slam
...

View File

@@ -0,0 +1,8 @@
---
hr: # 1998 hr ranking
- Mark McGwire
- Sammy Sosa
rbi:
# 1998 rbi ranking
- Sammy Sosa
- Ken Griffey

View File

@@ -0,0 +1 @@
# Comment only.

View File

@@ -0,0 +1,2 @@
commercial-at: @text
grave-accent: `text

View File

@@ -0,0 +1,3 @@
|
Line break (no glyph)
Line break (glyphed)

View File

@@ -0,0 +1,6 @@
# Tabs and spaces
quoted: "Quoted "
block: |
void main() {
printf("Hello, world!\n");
}

View File

@@ -0,0 +1,5 @@
"Fun with \\
\" \a \b \e \f \
\n \r \t \v \0 \
\  \_ \N \L \P \
\x41 \u0041 \U00000041"

View File

@@ -0,0 +1,3 @@
Bad escapes:
"\c
\xq-"

View File

@@ -0,0 +1,3 @@
- Invalid use of BOM
- Inside a document.

View File

@@ -0,0 +1,7 @@
sequence:
- one
- two
mapping:
? sky
: blue
sea : green

View File

@@ -0,0 +1,2 @@
sequence: [ one, two, ]
mapping: { sky: blue, sea: green }

View File

@@ -0,0 +1 @@
# Comment only.

View File

@@ -0,0 +1,2 @@
anchored: !local &anchor value
alias: *anchor

View File

@@ -0,0 +1,6 @@
literal: |
some
text
folded: >
some
text

View File

@@ -0,0 +1,2 @@
single: 'text'
double: "text"

View File

@@ -0,0 +1,2 @@
%YAML 1.2
--- text

View File

@@ -0,0 +1,12 @@
# Leading comment line spaces are
# neither content nor indentation.
Not indented:
By one space: |
By four
spaces
Flow style: [ # Leading spaces
By two, # in flow style
Also by two, # are neither
Still by two # content nor
] # indentation.

View File

@@ -0,0 +1,3 @@
# Comment

View File

@@ -0,0 +1,4 @@
key: # Comment
# lines
value

View File

@@ -0,0 +1,6 @@
{ first: Sammy, last: Sosa }:
# Statistics:
hr: # Home runs
65
avg: # Average
0.278

View File

@@ -0,0 +1,3 @@
%FOO bar baz # Should be ignored
# with a warning.
--- "foo"

View File

@@ -0,0 +1,4 @@
%YAML 1.3 # Attempt parsing
# with a warning
---
"foo"

View File

@@ -0,0 +1,3 @@
%YAML 1.2
%YAML 1.1
foo

View File

@@ -0,0 +1,3 @@
%TAG !yaml! tag:yaml.org,2002:
---
!yaml!str "foo"

View File

@@ -0,0 +1,3 @@
%TAG ! !foo
%TAG ! !foo
bar

View File

@@ -0,0 +1,7 @@
# Private
!foo "bar"
...
# Global
%TAG ! tag:example.com,2000:app/
---
!foo "bar"

View File

@@ -0,0 +1,3 @@
%TAG !! tag:example.com,2000:app/
---
!!int 1 - 3 # Interval, not integer

View File

@@ -0,0 +1,4 @@
? a
: - b
- - c
- d

View File

@@ -0,0 +1,3 @@
%TAG !e! tag:example.com,2000:app/
---
!e!foo "bar"

View File

@@ -0,0 +1,7 @@
%TAG !m! !my-
--- # Bulb here
!m!light fluorescent
...
%TAG !m! !my-
--- # Color here
!m!light green

View File

@@ -0,0 +1,3 @@
%TAG !e! tag:example.com,2000:app/
---
- !e!foo "bar"

View File

@@ -0,0 +1,3 @@
!!str &a1 "foo":
!!str bar
&a2 baz : *a1

View File

@@ -0,0 +1,2 @@
!<tag:yaml.org,2002:str> foo :
!<!bar> baz

View File

@@ -0,0 +1,2 @@
- !<!> foo
- !<$:?> bar

Some files were not shown because too many files have changed in this diff Show More