yamllint-1.2.1/ 0000775 0001750 0001750 00000000000 12675233100 014073 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/yamllint.egg-info/ 0000775 0001750 0001750 00000000000 12675233100 017416 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/yamllint.egg-info/SOURCES.txt 0000664 0001750 0001750 00000016221 12675233100 021304 0 ustar adrien adrien 0000000 0000000 LICENSE
MANIFEST.in
README.rst
setup.py
docs/Makefile
docs/conf.py
docs/configuration.rst
docs/development.rst
docs/index.rst
docs/quickstart.rst
docs/rules.rst
docs/screenshot.png
docs/text_editors.rst
tests/__init__.py
tests/common.py
tests/test_cli.py
tests/test_config.py
tests/test_linter.py
tests/test_parser.py
tests/test_spec_examples.py
tests/test_syntax_errors.py
tests/rules/__init__.py
tests/rules/test_braces.py
tests/rules/test_brackets.py
tests/rules/test_colons.py
tests/rules/test_commas.py
tests/rules/test_comments.py
tests/rules/test_comments_indentation.py
tests/rules/test_common.py
tests/rules/test_document_end.py
tests/rules/test_document_start.py
tests/rules/test_empty_lines.py
tests/rules/test_hyphens.py
tests/rules/test_indentation.py
tests/rules/test_key_duplicates.py
tests/rules/test_line_length.py
tests/rules/test_new_line_at_end_of_file.py
tests/rules/test_new_lines.py
tests/rules/test_trailing_spaces.py
tests/yaml-1.2-spec-examples/example-10.1
tests/yaml-1.2-spec-examples/example-10.2
tests/yaml-1.2-spec-examples/example-10.3
tests/yaml-1.2-spec-examples/example-10.4
tests/yaml-1.2-spec-examples/example-10.5
tests/yaml-1.2-spec-examples/example-10.6
tests/yaml-1.2-spec-examples/example-10.7
tests/yaml-1.2-spec-examples/example-10.8
tests/yaml-1.2-spec-examples/example-10.9
tests/yaml-1.2-spec-examples/example-2.1
tests/yaml-1.2-spec-examples/example-2.10
tests/yaml-1.2-spec-examples/example-2.11
tests/yaml-1.2-spec-examples/example-2.12
tests/yaml-1.2-spec-examples/example-2.13
tests/yaml-1.2-spec-examples/example-2.14
tests/yaml-1.2-spec-examples/example-2.15
tests/yaml-1.2-spec-examples/example-2.16
tests/yaml-1.2-spec-examples/example-2.17
tests/yaml-1.2-spec-examples/example-2.18
tests/yaml-1.2-spec-examples/example-2.19
tests/yaml-1.2-spec-examples/example-2.2
tests/yaml-1.2-spec-examples/example-2.20
tests/yaml-1.2-spec-examples/example-2.21
tests/yaml-1.2-spec-examples/example-2.22
tests/yaml-1.2-spec-examples/example-2.23
tests/yaml-1.2-spec-examples/example-2.24
tests/yaml-1.2-spec-examples/example-2.25
tests/yaml-1.2-spec-examples/example-2.26
tests/yaml-1.2-spec-examples/example-2.27
tests/yaml-1.2-spec-examples/example-2.28
tests/yaml-1.2-spec-examples/example-2.3
tests/yaml-1.2-spec-examples/example-2.4
tests/yaml-1.2-spec-examples/example-2.5
tests/yaml-1.2-spec-examples/example-2.6
tests/yaml-1.2-spec-examples/example-2.7
tests/yaml-1.2-spec-examples/example-2.8
tests/yaml-1.2-spec-examples/example-2.9
tests/yaml-1.2-spec-examples/example-5.1
tests/yaml-1.2-spec-examples/example-5.10
tests/yaml-1.2-spec-examples/example-5.11
tests/yaml-1.2-spec-examples/example-5.12
tests/yaml-1.2-spec-examples/example-5.13
tests/yaml-1.2-spec-examples/example-5.14
tests/yaml-1.2-spec-examples/example-5.2
tests/yaml-1.2-spec-examples/example-5.3
tests/yaml-1.2-spec-examples/example-5.4
tests/yaml-1.2-spec-examples/example-5.5
tests/yaml-1.2-spec-examples/example-5.6
tests/yaml-1.2-spec-examples/example-5.7
tests/yaml-1.2-spec-examples/example-5.8
tests/yaml-1.2-spec-examples/example-5.9
tests/yaml-1.2-spec-examples/example-6.1
tests/yaml-1.2-spec-examples/example-6.10
tests/yaml-1.2-spec-examples/example-6.11
tests/yaml-1.2-spec-examples/example-6.12
tests/yaml-1.2-spec-examples/example-6.13
tests/yaml-1.2-spec-examples/example-6.14
tests/yaml-1.2-spec-examples/example-6.15
tests/yaml-1.2-spec-examples/example-6.16
tests/yaml-1.2-spec-examples/example-6.17
tests/yaml-1.2-spec-examples/example-6.18
tests/yaml-1.2-spec-examples/example-6.19
tests/yaml-1.2-spec-examples/example-6.2
tests/yaml-1.2-spec-examples/example-6.20
tests/yaml-1.2-spec-examples/example-6.21
tests/yaml-1.2-spec-examples/example-6.22
tests/yaml-1.2-spec-examples/example-6.23
tests/yaml-1.2-spec-examples/example-6.24
tests/yaml-1.2-spec-examples/example-6.25
tests/yaml-1.2-spec-examples/example-6.26
tests/yaml-1.2-spec-examples/example-6.27
tests/yaml-1.2-spec-examples/example-6.28
tests/yaml-1.2-spec-examples/example-6.29
tests/yaml-1.2-spec-examples/example-6.3
tests/yaml-1.2-spec-examples/example-6.4
tests/yaml-1.2-spec-examples/example-6.5
tests/yaml-1.2-spec-examples/example-6.6
tests/yaml-1.2-spec-examples/example-6.7
tests/yaml-1.2-spec-examples/example-6.8
tests/yaml-1.2-spec-examples/example-6.9
tests/yaml-1.2-spec-examples/example-7.1
tests/yaml-1.2-spec-examples/example-7.10
tests/yaml-1.2-spec-examples/example-7.11
tests/yaml-1.2-spec-examples/example-7.12
tests/yaml-1.2-spec-examples/example-7.13
tests/yaml-1.2-spec-examples/example-7.14
tests/yaml-1.2-spec-examples/example-7.15
tests/yaml-1.2-spec-examples/example-7.16
tests/yaml-1.2-spec-examples/example-7.17
tests/yaml-1.2-spec-examples/example-7.18
tests/yaml-1.2-spec-examples/example-7.19
tests/yaml-1.2-spec-examples/example-7.2
tests/yaml-1.2-spec-examples/example-7.20
tests/yaml-1.2-spec-examples/example-7.21
tests/yaml-1.2-spec-examples/example-7.22
tests/yaml-1.2-spec-examples/example-7.23
tests/yaml-1.2-spec-examples/example-7.24
tests/yaml-1.2-spec-examples/example-7.3
tests/yaml-1.2-spec-examples/example-7.4
tests/yaml-1.2-spec-examples/example-7.5
tests/yaml-1.2-spec-examples/example-7.6
tests/yaml-1.2-spec-examples/example-7.7
tests/yaml-1.2-spec-examples/example-7.8
tests/yaml-1.2-spec-examples/example-7.9
tests/yaml-1.2-spec-examples/example-8.1
tests/yaml-1.2-spec-examples/example-8.10
tests/yaml-1.2-spec-examples/example-8.11
tests/yaml-1.2-spec-examples/example-8.12
tests/yaml-1.2-spec-examples/example-8.13
tests/yaml-1.2-spec-examples/example-8.14
tests/yaml-1.2-spec-examples/example-8.15
tests/yaml-1.2-spec-examples/example-8.16
tests/yaml-1.2-spec-examples/example-8.17
tests/yaml-1.2-spec-examples/example-8.18
tests/yaml-1.2-spec-examples/example-8.19
tests/yaml-1.2-spec-examples/example-8.2
tests/yaml-1.2-spec-examples/example-8.20
tests/yaml-1.2-spec-examples/example-8.21
tests/yaml-1.2-spec-examples/example-8.22
tests/yaml-1.2-spec-examples/example-8.3
tests/yaml-1.2-spec-examples/example-8.4
tests/yaml-1.2-spec-examples/example-8.5
tests/yaml-1.2-spec-examples/example-8.6
tests/yaml-1.2-spec-examples/example-8.7
tests/yaml-1.2-spec-examples/example-8.8
tests/yaml-1.2-spec-examples/example-8.9
tests/yaml-1.2-spec-examples/example-9.1
tests/yaml-1.2-spec-examples/example-9.2
tests/yaml-1.2-spec-examples/example-9.3
tests/yaml-1.2-spec-examples/example-9.4
tests/yaml-1.2-spec-examples/example-9.5
tests/yaml-1.2-spec-examples/example-9.6
yamllint/__init__.py
yamllint/cli.py
yamllint/config.py
yamllint/linter.py
yamllint/parser.py
yamllint.egg-info/PKG-INFO
yamllint.egg-info/SOURCES.txt
yamllint.egg-info/dependency_links.txt
yamllint.egg-info/entry_points.txt
yamllint.egg-info/requires.txt
yamllint.egg-info/top_level.txt
yamllint/conf/default.yaml
yamllint/conf/relaxed.yaml
yamllint/rules/__init__.py
yamllint/rules/braces.py
yamllint/rules/brackets.py
yamllint/rules/colons.py
yamllint/rules/commas.py
yamllint/rules/comments.py
yamllint/rules/comments_indentation.py
yamllint/rules/common.py
yamllint/rules/document_end.py
yamllint/rules/document_start.py
yamllint/rules/empty_lines.py
yamllint/rules/hyphens.py
yamllint/rules/indentation.py
yamllint/rules/key_duplicates.py
yamllint/rules/line_length.py
yamllint/rules/new_line_at_end_of_file.py
yamllint/rules/new_lines.py
yamllint/rules/trailing_spaces.py yamllint-1.2.1/yamllint.egg-info/entry_points.txt 0000664 0001750 0001750 00000000057 12675233100 022716 0 ustar adrien adrien 0000000 0000000 [console_scripts]
yamllint = yamllint.cli:run
yamllint-1.2.1/yamllint.egg-info/top_level.txt 0000664 0001750 0001750 00000000017 12675233100 022146 0 ustar adrien adrien 0000000 0000000 tests
yamllint
yamllint-1.2.1/yamllint.egg-info/requires.txt 0000664 0001750 0001750 00000000007 12675233100 022013 0 ustar adrien adrien 0000000 0000000 pyyaml
yamllint-1.2.1/yamllint.egg-info/PKG-INFO 0000664 0001750 0001750 00000001771 12675233100 020521 0 ustar adrien adrien 0000000 0000000 Metadata-Version: 1.1
Name: yamllint
Version: 1.2.1
Summary: A linter for YAML files.
Home-page: https://github.com/adrienverge/yamllint
Author: Adrien Vergé
Author-email: UNKNOWN
License: GPLv3
Description: 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.
Keywords: yaml,lint,linter,syntax,checker
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Debuggers
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
yamllint-1.2.1/yamllint.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12675233100 023464 0 ustar adrien adrien 0000000 0000000
yamllint-1.2.1/MANIFEST.in 0000664 0001750 0001750 00000000062 12666346130 015637 0 ustar adrien adrien 0000000 0000000 include LICENSE
include README.rst
include docs/*
yamllint-1.2.1/tests/ 0000775 0001750 0001750 00000000000 12675233100 015235 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/tests/test_config.py 0000664 0001750 0001750 00000024400 12675231644 020126 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import unittest
from yamllint import config
class SimpleConfigTestCase(unittest.TestCase):
def test_parse_config(self):
new = config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 0\n'
' max-spaces-after: 1\n')
self.assertEqual(list(new.rules.keys()), ['colons'])
self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
self.assertEqual(len(new.enabled_rules()), 1)
def test_invalid_conf(self):
with self.assertRaises(config.YamlLintConfigError):
config.YamlLintConfig('not: valid: yaml')
def test_unknown_rule(self):
with self.assertRaisesRegexp(
config.YamlLintConfigError,
'invalid config: no such rule: "this-one-does-not-exist"'):
config.YamlLintConfig('rules:\n'
' this-one-does-not-exist: enable\n')
def test_missing_option(self):
with self.assertRaisesRegexp(
config.YamlLintConfigError,
'invalid config: missing option "max-spaces-before" '
'for rule "colons"'):
config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-after: 1\n')
def test_unknown_option(self):
with self.assertRaisesRegexp(
config.YamlLintConfigError,
'invalid config: unknown option "abcdef" for rule "colons"'):
config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 0\n'
' 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)
self.assertEqual(config.validate_rule_conf(Rule, {}),
{'level': 'error'})
self.assertEqual(config.validate_rule_conf(Rule, 'enable'),
{'level': 'error'})
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):
old = config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 0\n'
' max-spaces-after: 1\n')
new = config.YamlLintConfig('rules:\n'
' hyphens:\n'
' max-spaces-after: 2\n')
new.extend(old)
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 2)
def test_extend_remove_rule(self):
old = config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 0\n'
' max-spaces-after: 1\n'
' hyphens:\n'
' max-spaces-after: 2\n')
new = config.YamlLintConfig('rules:\n'
' colons: disable\n')
new.extend(old)
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
self.assertEqual(new.rules['colons'], False)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 1)
def test_extend_edit_rule(self):
old = config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 0\n'
' max-spaces-after: 1\n'
' hyphens:\n'
' max-spaces-after: 2\n')
new = config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 3\n'
' max-spaces-after: 4\n')
new.extend(old)
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
self.assertEqual(new.rules['colons']['max-spaces-before'], 3)
self.assertEqual(new.rules['colons']['max-spaces-after'], 4)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 2)
def test_extend_reenable_rule(self):
old = config.YamlLintConfig('rules:\n'
' colons:\n'
' max-spaces-before: 0\n'
' max-spaces-after: 1\n'
' hyphens: disable\n')
new = config.YamlLintConfig('rules:\n'
' hyphens:\n'
' max-spaces-after: 2\n')
new.extend(old)
self.assertEqual(sorted(new.rules.keys()), ['colons', 'hyphens'])
self.assertEqual(new.rules['colons']['max-spaces-before'], 0)
self.assertEqual(new.rules['colons']['max-spaces-after'], 1)
self.assertEqual(new.rules['hyphens']['max-spaces-after'], 2)
self.assertEqual(len(new.enabled_rules()), 2)
class ExtendedLibraryConfigTestCase(unittest.TestCase):
def test_extend_config_disable_rule(self):
old = config.YamlLintConfig('extends: default')
new = config.YamlLintConfig('extends: default\n'
'rules:\n'
' trailing-spaces: disable\n')
old.rules['trailing-spaces'] = False
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
for rule in new.rules:
self.assertEqual(new.rules[rule], old.rules[rule])
def test_extend_config_override_whole_rule(self):
old = config.YamlLintConfig('extends: default')
new = config.YamlLintConfig('extends: default\n'
'rules:\n'
' empty-lines:\n'
' max: 42\n'
' max-start: 43\n'
' max-end: 44\n')
old.rules['empty-lines']['max'] = 42
old.rules['empty-lines']['max-start'] = 43
old.rules['empty-lines']['max-end'] = 44
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
for rule in new.rules:
self.assertEqual(new.rules[rule], old.rules[rule])
def test_extend_config_override_rule_partly(self):
old = config.YamlLintConfig('extends: default')
new = config.YamlLintConfig('extends: default\n'
'rules:\n'
' empty-lines:\n'
' max-start: 42\n')
old.rules['empty-lines']['max-start'] = 42
self.assertEqual(sorted(new.rules.keys()), sorted(old.rules.keys()))
for rule in new.rules:
self.assertEqual(new.rules[rule], old.rules[rule])
yamllint-1.2.1/tests/rules/ 0000775 0001750 0001750 00000000000 12675233100 016367 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/tests/rules/test_document_end.py 0000664 0001750 0001750 00000004726 12653727046 022472 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class DocumentEndTestCase(RuleTestCase):
rule_id = 'document-end'
def test_disabled(self):
conf = 'document-end: disable'
self.check('---\n'
'with:\n'
' document: end\n'
'...\n', conf)
self.check('---\n'
'without:\n'
' document: end\n', conf)
def test_required(self):
conf = 'document-end: {present: yes}'
self.check('', conf)
self.check('\n', conf)
self.check('---\n'
'with:\n'
' document: end\n'
'...\n', conf)
self.check('---\n'
'without:\n'
' document: end\n', conf, problem=(3, 1))
def test_forbidden(self):
conf = 'document-end: {present: no}'
self.check('---\n'
'with:\n'
' document: end\n'
'...\n', conf, problem=(4, 1))
self.check('---\n'
'without:\n'
' document: end\n', conf)
def test_multiple_documents(self):
conf = ('document-end: {present: yes}\n'
'document-start: disable\n')
self.check('---\n'
'first: document\n'
'...\n'
'---\n'
'second: document\n'
'...\n'
'---\n'
'third: document\n'
'...\n', conf)
self.check('---\n'
'first: document\n'
'...\n'
'---\n'
'second: document\n'
'---\n'
'third: document\n'
'...\n', conf, problem=(6, 1))
yamllint-1.2.1/tests/rules/test_new_lines.py 0000664 0001750 0001750 00000003235 12653727046 022003 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class NewLinesTestCase(RuleTestCase):
rule_id = 'new-lines'
def test_disabled(self):
conf = ('new-line-at-end-of-file: disable\n'
'new-lines: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('\r', conf)
self.check('\r\n', conf)
self.check('---\ntext\n', conf)
self.check('---\r\ntext\r\n', conf)
def test_unix_type(self):
conf = 'new-lines: {type: unix}'
self.check('', conf)
self.check('\n', conf)
self.check('\r\n', conf, problem=(1, 1))
self.check('---\ntext\n', conf)
self.check('---\r\ntext\r\n', conf, problem=(1, 4))
def test_dos_type(self):
conf = 'new-lines: {type: dos}\n'
self.check('', conf)
self.check('\n', conf, problem=(1, 1))
self.check('\r\n', conf)
self.check('---\ntext\n', conf, problem=(1, 4))
self.check('---\r\ntext\r\n', conf)
yamllint-1.2.1/tests/rules/__init__.py 0000664 0001750 0001750 00000000000 12645536260 020500 0 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/tests/rules/test_common.py 0000664 0001750 0001750 00000007555 12647502135 021312 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import unittest
import yaml
from yamllint.rules.common import (Comment, get_line_indent,
get_comments_between_tokens)
class CommonTestCase(unittest.TestCase):
def test_get_line_indent(self):
tokens = list(yaml.scan('a: 1\n'
'b:\n'
' - c: [2, 3, {d: 4}]\n'))
self.assertEqual(tokens[3].value, 'a')
self.assertEqual(tokens[5].value, '1')
self.assertEqual(tokens[7].value, 'b')
self.assertEqual(tokens[13].value, 'c')
self.assertEqual(tokens[16].value, '2')
self.assertEqual(tokens[18].value, '3')
self.assertEqual(tokens[22].value, 'd')
self.assertEqual(tokens[24].value, '4')
for i in (3, 5):
self.assertEqual(get_line_indent(tokens[i]), 0)
for i in (7,):
self.assertEqual(get_line_indent(tokens[i]), 0)
for i in (13, 16, 18, 22, 24):
self.assertEqual(get_line_indent(tokens[i]), 2)
def check_comments(self, buffer, *expected):
yaml_loader = yaml.BaseLoader(buffer)
comments = []
next = yaml_loader.peek_token()
while next is not None:
curr = yaml_loader.get_token()
next = yaml_loader.peek_token()
for comment in get_comments_between_tokens(curr, next):
comments.append(comment)
self.assertEqual(comments, list(expected))
def test_get_comments_between_tokens(self):
self.check_comments('# comment\n',
Comment(1, 1, '# comment', 0))
self.check_comments('---\n'
'# comment\n'
'...\n',
Comment(2, 1, '# comment', 0))
self.check_comments('---\n'
'# no newline char',
Comment(2, 1, '# no newline char', 0))
self.check_comments('# just comment',
Comment(1, 1, '# just comment', 0))
self.check_comments('\n'
' # indented comment\n',
Comment(2, 4, '# indented comment', 0))
self.check_comments('\n'
'# trailing spaces \n',
Comment(2, 1, '# trailing spaces ', 0))
self.check_comments('# comment one\n'
'\n'
'key: val # key=val\n'
'\n'
'# this is\n'
'# a block \n'
'# comment\n'
'\n'
'other:\n'
' - foo # equals\n'
' # bar\n',
Comment(1, 1, '# comment one', 0),
Comment(3, 11, '# key=val', 0),
Comment(5, 1, '# this is', 0),
Comment(6, 1, '# a block ', 0),
Comment(7, 1, '# comment', 0),
Comment(10, 10, '# equals', 0),
Comment(11, 10, '# bar', 0))
yamllint-1.2.1/tests/rules/test_line_length.py 0000664 0001750 0001750 00000007377 12653727046 022323 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class LineLengthTestCase(RuleTestCase):
rule_id = 'line-length'
def test_disabled(self):
conf = ('line-length: disable\n'
'empty-lines: disable\n'
'new-line-at-end-of-file: disable\n'
'document-start: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('---\n', conf)
self.check(81 * 'a', conf)
self.check('---\n' + 81 * 'a' + '\n', conf)
self.check(1000 * 'b', conf)
self.check('---\n' + 1000 * 'b' + '\n', conf)
def test_default(self):
conf = ('line-length: {max: 80}\n'
'empty-lines: disable\n'
'new-line-at-end-of-file: disable\n'
'document-start: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('---\n', conf)
self.check(80 * 'a', conf)
self.check('---\n' + 80 * 'a' + '\n', conf)
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('---\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'
'new-line-at-end-of-file: disable\n'
'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))
yamllint-1.2.1/tests/rules/test_document_start.py 0000664 0001750 0001750 00000006714 12653727046 023060 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class DocumentStartTestCase(RuleTestCase):
rule_id = 'document-start'
def test_disabled(self):
conf = 'document-start: disable'
self.check('', conf)
self.check('key: val\n', conf)
self.check('---\n'
'key: val\n', conf)
def test_required(self):
conf = ('document-start: {present: yes}\n'
'empty-lines: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('key: val\n', conf, problem=(1, 1))
self.check('\n'
'\n'
'key: val\n', conf, problem=(3, 1))
self.check('---\n'
'key: val\n', conf)
self.check('\n'
'\n'
'---\n'
'key: val\n', conf)
def test_forbidden(self):
conf = ('document-start: {present: no}\n'
'empty-lines: disable\n')
self.check('', conf)
self.check('key: val\n', conf)
self.check('\n'
'\n'
'key: val\n', conf)
self.check('---\n'
'key: val\n', conf, problem=(1, 1))
self.check('\n'
'\n'
'---\n'
'key: val\n', conf, problem=(3, 1))
self.check('first: document\n'
'---\n'
'key: val\n', conf, problem=(2, 1))
def test_multiple_documents(self):
conf = 'document-start: {present: yes}'
self.check('---\n'
'first: document\n'
'...\n'
'---\n'
'second: document\n'
'...\n'
'---\n'
'third: document\n', conf)
self.check('---\n'
'first: document\n'
'---\n'
'second: document\n'
'---\n'
'third: document\n', conf)
self.check('---\n'
'first: document\n'
'...\n'
'second: document\n'
'---\n'
'third: document\n', conf, problem=(4, 1, 'syntax'))
def test_directives(self):
conf = 'document-start: {present: yes}'
self.check('%YAML 1.2\n'
'---\n'
'doc: ument\n'
'...\n', conf)
self.check('%YAML 1.2\n'
'%TAG ! tag:clarkevans.com,2002:\n'
'---\n'
'doc: ument\n'
'...\n', conf)
self.check('---\n'
'doc: 1\n'
'...\n'
'%YAML 1.2\n'
'---\n'
'doc: 2\n'
'...\n', conf)
yamllint-1.2.1/tests/rules/test_key_duplicates.py 0000664 0001750 0001750 00000013263 12667043545 023027 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
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: enable'
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: enable'
self.check('---\n'
'[\n'
' flow: sequence, with, key: value, mappings\n'
']\n', conf)
yamllint-1.2.1/tests/rules/test_commas.py 0000664 0001750 0001750 00000023517 12653727046 021304 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class CommaTestCase(RuleTestCase):
rule_id = 'commas'
def test_disabled(self):
conf = 'commas: disable'
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e , f: [g, h]}\n'
'array: [\n'
' elem ,\n'
' key: val ,\n'
']\n'
'map: {\n'
' key1: val1 ,\n'
' 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_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)
self.check('---\n'
'array: [1, 2 , 3, 4]\n'
'...\n', conf, problem=(2, 13))
self.check('---\n'
'array: [1 , 2, 3 , 4]\n'
'...\n', conf, problem1=(2, 10), problem2=(2, 23))
self.check('---\n'
'dict: {a: b, c: "1 2 3", d: e, f: [g, h]}\n'
'...\n', conf)
self.check('---\n'
'dict: {a: b, c: "1 2 3" , d: e, f: [g, h]}\n'
'...\n', conf, problem=(2, 24))
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e, f: [g , h]}\n'
'...\n', conf, problem1=(2, 12), problem2=(2, 42))
self.check('---\n'
'array: [\n'
' elem,\n'
' key: val,\n'
']\n', conf)
self.check('---\n'
'array: [\n'
' elem ,\n'
' key: val,\n'
']\n', conf, problem=(3, 7))
self.check('---\n'
'map: {\n'
' key1: val1,\n'
' key2: val2,\n'
'}\n', conf)
self.check('---\n'
'map: {\n'
' key1: val1,\n'
' key2: val2 ,\n'
'}\n', conf, problem=(4, 13))
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)
self.check('---\n'
'array: [1 , 2, 3 , 4]\n'
'...\n', conf, problem=(2, 20))
self.check('---\n'
'array: [\n'
' elem1 ,\n'
' elem2 ,\n'
' key: val,\n'
']\n', conf, problem=(4, 11))
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)
self.check('---\n'
'array: [1, 2, 3, 4]\n'
'...\n', conf, problem=(2, 15))
self.check('---\n'
'array: [1, 2, 3, 4]\n'
'...\n', conf, problem1=(2, 12), problem2=(2, 22))
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e, f: [g, h]}\n'
'...\n', conf)
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e, f: [g, h]}\n'
'...\n', conf, problem=(2, 27))
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e, f: [g, h]}\n'
'...\n', conf, problem1=(2, 15), problem2=(2, 44))
self.check('---\n'
'array: [\n'
' elem,\n'
' key: val,\n'
']\n', conf)
self.check('---\n'
'array: [\n'
' elem, key: val,\n'
']\n', conf, problem=(3, 9))
self.check('---\n'
'map: {\n'
' key1: val1, key2: [val2, val3]\n'
'}\n', conf, problem1=(3, 16), problem2=(3, 30))
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)
self.check('---\n'
'array: [1, 2, 3, 4]\n'
'...\n', conf, problem=(2, 21))
self.check('---\n'
'dict: {a: b , c: "1 2 3", d: e, f: [g, h]}\n'
'...\n', conf, problem1=(2, 31), problem2=(2, 49))
def test_both_before_and_after(self):
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'
' elem ,\n'
' key: val ,\n'
']\n'
'map: {\n'
' key1: val1 ,\n'
' key2: val2,\n'
'}\n'
'...\n', conf,
problem1=(2, 12), problem2=(2, 16), problem3=(2, 31),
problem4=(2, 36), problem5=(2, 50), problem6=(4, 8),
problem7=(5, 11), problem8=(8, 13))
conf = ('commas:\n'
' max-spaces-before: 0\n'
' min-spaces-after: 1\n'
' max-spaces-after: 1\n'
'indentation: disable\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, 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))
yamllint-1.2.1/tests/rules/test_comments.py 0000664 0001750 0001750 00000012560 12653727046 021646 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class CommentsTestCase(RuleTestCase):
rule_id = 'comments'
def test_disabled(self):
conf = ('comments: disable\n'
'comments-indentation: disable\n')
self.check('---\n'
'#comment\n'
'\n'
'test: # description\n'
' - foo # bar\n'
' - hello #world\n'
'\n'
'# comment 2\n'
'#comment 3\n'
' #comment 3 bis\n'
' # comment 3 ter\n'
'\n'
'string: "Une longue phrase." # this is French\n', conf)
def test_starting_space(self):
conf = ('comments:\n'
' require-starting-space: yes\n'
' min-spaces-from-content: -1\n'
'comments-indentation: disable\n')
self.check('---\n'
'# comment\n'
'\n'
'test: # description\n'
' - foo # bar\n'
' - hello # world\n'
'\n'
'# comment 2\n'
'# comment 3\n'
' # comment 3 bis\n'
' # comment 3 ter\n', conf)
self.check('---\n'
'#comment\n'
'\n'
'test: # description\n'
' - foo # bar\n'
' - hello #world\n'
'\n'
'# comment 2\n'
'#comment 3\n'
' #comment 3 bis\n'
' # comment 3 ter\n', conf,
problem1=(2, 2), problem2=(6, 13),
problem4=(9, 2), problem5=(10, 4))
def test_spaces_from_content(self):
conf = ('comments:\n'
' require-starting-space: no\n'
' min-spaces-from-content: 2\n')
self.check('---\n'
'# comment\n'
'\n'
'test: # description\n'
' - foo # bar\n'
' - hello #world\n'
'\n'
'string: "Une longue phrase." # this is French\n', conf)
self.check('---\n'
'# comment\n'
'\n'
'test: # description\n'
' - foo # bar\n'
' - hello #world\n'
'\n'
'string: "Une longue phrase." # this is French\n', conf,
problem1=(4, 7), problem2=(6, 11), problem3=(8, 30))
def test_both(self):
conf = ('comments:\n'
' require-starting-space: yes\n'
' min-spaces-from-content: 2\n'
'comments-indentation: disable\n')
self.check('---\n'
'#comment\n'
'\n'
'test: # description\n'
' - foo # bar\n'
' - hello #world\n'
'\n'
'# comment 2\n'
'#comment 3\n'
' #comment 3 bis\n'
' # comment 3 ter\n'
'\n'
'string: "Une longue phrase." # this is French\n', conf,
problem1=(2, 2),
problem2=(4, 7),
problem3=(6, 11), problem4=(6, 12),
problem5=(9, 2),
problem6=(10, 4),
problem7=(13, 30))
def test_empty_comment(self):
conf = ('comments:\n'
' require-starting-space: yes\n'
' min-spaces-from-content: 2\n')
self.check('---\n'
'# This is paragraph 1.\n'
'#\n'
'# This is paragraph 2.\n', conf)
self.check('---\n'
'inline: comment #\n'
'foo: bar\n', conf)
def test_first_line(self):
conf = ('comments:\n'
' require-starting-space: yes\n'
' min-spaces-from-content: 2\n')
self.check('# comment\n', conf)
def test_multi_line_scalar(self):
conf = ('comments:\n'
' require-starting-space: yes\n'
' min-spaces-from-content: 2\n'
'trailing-spaces: disable\n')
self.check('---\n'
'string: >\n'
' this is plain text\n'
'\n'
'# comment\n', conf)
self.check('---\n'
'- string: >\n'
' this is plain text\n'
' \n'
' # comment\n', conf)
yamllint-1.2.1/tests/rules/test_trailing_spaces.py 0000664 0001750 0001750 00000003345 12667043545 023171 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class TrailingSpacesTestCase(RuleTestCase):
rule_id = 'trailing-spaces'
def test_disabled(self):
conf = 'trailing-spaces: disable'
self.check('', conf)
self.check('\n', conf)
self.check(' \n', conf)
self.check('---\n'
'some: text \n', conf)
def test_enabled(self):
conf = 'trailing-spaces: enable'
self.check('', conf)
self.check('\n', conf)
self.check(' \n', conf, problem=(1, 1))
self.check('\t\t\t\n', conf, problem=(1, 1, 'syntax'))
self.check('---\n'
'some: text \n', conf, problem=(2, 11))
self.check('---\n'
'some: text\t\n', conf, problem=(2, 11, 'syntax'))
def test_with_dos_new_lines(self):
conf = ('trailing-spaces: enable\n'
'new-lines: {type: dos}\n')
self.check('---\r\n'
'some: text\r\n', conf)
self.check('---\r\n'
'some: text \r\n', conf, problem=(2, 11))
yamllint-1.2.1/tests/rules/test_brackets.py 0000664 0001750 0001750 00000007703 12653727046 021622 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class ColonTestCase(RuleTestCase):
rule_id = 'brackets'
def test_disabled(self):
conf = 'brackets: disable'
self.check('---\n'
'array1: []\n'
'array2: [ ]\n'
'array3: [ a, b]\n'
'array4: [a, b, c ]\n'
'array5: [a, b, c ]\n'
'array6: [ a, b, c ]\n'
'array7: [ a, b, c ]\n', conf)
def test_min_spaces(self):
conf = 'brackets: {max-spaces-inside: -1, min-spaces-inside: 0}'
self.check('---\n'
'array: []\n', conf)
conf = 'brackets: {max-spaces-inside: -1, min-spaces-inside: 1}'
self.check('---\n'
'array: []\n', conf, problem=(2, 9))
self.check('---\n'
'array: [ ]\n', conf)
self.check('---\n'
'array: [a, b]\n', conf, problem1=(2, 9), problem2=(2, 13))
self.check('---\n'
'array: [ a, b ]\n', conf)
self.check('---\n'
'array: [\n'
' a,\n'
' b\n'
']\n', conf)
conf = 'brackets: {max-spaces-inside: -1, min-spaces-inside: 3}'
self.check('---\n'
'array: [ a, b ]\n', conf,
problem1=(2, 10), problem2=(2, 15))
self.check('---\n'
'array: [ a, b ]\n', conf)
def test_max_spaces(self):
conf = 'brackets: {max-spaces-inside: 0, min-spaces-inside: -1}'
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [ ]\n', conf, problem=(2, 9))
self.check('---\n'
'array: [a, b]\n', conf)
self.check('---\n'
'array: [ a, b ]\n', conf,
problem1=(2, 9), problem2=(2, 14))
self.check('---\n'
'array: [ a, b ]\n', conf,
problem1=(2, 11), problem2=(2, 18))
self.check('---\n'
'array: [\n'
' a,\n'
' b\n'
']\n', conf)
conf = 'brackets: {max-spaces-inside: 3, min-spaces-inside: -1}'
self.check('---\n'
'array: [ a, b ]\n', conf)
self.check('---\n'
'array: [ a, b ]\n', conf,
problem1=(2, 12), problem2=(2, 21))
def test_min_and_max_spaces(self):
conf = 'brackets: {max-spaces-inside: 0, min-spaces-inside: 0}'
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [ ]\n', conf, problem=(2, 9))
self.check('---\n'
'array: [ a, b]\n', conf, problem=(2, 11))
conf = 'brackets: {max-spaces-inside: 1, min-spaces-inside: 1}'
self.check('---\n'
'array: [a, b, c ]\n', conf, problem=(2, 9))
conf = 'brackets: {max-spaces-inside: 2, min-spaces-inside: 0}'
self.check('---\n'
'array: [a, b, c ]\n', conf)
self.check('---\n'
'array: [ a, b, c ]\n', conf)
self.check('---\n'
'array: [ a, b, c ]\n', conf, problem=(2, 11))
yamllint-1.2.1/tests/rules/test_empty_lines.py 0000664 0001750 0001750 00000006463 12653727046 022356 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class EmptyLinesTestCase(RuleTestCase):
rule_id = 'empty-lines'
def test_disabled(self):
conf = ('empty-lines: disable\n'
'new-line-at-end-of-file: disable\n'
'document-start: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('\n\n', conf)
self.check('\n\n\n\n\n\n\n\n\n', conf)
self.check('some text\n\n\n\n\n\n\n\n\n', conf)
self.check('\n\n\n\n\n\n\n\n\nsome text', conf)
self.check('\n\n\nsome text\n\n\n', conf)
def test_empty_document(self):
conf = ('empty-lines: {max: 0, max-start: 0, max-end: 0}\n'
'new-line-at-end-of-file: disable\n'
'document-start: disable\n')
self.check('', conf)
self.check('\n', conf)
def test_0_empty_lines(self):
conf = ('empty-lines: {max: 0, max-start: 0, max-end: 0}\n'
'new-line-at-end-of-file: disable\n')
self.check('---\n', conf)
self.check('---\ntext\n\ntext', conf, problem=(3, 1))
self.check('---\ntext\n\ntext\n', conf, problem=(3, 1))
def test_10_empty_lines(self):
conf = 'empty-lines: {max: 10, max-start: 0, max-end: 0}'
self.check('---\nintro\n\n\n\n\n\n\n\n\n\n\nconclusion\n', conf)
self.check('---\nintro\n\n\n\n\n\n\n\n\n\n\n\nconclusion\n', conf,
problem=(13, 1))
def test_spaces(self):
conf = ('empty-lines: {max: 1, max-start: 0, max-end: 0}\n'
'trailing-spaces: disable\n')
self.check('---\nintro\n\n \n\nconclusion\n', conf)
self.check('---\nintro\n\n \n\n\nconclusion\n', conf, problem=(6, 1))
def test_empty_lines_at_start(self):
conf = ('empty-lines: {max: 2, max-start: 4, max-end: 0}\n'
'document-start: disable\n')
self.check('\n\n\n\nnon empty\n', conf)
self.check('\n\n\n\n\nnon empty\n', conf, problem=(5, 1))
conf = ('empty-lines: {max: 2, max-start: 0, max-end: 0}\n'
'document-start: disable\n')
self.check('non empty\n', conf)
self.check('\nnon empty\n', conf, problem=(1, 1))
def test_empty_lines_at_end(self):
conf = ('empty-lines: {max: 2, max-start: 0, max-end: 4}\n'
'document-start: disable\n')
self.check('non empty\n\n\n\n\n', conf)
self.check('non empty\n\n\n\n\n\n', conf, problem=(6, 1))
conf = ('empty-lines: {max: 2, max-start: 0, max-end: 0}\n'
'document-start: disable\n')
self.check('non empty\n', conf)
self.check('non empty\n\n', conf, problem=(2, 1))
yamllint-1.2.1/tests/rules/test_colons.py 0000664 0001750 0001750 00000022102 12653727046 021307 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class ColonTestCase(RuleTestCase):
rule_id = 'colons'
def test_disabled(self):
conf = 'colons: disable'
self.check('---\n'
'object:\n'
' k1 : v1\n'
'obj2:\n'
' k2 :\n'
' - 8\n'
' k3:\n'
' val\n'
' property : value\n'
' prop2 : val2\n'
' propriété : [valeur]\n'
' o:\n'
' k1: [v1, v2]\n'
' p:\n'
' - k3: >\n'
' val\n'
' - o: {k1: v1}\n'
' - p: kdjf\n'
' - q: val0\n'
' - q2:\n'
' - val1\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' k1: v1\n'
'obj2:\n'
' k2:\n'
' - 8\n'
' k3:\n'
' val\n'
' property: value\n'
' prop2: val2\n'
' propriété: [valeur]\n'
' o:\n'
' k1: [v1, v2]\n', conf)
self.check('---\n'
'obj:\n'
' p:\n'
' - k1: >\n'
' val\n'
' - k3: >\n'
' val\n'
' - o: {k1: v1}\n'
' - o: {k1: v1}\n'
' - q2:\n'
' - val1\n'
'...\n', conf)
self.check('---\n'
'a: {b: {c: d, e : f}}\n', conf)
def test_before_enabled(self):
conf = 'colons: {max-spaces-before: 0, max-spaces-after: -1}'
self.check('---\n'
'object:\n'
' k1:\n'
' - a\n'
' - b\n'
' k2: v2\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' k1 :\n'
' - a\n'
' - b\n'
' k2: v2\n'
'...\n', conf, problem=(3, 5))
self.check('---\n'
'lib :\n'
' - var\n'
'...\n', conf, problem=(2, 4))
self.check('---\n'
'- lib :\n'
' - var\n'
'...\n', conf, problem=(2, 6))
self.check('---\n'
'a: {b: {c : d, e : f}}\n', conf,
problem1=(2, 10), problem2=(2, 17))
def test_before_max(self):
conf = 'colons: {max-spaces-before: 3, max-spaces-after: -1}'
self.check('---\n'
'object :\n'
' k1 :\n'
' - a\n'
' - b\n'
' k2 : v2\n'
'...\n', conf)
self.check('---\n'
'object :\n'
' k1 :\n'
' - a\n'
' - b\n'
' k2 : v2\n'
'...\n', conf, problem=(3, 8))
def test_before_with_explicit_block_mappings(self):
conf = 'colons: {max-spaces-before: 0, max-spaces-after: 1}'
self.check('---\n'
'object:\n'
' ? key\n'
' : value\n'
'...\n', conf)
self.check('---\n'
'object :\n'
' ? key\n'
' : value\n'
'...\n', conf, problem=(2, 7))
self.check('---\n'
'? >\n'
' multi-line\n'
' key\n'
': >\n'
' multi-line\n'
' value\n'
'...\n', conf)
self.check('---\n'
'- ? >\n'
' multi-line\n'
' key\n'
' : >\n'
' multi-line\n'
' value\n'
'...\n', conf)
self.check('---\n'
'- ? >\n'
' multi-line\n'
' key\n'
' : >\n'
' multi-line\n'
' value\n'
'...\n', conf, problem=(5, 5))
def test_after_enabled(self):
conf = 'colons: {max-spaces-before: -1, max-spaces-after: 1}'
self.check('---\n'
'key: value\n', conf)
self.check('---\n'
'key: value\n', conf, problem=(2, 6))
self.check('---\n'
'object:\n'
' k1: [a, b]\n'
' k2: string\n', conf, problem=(3, 7))
self.check('---\n'
'object:\n'
' k1: [a, b]\n'
' k2: string\n', conf, problem=(4, 7))
self.check('---\n'
'object:\n'
' other: {key: value}\n'
'...\n', conf, problem=(3, 16))
self.check('---\n'
'a: {b: {c: d, e : f}}\n', conf,
problem1=(2, 12), problem2=(2, 20))
def test_after_enabled_question_mark(self):
conf = 'colons: {max-spaces-before: -1, max-spaces-after: 1}'
self.check('---\n'
'? key\n'
': value\n', conf)
self.check('---\n'
'? key\n'
': value\n', conf, problem=(2, 3))
self.check('---\n'
'? key\n'
': value\n', conf, problem1=(2, 3), problem2=(3, 3))
self.check('---\n'
'- ? key\n'
' : value\n', conf, problem1=(2, 5), problem2=(3, 5))
def test_after_max(self):
conf = 'colons: {max-spaces-before: -1, max-spaces-after: 3}'
self.check('---\n'
'object:\n'
' k1: [a, b]\n', conf)
self.check('---\n'
'object:\n'
' k1: [a, b]\n', conf, problem=(3, 9))
self.check('---\n'
'object:\n'
' k2: string\n', conf)
self.check('---\n'
'object:\n'
' k2: string\n', conf, problem=(3, 9))
self.check('---\n'
'object:\n'
' other: {key: value}\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' other: {key: value}\n'
'...\n', conf, problem=(3, 18))
def test_after_with_explicit_block_mappings(self):
conf = 'colons: {max-spaces-before: -1, max-spaces-after: 1}'
self.check('---\n'
'object:\n'
' ? key\n'
' : value\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' ? key\n'
' : value\n'
'...\n', conf, problem=(4, 5))
def test_after_do_not_confound_with_trailing_space(self):
conf = ('colons: {max-spaces-before: 1, max-spaces-after: 1}\n'
'trailing-spaces: disable\n')
self.check('---\n'
'trailing: \n'
' - spaces\n', conf)
def test_both_before_and_after(self):
conf = 'colons: {max-spaces-before: 0, max-spaces-after: 1}'
self.check('---\n'
'obj:\n'
' string: text\n'
' k:\n'
' - 8\n'
' k3:\n'
' val\n'
' property: [value]\n', conf)
self.check('---\n'
'object:\n'
' k1 : v1\n', conf, problem1=(3, 5), problem2=(3, 8))
self.check('---\n'
'obj:\n'
' string: text\n'
' k :\n'
' - 8\n'
' k3:\n'
' val\n'
' property: {a: 1, b: 2, c : 3}\n', conf,
problem1=(3, 11), problem2=(4, 4),
problem3=(8, 23), problem4=(8, 28))
yamllint-1.2.1/tests/rules/test_indentation.py 0000664 0001750 0001750 00000215564 12675231644 022344 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
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')
def test_flows_imbrication(self):
self.assertMultiLineEqual(
self.full_stack('[[val]]\n'),
'FSeqStart F_SEQ:1\n'
'FSeqStart F_SEQ:1 F_SEQ:2\n'
' Scalar F_SEQ:1 F_SEQ:2\n'
' FSeqEnd F_SEQ:1\n'
' FSeqEnd \n')
self.assertMultiLineEqual(
self.full_stack('[[val], [val2]]\n'),
'FSeqStart F_SEQ:1\n'
'FSeqStart F_SEQ:1 F_SEQ:2\n'
' Scalar F_SEQ:1 F_SEQ:2\n'
' FSeqEnd F_SEQ:1\n'
' FEntry F_SEQ:1\n'
'FSeqStart F_SEQ:1 F_SEQ:9\n'
' Scalar F_SEQ:1 F_SEQ:9\n'
' FSeqEnd F_SEQ:1\n'
' FSeqEnd \n')
self.assertMultiLineEqual(
self.full_stack('{{key}}\n'),
'FMapStart F_MAP:1\n'
'FMapStart F_MAP:1 F_MAP:2\n'
' Scalar F_MAP:1 F_MAP:2\n'
' FMapEnd F_MAP:1\n'
' FMapEnd \n')
self.assertMultiLineEqual(
self.full_stack('[key]: value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
'FSeqStart B_MAP:0 KEY:0 F_SEQ:1\n'
' Scalar B_MAP:0 KEY:0 F_SEQ:1\n'
' FSeqEnd B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:7\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('[[key]]: value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
'FSeqStart B_MAP:0 KEY:0 F_SEQ:1\n'
'FSeqStart B_MAP:0 KEY:0 F_SEQ:1 F_SEQ:2\n'
' Scalar B_MAP:0 KEY:0 F_SEQ:1 F_SEQ:2\n'
' FSeqEnd B_MAP:0 KEY:0 F_SEQ:1\n'
' FSeqEnd B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:9\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('{key}: value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
'FMapStart B_MAP:0 KEY:0 F_MAP:1\n'
' Scalar B_MAP:0 KEY:0 F_MAP:1\n'
' FMapEnd B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:7\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('{key: value}: value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
'FMapStart B_MAP:0 KEY:0 F_MAP:1\n'
' Key B_MAP:0 KEY:0 F_MAP:1 KEY:1\n'
' Scalar B_MAP:0 KEY:0 F_MAP:1 KEY:1\n'
' Value B_MAP:0 KEY:0 F_MAP:1 KEY:1 VAL:6\n'
' Scalar B_MAP:0 KEY:0 F_MAP:1\n'
' FMapEnd B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:14\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('{{key}}: value\n'),
'BMapStart B_MAP:0\n'
' Key B_MAP:0 KEY:0\n'
'FMapStart B_MAP:0 KEY:0 F_MAP:1\n'
'FMapStart B_MAP:0 KEY:0 F_MAP:1 F_MAP:2\n'
' Scalar B_MAP:0 KEY:0 F_MAP:1 F_MAP:2\n'
' FMapEnd B_MAP:0 KEY:0 F_MAP:1\n'
' FMapEnd B_MAP:0 KEY:0\n'
' Value B_MAP:0 KEY:0 VAL:9\n'
' Scalar B_MAP:0\n'
' BEnd \n')
self.assertMultiLineEqual(
self.full_stack('{{key}: val, {key2}: {val2}}\n'),
'FMapStart F_MAP:1\n'
' Key F_MAP:1 KEY:1\n'
'FMapStart F_MAP:1 KEY:1 F_MAP:2\n'
' Scalar F_MAP:1 KEY:1 F_MAP:2\n'
' FMapEnd F_MAP:1 KEY:1\n'
' Value F_MAP:1 KEY:1 VAL:8\n'
' Scalar F_MAP:1\n'
' FEntry F_MAP:1\n'
' Key F_MAP:1 KEY:1\n'
'FMapStart F_MAP:1 KEY:1 F_MAP:14\n'
' Scalar F_MAP:1 KEY:1 F_MAP:14\n'
' FMapEnd F_MAP:1 KEY:1\n'
' Value F_MAP:1 KEY:1 VAL:21\n'
'FMapStart F_MAP:1 KEY:1 VAL:21 F_MAP:22\n'
' Scalar F_MAP:1 KEY:1 VAL:21 F_MAP:22\n'
' FMapEnd F_MAP:1\n'
' FMapEnd \n')
self.assertMultiLineEqual(
self.full_stack('{[{{[val]}}, [{[key]: val2}]]}\n'),
'FMapStart F_MAP:1\n'
'FSeqStart F_MAP:1 F_SEQ:2\n'
'FMapStart F_MAP:1 F_SEQ:2 F_MAP:3\n'
'FMapStart F_MAP:1 F_SEQ:2 F_MAP:3 F_MAP:4\n'
'FSeqStart F_MAP:1 F_SEQ:2 F_MAP:3 F_MAP:4 F_SEQ:5\n'
' Scalar F_MAP:1 F_SEQ:2 F_MAP:3 F_MAP:4 F_SEQ:5\n'
' FSeqEnd F_MAP:1 F_SEQ:2 F_MAP:3 F_MAP:4\n'
' FMapEnd F_MAP:1 F_SEQ:2 F_MAP:3\n'
' FMapEnd F_MAP:1 F_SEQ:2\n'
' FEntry F_MAP:1 F_SEQ:2\n'
'FSeqStart F_MAP:1 F_SEQ:2 F_SEQ:14\n'
'FMapStart F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15\n'
' Key F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15 KEY:15\n'
'FSeqStart F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15 KEY:15 F_SEQ:16\n'
' Scalar F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15 KEY:15 F_SEQ:16\n'
' FSeqEnd F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15 KEY:15\n'
' Value F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15 KEY:15 VAL:22\n'
' Scalar F_MAP:1 F_SEQ:2 F_SEQ:14 F_MAP:15\n'
' FMapEnd F_MAP:1 F_SEQ:2 F_SEQ:14\n'
' FSeqEnd F_MAP:1 F_SEQ:2\n'
' FSeqEnd F_MAP:1\n'
' FMapEnd \n')
class IndentationTestCase(RuleTestCase):
rule_id = 'indentation'
def test_disabled(self):
conf = 'indentation: disable'
self.check('---\n'
'object:\n'
' k1: v1\n'
'obj2:\n'
' k2:\n'
' - 8\n'
' k3:\n'
' val\n'
'...\n', conf)
self.check('---\n'
' o:\n'
' k1: v1\n'
' p:\n'
' k3:\n'
' val\n'
'...\n', conf)
self.check('---\n'
' - o:\n'
' k1: v1\n'
' - p: kdjf\n'
' - q:\n'
' k3:\n'
' - val\n'
'...\n', conf)
def test_one_space(self):
conf = 'indentation: {spaces: 1, indent-sequences: no}'
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)
conf = 'indentation: {spaces: 1, indent-sequences: yes}'
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)
def test_two_spaces(self):
conf = 'indentation: {spaces: 2, indent-sequences: no}'
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)
conf = 'indentation: {spaces: 2, indent-sequences: yes}'
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)
def test_three_spaces(self):
conf = 'indentation: {spaces: 3, indent-sequences: no}'
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)
conf = 'indentation: {spaces: 3, indent-sequences: yes}'
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)
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'
'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, problem=(3, 3))
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list two:\n'
' - a\n'
' - b\n'
' - c\n', conf, problem=(7, 3))
self.check('---\n'
'list:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'- a\n'
'- b\n'
'- c\n', conf, problem=(6, 1, 'syntax'))
def test_indent_sequences_consistent(self):
conf = 'indentation: {spaces: 4, indent-sequences: consistent}'
self.check('---\n'
'list one:\n'
'- 1\n'
'- 2\n'
'- 3\n'
'list:\n'
' two:\n'
' - a\n'
' - b\n'
' - c\n', conf)
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list:\n'
' 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, 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, problem=(7, 1))
self.check('---\n'
'list one:\n'
' - 1\n'
' - 2\n'
' - 3\n'
'list two:\n'
'- a\n'
'- b\n'
'- c\n', conf, problem1=(3, 2), problem2=(7, 1))
def test_direct_flows(self):
# flow: [ ...
# ]
conf = 'indentation: {spaces: consistent}'
self.check('---\n'
'a: {x: 1,\n'
' y,\n'
' z: 1}\n', conf)
self.check('---\n'
'a: {x: 1,\n'
' y,\n'
' z: 1}\n', conf, problem=(3, 4))
self.check('---\n'
'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: consistent}'
self.check('---\n'
'a: {\n'
' x: 1,\n'
' y, z: 1\n'
'}\n', conf)
self.check('---\n'
'a: {\n'
' x: 1,\n'
' y, z: 1}\n', conf)
self.check('---\n'
'a: {\n'
' x: 1,\n'
' y, z: 1\n'
'}\n', conf, problem=(4, 3))
self.check('---\n'
'a: {\n'
' x: 1,\n'
' y, z: 1\n'
' }\n', conf, problem=(5, 3))
self.check('---\n'
'a: [\n'
' x,\n'
' y, z\n'
']\n', conf)
self.check('---\n'
'a: [\n'
' x,\n'
' y, z]\n', conf)
self.check('---\n'
'a: [\n'
' x,\n'
' y, z\n'
']\n', conf, problem=(4, 3))
self.check('---\n'
'a: [\n'
' 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))
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'a: {\n'
' x: 1,\n'
' y, z: 1\n'
'}\n', conf, problem=(3, 4))
self.check('---\n'
'a: [\n'
' x,\n'
' y, z\n'
']\n', conf, problem=(3, 4))
def test_cleared_flows(self):
# flow:
# [
# ...
# ]
conf = 'indentation: {spaces: consistent}'
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=(4, 6))
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: consistent}'
self.check('---\n'
'object:\n'
' val: 1\n'
'...\n', conf, problem=(3, 2))
self.check('---\n'
'object:\n'
' k1:\n'
' - a\n'
'...\n', conf, problem=(4, 4))
self.check('---\n'
'object:\n'
' k3:\n'
' - name: Unix\n'
' date: 1969\n'
'...\n', conf, problem=(5, 6, 'syntax'))
conf = 'indentation: {spaces: 4, indent-sequences: consistent}'
self.check('---\n'
'object:\n'
' val: 1\n'
'...\n', conf, problem=(3, 4))
self.check('---\n'
'- el1\n'
'- el2:\n'
' - subel\n'
'...\n', conf, problem=(4, 4))
self.check('---\n'
'object:\n'
' k3:\n'
' - name: Linux\n'
' date: 1991\n'
'...\n', conf, problem=(5, 10, 'syntax'))
def test_over_indented(self):
conf = 'indentation: {spaces: 2, indent-sequences: consistent}'
self.check('---\n'
'object:\n'
' val: 1\n'
'...\n', conf, problem=(3, 4))
self.check('---\n'
'object:\n'
' k1:\n'
' - a\n'
'...\n', conf, problem=(4, 6))
self.check('---\n'
'object:\n'
' k3:\n'
' - name: Unix\n'
' date: 1969\n'
'...\n', conf, problem=(5, 12, 'syntax'))
conf = 'indentation: {spaces: 4, indent-sequences: consistent}'
self.check('---\n'
'object:\n'
' val: 1\n'
'...\n', conf, problem=(3, 6))
self.check('---\n'
' object:\n'
' val: 1\n'
'...\n', conf, problem=(2, 2))
self.check('---\n'
'- el1\n'
'- el2:\n'
' - subel\n'
'...\n', conf, problem=(4, 6))
self.check('---\n'
'- el1\n'
'- el2:\n'
' - subel\n'
'...\n', conf, problem=(4, 15))
self.check('---\n'
' - el1\n'
' - el2:\n'
' - subel\n'
'...\n', conf,
problem=(2, 3))
self.check('---\n'
'object:\n'
' k3:\n'
' - name: Linux\n'
' date: 1991\n'
'...\n', conf, problem=(5, 16, 'syntax'))
conf = 'indentation: {spaces: 4, indent-sequences: whatever}'
self.check('---\n'
' - el1\n'
' - el2:\n'
' - subel\n'
'...\n', conf,
problem=(2, 3))
def test_multi_lines(self):
conf = 'indentation: {spaces: consistent, indent-sequences: yes}'
self.check('---\n'
'long_string: >\n'
' bla bla blah\n'
' blah bla bla\n'
'...\n', conf)
self.check('---\n'
'- long_string: >\n'
' bla bla blah\n'
' blah bla bla\n'
'...\n', conf)
self.check('---\n'
'obj:\n'
' - long_string: >\n'
' bla bla blah\n'
' blah bla bla\n'
'...\n', conf)
def test_empty_value(self):
conf = 'indentation: {spaces: consistent}'
self.check('---\n'
'key1:\n'
'key2: not empty\n'
'key3:\n'
'...\n', conf)
self.check('---\n'
'-\n'
'- item 2\n'
'-\n'
'...\n', conf)
def test_nested_collections(self):
conf = 'indentation: {spaces: 2}'
self.check('---\n'
'- o:\n'
' k1: v1\n'
'...\n', conf)
self.check('---\n'
'- o:\n'
' k1: v1\n'
'...\n', conf, problem=(3, 2, 'syntax'))
self.check('---\n'
'- o:\n'
' k1: v1\n'
'...\n', conf, problem=(3, 4))
conf = 'indentation: {spaces: 4}'
self.check('---\n'
'- o:\n'
' k1: v1\n'
'...\n', conf)
self.check('---\n'
'- o:\n'
' k1: v1\n'
'...\n', conf, problem=(3, 6))
self.check('---\n'
'- o:\n'
' k1: v1\n'
'...\n', conf, problem=(3, 8))
self.check('---\n'
'- - - - item\n'
' - elem 1\n'
' - elem 2\n'
' - - - - - very nested: a\n'
' key: value\n'
'...\n', conf)
self.check('---\n'
' - - - - item\n'
' - elem 1\n'
' - elem 2\n'
' - - - - - very nested: a\n'
' key: value\n'
'...\n', conf, problem=(2, 2))
def test_return(self):
conf = 'indentation: {spaces: consistent}'
self.check('---\n'
'a:\n'
' b:\n'
' c:\n'
' d:\n'
' e:\n'
' f:\n'
'g:\n'
'...\n', conf)
self.check('---\n'
'a:\n'
' b:\n'
' c:\n'
' d:\n'
'...\n', conf, problem=(5, 4, 'syntax'))
self.check('---\n'
'a:\n'
' b:\n'
' c:\n'
' d:\n'
'...\n', conf, problem=(5, 2, 'syntax'))
def test_first_line(self):
conf = ('indentation: {spaces: consistent}\n'
'document-start: disable\n')
self.check(' a: 1\n', conf, problem=(1, 3))
def test_explicit_block_mappings(self):
conf = 'indentation: {spaces: consistent}'
self.check('---\n'
'object:\n'
' ? key\n'
' : value\n', conf)
self.check('---\n'
'object:\n'
' ? key\n'
' :\n'
' value\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' ?\n'
' key\n'
' : value\n', conf)
self.check('---\n'
'object:\n'
' ?\n'
' key\n'
' :\n'
' value\n'
'...\n', conf)
self.check('---\n'
'- ? key\n'
' : value\n', conf)
self.check('---\n'
'- ? key\n'
' :\n'
' value\n'
'...\n', conf)
self.check('---\n'
'- ?\n'
' key\n'
' : value\n', conf)
self.check('---\n'
'- ?\n'
' key\n'
' :\n'
' value\n'
'...\n', conf)
self.check('---\n'
'object:\n'
' ? key\n'
' :\n'
' value\n'
'...\n', conf, problem=(5, 8))
self.check('---\n'
'- - ?\n'
' key\n'
' :\n'
' value\n'
'...\n', conf, problem=(5, 7))
self.check('---\n'
'object:\n'
' ?\n'
' key\n'
' :\n'
' value\n'
'...\n', conf, problem1=(4, 8), problem2=(6, 10))
self.check('---\n'
'object:\n'
' ?\n'
' key\n'
' :\n'
' value\n'
'...\n', conf, problem1=(4, 10), problem2=(6, 8))
def test_clear_sequence_item(self):
conf = 'indentation: {spaces: consistent}'
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, problem=(5, 4))
self.check('---\n'
'-\n'
' map: ping\n'
'-\n'
' map: ping\n', conf, problem=(5, 4))
self.check('---\n'
'-\n'
' - sequence\n'
'-\n'
' - sequence\n', conf, problem=(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))
conf = 'indentation: {spaces: 2}'
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))
def test_anchors(self):
conf = 'indentation: {spaces: consistent}'
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: consistent}'
self.check('---\n'
'-\n'
' "flow in block"\n'
'- >\n'
' Block scalar\n'
'- !!map # Block collection\n'
' foo: bar\n', conf)
conf = 'indentation: {spaces: consistent, 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)
def test_flows_imbrication(self):
conf = 'indentation: {spaces: consistent}'
self.check('---\n'
'[val]: value\n', conf)
self.check('---\n'
'{key}: value\n', conf)
self.check('---\n'
'{key: val}: value\n', conf)
self.check('---\n'
'[[val]]: value\n', conf)
self.check('---\n'
'{{key}}: value\n', conf)
self.check('---\n'
'{{key: val1}: val2}: value\n', conf)
self.check('---\n'
'- [val, {{key: val}: val}]: value\n'
'- {[val,\n'
' {{key: val}: val}]}\n'
'- {[val,\n'
' {{key: val,\n'
' key2}}]}\n'
'- {{{{{moustaches}}}}}\n'
'- {{{{{moustache,\n'
' moustache},\n'
' moustache}},\n'
' moustache}}\n', conf)
self.check('---\n'
'- {[val,\n'
' {{key: val}: val}]}\n',
conf, problem=(3, 6))
self.check('---\n'
'- {[val,\n'
' {{key: val,\n'
' key2}}]}\n',
conf, problem=(4, 6))
self.check('---\n'
'- {{{{{moustache,\n'
' moustache},\n'
' moustache}},\n'
' moustache}}\n',
conf, problem1=(4, 8), problem2=(5, 4))
class ScalarIndentationTestCase(RuleTestCase):
rule_id = 'indentation'
def test_basics_plain(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n'
'document-start: disable\n')
self.check('multi\n'
'line\n', conf)
self.check('multi\n'
' line\n', conf)
self.check('- multi\n'
' line\n', conf)
self.check('- multi\n'
' line\n', conf)
self.check('a key: multi\n'
' line\n', conf)
self.check('a key: multi\n'
' line\n', conf)
self.check('a key: multi\n'
' line\n', conf)
self.check('a key:\n'
' multi\n'
' line\n', conf)
self.check('- C code: void main() {\n'
' printf("foo");\n'
' }\n', conf)
self.check('- C code:\n'
' void main() {\n'
' printf("foo");\n'
' }\n', conf)
def test_check_multi_line_plain(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('multi\n'
' 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'
' 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))
def test_basics_quoted(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n'
'document-start: disable\n')
self.check('"multi\n'
' line"\n', conf)
self.check('- "multi\n'
' line"\n', conf)
self.check('a key: "multi\n'
' line"\n', conf)
self.check('a key:\n'
' "multi\n'
' line"\n', conf)
self.check('- jinja2: "{% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}"\n', conf)
self.check('- jinja2:\n'
' "{% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% 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: consistent,\n'
' 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))
self.check('- jinja2: "{% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}"\n', conf,
problem1=(2, 14), problem2=(4, 14))
self.check('- jinja2:\n'
' "{% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ 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: consistent,\n'
' check-multi-line-strings: no}\n'
'document-start: disable\n')
self.check('>\n'
' multi\n'
' line\n', conf)
self.check('- >\n'
' multi\n'
' line\n', conf)
self.check('- key: >\n'
' multi\n'
' line\n', conf)
self.check('- key:\n'
' >\n'
' multi\n'
' line\n', conf)
self.check('- ? >\n'
' multi-line\n'
' key\n'
' : >\n'
' multi-line\n'
' value\n', conf)
self.check('- ?\n'
' >\n'
' multi-line\n'
' key\n'
' :\n'
' >\n'
' multi-line\n'
' value\n', conf)
self.check('- jinja2: >\n'
' {% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}\n', conf)
def test_check_multi_line_folded_style(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('>\n'
' multi\n'
' line\n', conf, problem=(3, 4))
self.check('- >\n'
' multi\n'
' line\n', conf, problem=(3, 6))
self.check('- key: >\n'
' multi\n'
' line\n', conf, problem=(3, 6))
self.check('- key:\n'
' >\n'
' multi\n'
' line\n', conf, problem=(4, 8))
self.check('- ? >\n'
' multi-line\n'
' key\n'
' : >\n'
' multi-line\n'
' value\n', conf,
problem1=(3, 8), problem2=(6, 8))
self.check('- ?\n'
' >\n'
' multi-line\n'
' key\n'
' :\n'
' >\n'
' multi-line\n'
' value\n', conf,
problem1=(4, 8), problem2=(8, 8))
self.check('- jinja2: >\n'
' {% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}\n', conf,
problem1=(3, 7), problem2=(5, 7))
def test_basics_literal_style(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: no}\n'
'document-start: disable\n')
self.check('|\n'
' multi\n'
' line\n', conf)
self.check('- |\n'
' multi\n'
' line\n', conf)
self.check('- key: |\n'
' multi\n'
' line\n', conf)
self.check('- key:\n'
' |\n'
' multi\n'
' line\n', conf)
self.check('- ? |\n'
' multi-line\n'
' key\n'
' : |\n'
' multi-line\n'
' value\n', conf)
self.check('- ?\n'
' |\n'
' multi-line\n'
' key\n'
' :\n'
' |\n'
' multi-line\n'
' value\n', conf)
self.check('- jinja2: |\n'
' {% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}\n', conf)
def test_check_multi_line_literal_style(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('|\n'
' multi\n'
' line\n', conf, problem=(3, 4))
self.check('- |\n'
' multi\n'
' line\n', conf, problem=(3, 6))
self.check('- key: |\n'
' multi\n'
' line\n', conf, problem=(3, 6))
self.check('- key:\n'
' |\n'
' multi\n'
' line\n', conf, problem=(4, 8))
self.check('- ? |\n'
' multi-line\n'
' key\n'
' : |\n'
' multi-line\n'
' value\n', conf,
problem1=(3, 8), problem2=(6, 8))
self.check('- ?\n'
' |\n'
' multi-line\n'
' key\n'
' :\n'
' |\n'
' multi-line\n'
' value\n', conf,
problem1=(4, 8), problem2=(8, 8))
self.check('- jinja2: |\n'
' {% if ansible is defined %}\n'
' {{ ansible }}\n'
' {% else %}\n'
' {{ chef }}\n'
' {% endif %}\n', conf,
problem1=(3, 7), problem2=(5, 7))
# The following "paragraph" examples are inspired from
# http://stackoverflow.com/questions/3790454/in-yaml-how-do-i-break-a-string-over-multiple-lines
def test_paragraph_plain(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('- long text: very "long"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\n', conf)
self.check('- long text: very "long"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\n', conf,
problem1=(2, 5), problem2=(4, 5), problem3=(5, 5))
self.check('- long text:\n'
' very "long"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\n', conf)
def test_paragraph_double_quoted(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('- long text: "very \\"long\\"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces."\n', conf)
self.check('- long text: "very \\"long\\"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces."\n', conf,
problem1=(2, 5), problem2=(4, 5), problem3=(5, 5))
self.check('- long text: "very \\"long\\"\n'
'\'string\' with\n'
'\n'
'paragraph gap, \\n and\n'
'spaces."\n', conf,
problem1=(2, 1), problem2=(4, 1), problem3=(5, 1))
self.check('- long text:\n'
' "very \\"long\\"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces."\n', conf)
def test_paragraph_single_quoted(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('- long text: \'very "long"\n'
' \'\'string\'\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\'\n', conf)
self.check('- long text: \'very "long"\n'
' \'\'string\'\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\'\n', conf,
problem1=(2, 5), problem2=(4, 5), problem3=(5, 5))
self.check('- long text: \'very "long"\n'
'\'\'string\'\' with\n'
'\n'
'paragraph gap, \\n and\n'
'spaces.\'\n', conf,
problem1=(2, 1), problem2=(4, 1), problem3=(5, 1))
self.check('- long text:\n'
' \'very "long"\n'
' \'\'string\'\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\'\n', conf)
def test_paragraph_folded(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('- long text: >\n'
' very "long"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\n', conf)
self.check('- long text: >\n'
' very "long"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\n', conf,
problem1=(3, 6), problem2=(5, 7), problem3=(6, 8))
def test_paragraph_literal(self):
conf = ('indentation: {spaces: consistent,\n'
' check-multi-line-strings: yes}\n'
'document-start: disable\n')
self.check('- long text: |\n'
' very "long"\n'
' \'string\' with\n'
'\n'
' paragraph gap, \\n and\n'
' spaces.\n', conf)
self.check('- long text: |\n'
' very "long"\n'
' \'string\' with\n'
'\n'
' 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))
yamllint-1.2.1/tests/rules/test_comments_indentation.py 0000664 0001750 0001750 00000011544 12667043545 024243 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class CommentsIndentationTestCase(RuleTestCase):
rule_id = 'comments-indentation'
def test_disable(self):
conf = 'comments-indentation: disable'
self.check('---\n'
' # line 1\n'
'# line 2\n'
' # line 3\n'
' # line 4\n'
'\n'
'obj:\n'
' # these\n'
' # are\n'
' # [good]\n'
'# bad\n'
' # comments\n'
' a: b\n'
'\n'
'obj1:\n'
' a: 1\n'
' # comments\n'
'\n'
'obj2:\n'
' b: 2\n'
'\n'
'# empty\n'
'#\n'
'# comment\n'
'...\n', conf)
def test_enabled(self):
conf = 'comments-indentation: enable'
self.check('---\n'
'# line 1\n'
'# line 2\n', conf)
self.check('---\n'
' # line 1\n'
'# line 2\n', conf, problem=(2, 2))
self.check('---\n'
' # line 1\n'
' # line 2\n', conf, problem1=(2, 3), problem2=(3, 3))
self.check('---\n'
'obj:\n'
' # normal\n'
' a: b\n', conf)
self.check('---\n'
'obj:\n'
' # bad\n'
' a: b\n', conf, problem=(3, 2))
self.check('---\n'
'obj:\n'
'# bad\n'
' a: b\n', conf, problem=(3, 1))
self.check('---\n'
'obj:\n'
' # bad\n'
' a: b\n', conf, problem=(3, 4))
self.check('---\n'
'obj:\n'
' # these\n'
' # are\n'
' # [good]\n'
'# bad\n'
' # comments\n'
' a: b\n', conf,
problem1=(3, 2), problem2=(4, 4),
problem3=(6, 1), problem4=(7, 7))
self.check('---\n'
'obj1:\n'
' a: 1\n'
' # the following line is disabled\n'
' # b: 2\n', conf)
self.check('---\n'
'obj1:\n'
' a: 1\n'
' # b: 2\n'
'\n'
'obj2:\n'
' b: 2\n', conf)
self.check('---\n'
'obj1:\n'
' a: 1\n'
' # b: 2\n'
'# this object is useless\n'
'obj2: no\n', conf)
self.check('---\n'
'obj1:\n'
' a: 1\n'
'# this object is useless\n'
' # b: 2\n'
'obj2: no\n', conf, problem=(5, 3))
self.check('---\n'
'obj1:\n'
' a: 1\n'
' # comments\n'
' b: 2\n', conf)
self.check('---\n'
'my list for today:\n'
' - todo 1\n'
' - todo 2\n'
' # commented for now\n'
' # - todo 3\n'
'...\n', conf)
def test_first_line(self):
conf = 'comments-indentation: enable'
self.check('# comment\n', conf)
self.check(' # comment\n', conf, problem=(1, 3))
def test_no_newline_at_end(self):
conf = ('comments-indentation: enable\n'
'new-line-at-end-of-file: disable\n')
self.check('# comment', conf)
self.check(' # comment', conf, problem=(1, 3))
def test_empty_comment(self):
conf = 'comments-indentation: enable'
self.check('---\n'
'# hey\n'
'# normal\n'
'#\n', conf)
self.check('---\n'
'# hey\n'
'# normal\n'
' #\n', conf, problem=(4, 2))
yamllint-1.2.1/tests/rules/test_new_line_at_end_of_file.py 0000664 0001750 0001750 00000003023 12667043545 024610 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class NewLineAtEndOfFileTestCase(RuleTestCase):
rule_id = 'new-line-at-end-of-file'
def test_disabled(self):
conf = ('new-line-at-end-of-file: disable\n'
'empty-lines: disable\n'
'document-start: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('word', conf)
self.check('Sentence.\n', conf)
def test_enabled(self):
conf = ('new-line-at-end-of-file: enable\n'
'empty-lines: disable\n'
'document-start: disable\n')
self.check('', conf)
self.check('\n', conf)
self.check('word', conf, problem=(1, 5))
self.check('Sentence.\n', conf)
self.check('---\n'
'yaml: document\n'
'...', conf, problem=(3, 4))
yamllint-1.2.1/tests/rules/test_hyphens.py 0000664 0001750 0001750 00000007247 12653727046 021505 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class HyphenTestCase(RuleTestCase):
rule_id = 'hyphens'
def test_disabled(self):
conf = 'hyphens: disable'
self.check('---\n'
'- elem1\n'
'- elem2\n', conf)
self.check('---\n'
'- elem1\n'
'- elem2\n', conf)
self.check('---\n'
'- elem1\n'
'- elem2\n', conf)
self.check('---\n'
'- elem1\n'
'- elem2\n', conf)
self.check('---\n'
'object:\n'
' - elem1\n'
' - elem2\n', conf)
self.check('---\n'
'object:\n'
' - elem1\n'
' - elem2\n', conf)
self.check('---\n'
'object:\n'
' subobject:\n'
' - elem1\n'
' - elem2\n', conf)
self.check('---\n'
'object:\n'
' subobject:\n'
' - elem1\n'
' - elem2\n', conf)
def test_enabled(self):
conf = 'hyphens: {max-spaces-after: 1}'
self.check('---\n'
'- elem1\n'
'- elem2\n', conf)
self.check('---\n'
'- elem1\n'
'- elem2\n', conf, problem=(3, 3))
self.check('---\n'
'- elem1\n'
'- elem2\n', conf, problem1=(2, 3), problem2=(3, 3))
self.check('---\n'
'- elem1\n'
'- elem2\n', conf, problem=(2, 3))
self.check('---\n'
'object:\n'
' - elem1\n'
' - elem2\n', conf, problem=(4, 5))
self.check('---\n'
'object:\n'
' - elem1\n'
' - elem2\n', conf, problem1=(3, 5), problem2=(4, 5))
self.check('---\n'
'object:\n'
' subobject:\n'
' - elem1\n'
' - elem2\n', conf, problem=(5, 7))
self.check('---\n'
'object:\n'
' subobject:\n'
' - elem1\n'
' - elem2\n', conf, problem1=(4, 7), problem2=(5, 7))
def test_max_3(self):
conf = 'hyphens: {max-spaces-after: 3}'
self.check('---\n'
'- elem1\n'
'- elem2\n', conf)
self.check('---\n'
'- elem1\n'
'- elem2\n', conf, problem=(2, 5))
self.check('---\n'
'a:\n'
' b:\n'
' - elem1\n'
' - elem2\n', conf)
self.check('---\n'
'a:\n'
' b:\n'
' - elem1\n'
' - elem2\n', conf, problem1=(4, 9), problem2=(5, 9))
yamllint-1.2.1/tests/rules/test_braces.py 0000664 0001750 0001750 00000007772 12653727046 021271 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class ColonTestCase(RuleTestCase):
rule_id = 'braces'
def test_disabled(self):
conf = 'braces: disable'
self.check('---\n'
'dict1: {}\n'
'dict2: { }\n'
'dict3: { a: 1, b}\n'
'dict4: {a: 1, b, c: 3 }\n'
'dict5: {a: 1, b, c: 3 }\n'
'dict6: { a: 1, b, c: 3 }\n'
'dict7: { a: 1, b, c: 3 }\n', conf)
def test_min_spaces(self):
conf = 'braces: {max-spaces-inside: -1, min-spaces-inside: 0}'
self.check('---\n'
'dict: {}\n', conf)
conf = 'braces: {max-spaces-inside: -1, min-spaces-inside: 1}'
self.check('---\n'
'dict: {}\n', conf, problem=(2, 8))
self.check('---\n'
'dict: { }\n', conf)
self.check('---\n'
'dict: {a: 1, b}\n', conf,
problem1=(2, 8), problem2=(2, 15))
self.check('---\n'
'dict: { a: 1, b }\n', conf)
self.check('---\n'
'dict: {\n'
' a: 1,\n'
' b\n'
'}\n', conf)
conf = 'braces: {max-spaces-inside: -1, min-spaces-inside: 3}'
self.check('---\n'
'dict: { a: 1, b }\n', conf,
problem1=(2, 9), problem2=(2, 17))
self.check('---\n'
'dict: { a: 1, b }\n', conf)
def test_max_spaces(self):
conf = 'braces: {max-spaces-inside: 0, min-spaces-inside: -1}'
self.check('---\n'
'dict: {}\n', conf)
self.check('---\n'
'dict: { }\n', conf, problem=(2, 8))
self.check('---\n'
'dict: {a: 1, b}\n', conf)
self.check('---\n'
'dict: { a: 1, b }\n', conf,
problem1=(2, 8), problem2=(2, 16))
self.check('---\n'
'dict: { a: 1, b }\n', conf,
problem1=(2, 10), problem2=(2, 20))
self.check('---\n'
'dict: {\n'
' a: 1,\n'
' b\n'
'}\n', conf)
conf = 'braces: {max-spaces-inside: 3, min-spaces-inside: -1}'
self.check('---\n'
'dict: { a: 1, b }\n', conf)
self.check('---\n'
'dict: { a: 1, b }\n', conf,
problem1=(2, 11), problem2=(2, 23))
def test_min_and_max_spaces(self):
conf = 'braces: {max-spaces-inside: 0, min-spaces-inside: 0}'
self.check('---\n'
'dict: {}\n', conf)
self.check('---\n'
'dict: { }\n', conf, problem=(2, 8))
self.check('---\n'
'dict: { a: 1, b}\n', conf, problem=(2, 10))
conf = 'braces: {max-spaces-inside: 1, min-spaces-inside: 1}'
self.check('---\n'
'dict: {a: 1, b, c: 3 }\n', conf, problem=(2, 8))
conf = 'braces: {max-spaces-inside: 2, min-spaces-inside: 0}'
self.check('---\n'
'dict: {a: 1, b, c: 3 }\n', conf)
self.check('---\n'
'dict: { a: 1, b, c: 3 }\n', conf)
self.check('---\n'
'dict: { a: 1, b, c: 3 }\n', conf, problem=(2, 10))
yamllint-1.2.1/tests/__init__.py 0000664 0001750 0001750 00000000000 12645536260 017346 0 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/tests/common.py 0000664 0001750 0001750 00000003367 12653727046 017125 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import unittest
import yaml
from yamllint.config import YamlLintConfig
from yamllint import linter
class RuleTestCase(unittest.TestCase):
def build_fake_config(self, conf):
if conf is None:
conf = {}
else:
conf = yaml.safe_load(conf)
conf = {'extends': 'default',
'rules': conf}
return YamlLintConfig(yaml.safe_dump(conf))
def check(self, source, conf, **kwargs):
expected_problems = []
for key in kwargs:
assert key.startswith('problem')
if len(kwargs[key]) > 2:
if kwargs[key][2] == 'syntax':
rule_id = None
else:
rule_id = kwargs[key][2]
else:
rule_id = self.rule_id
expected_problems.append(linter.LintProblem(
kwargs[key][0], kwargs[key][1], rule=rule_id))
expected_problems.sort()
real_problems = list(linter.run(source, self.build_fake_config(conf)))
self.assertEqual(real_problems, expected_problems)
yamllint-1.2.1/tests/test_spec_examples.py 0000664 0001750 0001750 00000016457 12666346130 021523 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
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))
yamllint-1.2.1/tests/test_linter.py 0000664 0001750 0001750 00000003016 12666346130 020153 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
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())
yamllint-1.2.1/tests/yaml-1.2-spec-examples/ 0000775 0001750 0001750 00000000000 12675233100 021241 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.2 0000664 0001750 0001750 00000000120 12653727046 023124 0 ustar adrien adrien 0000000 0000000 hr: 65 # Home runs
avg: 0.278 # Batting average
rbi: 147 # Runs Batted In
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.22 0000664 0001750 0001750 00000000173 12653727046 023216 0 ustar adrien adrien 0000000 0000000 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
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.19 0000664 0001750 0001750 00000000015 12653727046 023224 0 ustar adrien adrien 0000000 0000000 [
foo: bar
]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.20 0000664 0001750 0001750 00000000115 12653727046 023216 0 ustar adrien adrien 0000000 0000000 -
"flow in block"
- >
Block scalar
- !!map # Block collection
foo : bar
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.7 0000664 0001750 0001750 00000000032 12653727046 023137 0 ustar adrien adrien 0000000 0000000 >
foo
bar
baz
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.4 0000664 0001750 0001750 00000000136 12653727046 023135 0 ustar adrien adrien 0000000 0000000 -
name: Mark McGwire
hr: 65
avg: 0.278
-
name: Sammy Sosa
hr: 63
avg: 0.288
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.12 0000664 0001750 0001750 00000000140 12653727046 023212 0 ustar adrien adrien 0000000 0000000 # Tabs and spaces
quoted: "Quoted "
block: |
void main() {
printf("Hello, world!\n");
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.8 0000664 0001750 0001750 00000000221 12653727046 023213 0 ustar adrien adrien 0000000 0000000 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 ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.4 0000664 0001750 0001750 00000000073 12653727046 023142 0 ustar adrien adrien 0000000 0000000 "implicit block key" : [
"implicit flow key" : value,
]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.7 0000664 0001750 0001750 00000000023 12653727046 023141 0 ustar adrien adrien 0000000 0000000 |
literal
text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.16 0000664 0001750 0001750 00000000033 12653727046 023222 0 ustar adrien adrien 0000000 0000000 block mapping:
key: value
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.27 0000664 0001750 0001750 00000001204 12653727046 023217 0 ustar adrien adrien 0000000 0000000 --- !
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.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.5 0000664 0001750 0001750 00000000122 12653727046 023135 0 ustar adrien adrien 0000000 0000000 Folding:
"Empty line
as a line feed"
Chomping: |
Clipped empty lines
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.6 0000664 0001750 0001750 00000000040 12653727046 023135 0 ustar adrien adrien 0000000 0000000 >-
trimmed
as
space
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.14 0000664 0001750 0001750 00000000033 12653727046 023215 0 ustar adrien adrien 0000000 0000000 Bad escapes:
"\c
\xq-"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.3 0000664 0001750 0001750 00000000034 12653727046 023135 0 ustar adrien adrien 0000000 0000000 - foo: bar
- - baz
- baz
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-9.6 0000664 0001750 0001750 00000000065 12653727046 023147 0 ustar adrien adrien 0000000 0000000 Document
---
# Empty
...
%YAML 1.2
---
matches %: 20
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.13 0000664 0001750 0001750 00000000131 12653727046 023213 0 ustar adrien adrien 0000000 0000000 "Fun with \\
\" \a \b \e \f \
\n \r \t \v \0 \
\ \_ \N \L \P \
\x41 \u0041 \U00000041"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.11 0000664 0001750 0001750 00000000067 12653727046 023223 0 ustar adrien adrien 0000000 0000000 implicit block key : [
implicit flow key : value,
]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.6 0000664 0001750 0001750 00000000062 12653727046 023142 0 ustar adrien adrien 0000000 0000000 " 1st non-empty
2nd non-empty
3rd non-empty "
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.1 0000664 0001750 0001750 00000000154 12653727046 023137 0 ustar adrien adrien 0000000 0000000 First occurrence: &anchor Foo
Second occurrence: *anchor
Override anchor: &anchor Bar
Reuse anchor: *anchor
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.21 0000664 0001750 0001750 00000000112 12653727046 023213 0 ustar adrien adrien 0000000 0000000 - [ YAML : separate ]
- [ : empty key entry ]
- [ {JSON: like}:adjacent ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-9.2 0000664 0001750 0001750 00000000044 12653727046 023140 0 ustar adrien adrien 0000000 0000000 %YAML 1.2
---
Document
... # Suffix
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.14 0000664 0001750 0001750 00000000050 12653727046 023217 0 ustar adrien adrien 0000000 0000000 block sequence:
- one
- two : three
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.20 0000664 0001750 0001750 00000000025 12653727046 023215 0 ustar adrien adrien 0000000 0000000 [
? foo
bar : baz
]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.11 0000664 0001750 0001750 00000000061 12653727046 023213 0 ustar adrien adrien 0000000 0000000 |
Line break (no glyph)
Line break (glyphed)
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-9.1 0000664 0001750 0001750 00000000033 12653727046 023135 0 ustar adrien adrien 0000000 0000000 # Comment
# lines
Document
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.9 0000664 0001750 0001750 00000000313 12653727046 023216 0 ustar adrien adrien 0000000 0000000 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 ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.24 0000664 0001750 0001750 00000000452 12653727046 023220 0 ustar adrien adrien 0000000 0000000 %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.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.2 0000664 0001750 0001750 00000000034 12653727046 023134 0 ustar adrien adrien 0000000 0000000 ? a
: - b
- - c
- d
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.17 0000664 0001750 0001750 00000000112 12653727046 023220 0 ustar adrien adrien 0000000 0000000 {
unquoted : "separate",
http://foo.com,
omitted value:,
: omitted key,
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.21 0000664 0001750 0001750 00000000060 12653727046 023216 0 ustar adrien adrien 0000000 0000000 literal: |2
value
folded:
!foo
>1
value
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.16 0000664 0001750 0001750 00000000213 12653727046 023214 0 ustar adrien adrien 0000000 0000000 name: Mark McGwire
accomplishment: >
Mark set a major league
home run record in 1998.
stats: |
65 Home Runs
0.278 Batting Average
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.4 0000664 0001750 0001750 00000000073 12653727046 023140 0 ustar adrien adrien 0000000 0000000 sequence: [ one, two, ]
mapping: { sky: blue, sea: green }
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.13 0000664 0001750 0001750 00000000126 12653727046 023222 0 ustar adrien adrien 0000000 0000000 >
folded
line
next
line
* bullet
* list
* line
last
line
# Comment
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.1 0000664 0001750 0001750 00000000455 12653727046 023142 0 ustar adrien adrien 0000000 0000000 # 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.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.5 0000664 0001750 0001750 00000000077 12653727046 023147 0 ustar adrien adrien 0000000 0000000 "folded
to a space,
to a line feed, or \
\ non-content"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.3 0000664 0001750 0001750 00000000205 12653727046 023131 0 ustar adrien adrien 0000000 0000000 american:
- Boston Red Sox
- Detroit Tigers
- New York Yankees
national:
- New York Mets
- Chicago Cubs
- Atlanta Braves
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.21 0000664 0001750 0001750 00000000145 12653727046 023220 0 ustar adrien adrien 0000000 0000000 %TAG !m! !my-
--- # Bulb here
!m!light fluorescent
...
%TAG !m! !my-
--- # Color here
!m!light green
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.10 0000664 0001750 0001750 00000000051 12653727046 023211 0 ustar adrien adrien 0000000 0000000 commercial-at: @text
grave-accent: `text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.20 0000664 0001750 0001750 00000000152 12653727046 023211 0 ustar adrien adrien 0000000 0000000 canonical: 1.23015e+3
exponential: 12.3015e+02
fixed: 1230.15
negative infinity: -.inf
not a number: .NaN
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.22 0000664 0001750 0001750 00000000066 12653727046 023223 0 ustar adrien adrien 0000000 0000000 %TAG !e! tag:example.com,2000:app/
---
- !e!foo "bar"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.13 0000664 0001750 0001750 00000000040 12653727046 023214 0 ustar adrien adrien 0000000 0000000 - [ one, two, ]
- [three ,four]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.3 0000664 0001750 0001750 00000000051 12653727046 023136 0 ustar adrien adrien 0000000 0000000 - |
text
- >
text
text
- |2
text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.11 0000664 0001750 0001750 00000000216 12653727046 023212 0 ustar adrien adrien 0000000 0000000 ? - Detroit Tigers
- Chicago cubs
:
- 2001-07-23
? [ New York Yankees,
Atlanta Braves ]
: [ 2001-07-02, 2001-08-12,
2001-08-14 ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.1 0000664 0001750 0001750 00000000020 12653727046 023125 0 ustar adrien adrien 0000000 0000000 # Comment only.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.19 0000664 0001750 0001750 00000000077 12653727046 023227 0 ustar adrien adrien 0000000 0000000 canonical: 12345
decimal: +12345
octal: 0o14
hexadecimal: 0xC
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.16 0000664 0001750 0001750 00000000063 12653727046 023223 0 ustar adrien adrien 0000000 0000000 %TAG !yaml! tag:yaml.org,2002:
---
!yaml!str "foo"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.7 0000664 0001750 0001750 00000000202 12653727046 023132 0 ustar adrien adrien 0000000 0000000 # Ranking of 1998 home runs
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# Team ranking
---
- Chicago Cubs
- St Louis Cardinals
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.8 0000664 0001750 0001750 00000000073 12653727046 023146 0 ustar adrien adrien 0000000 0000000 'implicit block key' : [
'implicit flow key' : value,
]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.5 0000664 0001750 0001750 00000000126 12653727046 023135 0 ustar adrien adrien 0000000 0000000 - [name , hr, avg ]
- [Mark McGwire, 65, 0.278]
- [Sammy Sosa , 63, 0.288]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.27 0000664 0001750 0001750 00000000072 12653727046 023225 0 ustar adrien adrien 0000000 0000000 %TAG !e! tag:example,2000:app/
---
- !e! foo
- !h!bar baz
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.4 0000664 0001750 0001750 00000000106 12653727046 023136 0 ustar adrien adrien 0000000 0000000 plain: text
lines
quoted: "text
lines"
block: |
text
lines
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.2 0000664 0001750 0001750 00000000053 12653727046 023134 0 ustar adrien adrien 0000000 0000000 - Invalid use of BOM
- Inside a document.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.24 0000664 0001750 0001750 00000000062 12653727046 023222 0 ustar adrien adrien 0000000 0000000 - !!str "a"
- 'b'
- &anchor "c"
- *anchor
- !!str
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.15 0000664 0001750 0001750 00000000030 12653727046 023214 0 ustar adrien adrien 0000000 0000000 %YAML 1.2
%YAML 1.1
foo
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.17 0000664 0001750 0001750 00000000136 12653727046 023227 0 ustar adrien adrien 0000000 0000000 ? explicit key # Empty value
? |
block key
: - one # Explicit compact
- two # block value
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.6 0000664 0001750 0001750 00000000065 12653727046 023217 0 ustar adrien adrien 0000000 0000000 negative: !!int -12
zero: !!int 0
positive: !!int 34
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.10 0000664 0001750 0001750 00000000332 12653727046 023215 0 ustar adrien adrien 0000000 0000000 # Outside flow collection:
- ::vector
- ": - ()"
- Up, up, and away!
- -123
- http://example.com/foo#bar
# Inside flow collection:
- [ ::vector,
": - ()",
"Up, up and away!",
-123,
http://example.com/foo#bar ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.4 0000664 0001750 0001750 00000000101 12653727046 023204 0 ustar adrien adrien 0000000 0000000 !!null null: value for null key
key with null value: !!null null
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.21 0000664 0001750 0001750 00000000061 12653727046 023211 0 ustar adrien adrien 0000000 0000000 null:
booleans: [ true, false ]
string: '012345'
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.15 0000664 0001750 0001750 00000000134 12653727046 023223 0 ustar adrien adrien 0000000 0000000 - # Empty
- |
block node
- - one # Compact
- two # sequence
- one: two # Compact mapping
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.18 0000664 0001750 0001750 00000000122 12653727046 023221 0 ustar adrien adrien 0000000 0000000 # Private
!foo "bar"
...
# Global
%TAG ! tag:example.com,2000:app/
---
!foo "bar"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.5 0000664 0001750 0001750 00000000230 12653755725 023144 0 ustar adrien adrien 0000000 0000000 # Strip
# Comments:
strip: |-
# text
# Clip
# comments:
clip: |
# text
# Keep
# comments:
keep: |+
# text
# Trail
# comments.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.20 0000664 0001750 0001750 00000000064 12653727046 023217 0 ustar adrien adrien 0000000 0000000 %TAG !e! tag:example.com,2000:app/
---
!e!foo "bar"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.18 0000664 0001750 0001750 00000000136 12653727046 023222 0 ustar adrien adrien 0000000 0000000 plain:
This unquoted scalar
spans many lines.
quoted: "So does this
quoted scalar.\n"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.16 0000664 0001750 0001750 00000000052 12653727046 023222 0 ustar adrien adrien 0000000 0000000 {
? explicit: entry,
implicit: entry,
?
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.10 0000664 0001750 0001750 00000000177 12653727046 023217 0 ustar adrien adrien 0000000 0000000 ---
hr:
- Mark McGwire
# Following node labeled SS
- &SS Sammy Sosa
rbi:
- *SS # Subsequent occurrence
- Ken Griffey
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.28 0000664 0001750 0001750 00000000636 12653727046 023230 0 ustar adrien adrien 0000000 0000000 ---
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
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.23 0000664 0001750 0001750 00000000046 12653727046 023223 0 ustar adrien adrien 0000000 0000000 - [ a, b ]
- { a: b }
- "a"
- 'b'
- c
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.9 0000664 0001750 0001750 00000000062 12653727046 023145 0 ustar adrien adrien 0000000 0000000 ' 1st non-empty
2nd non-empty
3rd non-empty '
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.5 0000664 0001750 0001750 00000000020 12653727046 023131 0 ustar adrien adrien 0000000 0000000 # Comment only.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.1 0000664 0001750 0001750 00000000204 12653727046 023134 0 ustar adrien adrien 0000000 0000000 - | # Empty header
literal
- >1 # Indentation indicator
folded
- |+ # Chomping indicator
keep
- >1- # Both indicators
strip
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.12 0000664 0001750 0001750 00000000210 12653727046 023205 0 ustar adrien adrien 0000000 0000000 ---
# Products purchased
- item : Super Hoop
quantity: 1
- item : Basketball
quantity: 4
- item : Big Shoes
quantity: 1
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.14 0000664 0001750 0001750 00000000131 12653727046 023216 0 ustar adrien adrien 0000000 0000000 [
"double
quoted", 'single
quoted',
plain
text, [ nested ],
single: pair,
]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.12 0000664 0001750 0001750 00000000127 12653727046 023222 0 ustar adrien adrien 0000000 0000000 >
folded
line
next
line
* bullet
* list
* line
last
line
# Comment
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.1 0000664 0001750 0001750 00000000215 12653727046 023207 0 ustar adrien adrien 0000000 0000000 Block style: !!map
Clark : Evans
Ingy : döt Net
Oren : Ben-Kiki
Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.3 0000664 0001750 0001750 00000000030 12653727046 023132 0 ustar adrien adrien 0000000 0000000 {
? foo :,
: bar,
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.3 0000664 0001750 0001750 00000000133 12653727046 023210 0 ustar adrien adrien 0000000 0000000 Block style: !!str |-
String: just a theory.
Flow style: !!str "String: just a theory."
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.9 0000664 0001750 0001750 00000000035 12653727046 023144 0 ustar adrien adrien 0000000 0000000 key: # Comment
valueeof
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.9 0000664 0001750 0001750 00000000021 12653727046 023141 0 ustar adrien adrien 0000000 0000000 >
folded
text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.14 0000664 0001750 0001750 00000000102 12653727046 023213 0 ustar adrien adrien 0000000 0000000 %YAML 1.3 # Attempt parsing
# with a warning
---
"foo"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.1 0000664 0001750 0001750 00000000052 12653727046 023127 0 ustar adrien adrien 0000000 0000000 - Mark McGwire
- Sammy Sosa
- Ken Griffey
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.9 0000664 0001750 0001750 00000000023 12653727046 023140 0 ustar adrien adrien 0000000 0000000 %YAML 1.2
--- text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.19 0000664 0001750 0001750 00000000112 12653727046 023221 0 ustar adrien adrien 0000000 0000000 %TAG !! tag:example.com,2000:app/
---
!!int 1 - 3 # Interval, not integer
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.26 0000664 0001750 0001750 00000000237 12653727046 023223 0 ustar adrien adrien 0000000 0000000 # 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
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.15 0000664 0001750 0001750 00000000074 12653727046 023225 0 ustar adrien adrien 0000000 0000000 - { one : two , three: four , }
- {five: six,seven : eight}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.26 0000664 0001750 0001750 00000000120 12653727046 023216 0 ustar adrien adrien 0000000 0000000 %TAG !e! tag:example.com,2000:app/
---
- !local foo
- !!str bar
- !e!tag%21 baz
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.12 0000664 0001750 0001750 00000000141 12653727046 023214 0 ustar adrien adrien 0000000 0000000 { first: Sammy, last: Sosa }:
# Statistics:
hr: # Home runs
65
avg: # Average
0.278
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.8 0000664 0001750 0001750 00000000036 12653727046 023143 0 ustar adrien adrien 0000000 0000000 single: 'text'
double: "text"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.9 0000664 0001750 0001750 00000000163 12653727046 023142 0 ustar adrien adrien 0000000 0000000 ---
hr: # 1998 hr ranking
- Mark McGwire
- Sammy Sosa
rbi:
# 1998 rbi ranking
- Sammy Sosa
- Ken Griffey
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.4 0000664 0001750 0001750 00000000060 12653727046 023137 0 ustar adrien adrien 0000000 0000000 strip: |-
text
clip: |
text
keep: |+
text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.22 0000664 0001750 0001750 00000000076 12653727046 023225 0 ustar adrien adrien 0000000 0000000 [ foo
bar: invalid,
"foo...>1K characters...bar": invalid ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.25 0000664 0001750 0001750 00000000211 12653727046 023212 0 ustar adrien adrien 0000000 0000000 # Sets are represented as a
# Mapping where each key is
# associated with a null value
--- !!set
? Mark McGwire
? Sammy Sosa
? Ken Griff
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.6 0000664 0001750 0001750 00000000120 12653727046 023130 0 ustar adrien adrien 0000000 0000000 Mark McGwire: {hr: 65, avg: 0.278}
Sammy Sosa: {
hr: 63,
avg: 0.288
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.18 0000664 0001750 0001750 00000000076 12653727046 023233 0 ustar adrien adrien 0000000 0000000 plain key: in-line value
: # Both empty
"quoted key":
- entry
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.18 0000664 0001750 0001750 00000000062 12653727046 023225 0 ustar adrien adrien 0000000 0000000 {
"adjacent":value,
"readable": value,
"empty":
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.11 0000664 0001750 0001750 00000000130 12653727046 023213 0 ustar adrien adrien 0000000 0000000 >
folded
line
next
line
* bullet
* list
* lines
last
line
# Comment
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.23 0000664 0001750 0001750 00000000053 12653727046 023220 0 ustar adrien adrien 0000000 0000000 !!str &a1 "foo":
!!str bar
&a2 baz : *a1
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.23 0000664 0001750 0001750 00000000411 12653727046 023212 0 ustar adrien adrien 0000000 0000000 ---
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.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.10 0000664 0001750 0001750 00000000021 12653727046 023207 0 ustar adrien adrien 0000000 0000000 # Comment
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.13 0000664 0001750 0001750 00000000054 12653727046 023214 0 ustar adrien adrien 0000000 0000000 # ASCII Art
--- |
\//||\/||
// || ||__
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.2 0000664 0001750 0001750 00000000202 12653727046 023204 0 ustar adrien adrien 0000000 0000000 Block style: !!seq
- Clark Evans
- Ingy döt Net
- Oren Ben-Kiki
Flow style: !!seq [ Clark Evans, Ingy döt Net, Oren Ben-Kiki ]
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.2 0000664 0001750 0001750 00000000042 12653727046 023134 0 ustar adrien adrien 0000000 0000000 {
foo : !!str,
!!str : bar,
}
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.7 0000664 0001750 0001750 00000000157 12653727046 023222 0 ustar adrien adrien 0000000 0000000 negative: !!float -1
zero: !!float 0
positive: !!float 2.3e4
infinity: !!float .inf
not a number: !!float .nan
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.28 0000664 0001750 0001750 00000000067 12653727046 023232 0 ustar adrien adrien 0000000 0000000 # Assuming conventional resolution:
- "12"
- 12
- ! 12
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.3 0000664 0001750 0001750 00000000076 12653727046 023142 0 ustar adrien adrien 0000000 0000000 sequence:
- one
- two
mapping:
? sky
: blue
sea : green
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.8 0000664 0001750 0001750 00000000053 12653727046 023145 0 ustar adrien adrien 0000000 0000000 |
literal
text
# Comment
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.17 0000664 0001750 0001750 00000000261 12653727046 023220 0 ustar adrien adrien 0000000 0000000 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: '|\-*-/|'
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.2 0000664 0001750 0001750 00000000105 12653727046 023135 0 ustar adrien adrien 0000000 0000000 - |
detected
- >
# detected
- |1
explicit
- >
detected
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.13 0000664 0001750 0001750 00000000115 12653727046 023216 0 ustar adrien adrien 0000000 0000000 %FOO bar baz # Should be ignored
# with a warning.
--- "foo"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.7 0000664 0001750 0001750 00000000061 12653727046 023140 0 ustar adrien adrien 0000000 0000000 literal: |
some
text
folded: >
some
text
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.12 0000664 0001750 0001750 00000000056 12653727046 023222 0 ustar adrien adrien 0000000 0000000 1st non-empty
2nd non-empty
3rd non-empty
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.22 0000664 0001750 0001750 00000000103 12653727046 023215 0 ustar adrien adrien 0000000 0000000 sequence: !!seq
- entry
- !!seq
- nested
mapping: !!map
foo: bar
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.24 0000664 0001750 0001750 00000000055 12653727046 023223 0 ustar adrien adrien 0000000 0000000 ! foo :
! baz
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-7.7 0000664 0001750 0001750 00000000027 12653727046 023144 0 ustar adrien adrien 0000000 0000000 'here''s to "quotes"'
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.6 0000664 0001750 0001750 00000000036 12653727046 023144 0 ustar adrien adrien 0000000 0000000 strip: >-
clip: >
keep: |+
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.8 0000664 0001750 0001750 00000000034 12653727046 023142 0 ustar adrien adrien 0000000 0000000 "
foo
bar
baz
"
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-9.3 0000664 0001750 0001750 00000000112 12653727046 023135 0 ustar adrien adrien 0000000 0000000 Bare
document
...
# No document
...
|
%!PS-Adobe-2.0 # Not the first line
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-5.6 0000664 0001750 0001750 00000000056 12653727046 023143 0 ustar adrien adrien 0000000 0000000 anchored: !local &anchor value
alias: *anchor
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.10 0000664 0001750 0001750 00000000130 12653727046 023212 0 ustar adrien adrien 0000000 0000000 >
folded
line
next
line
* bullet
* list
* lines
last
line
# Comment
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-9.5 0000664 0001750 0001750 00000000074 12653727046 023146 0 ustar adrien adrien 0000000 0000000 %YAML 1.2
--- |
%!PS-Adobe-2.0
...
%YAML1.2
---
# Empty
...
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.15 0000664 0001750 0001750 00000000170 12653727046 023215 0 ustar adrien adrien 0000000 0000000 >
Sammy Sosa completed another
fine season with great stats.
63 Home Runs
0.288 Batting Average
What a year!
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.29 0000664 0001750 0001750 00000000073 12653727046 023230 0 ustar adrien adrien 0000000 0000000 First occurrence: &anchor Value
Second occurrence: *anchor
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.25 0000664 0001750 0001750 00000000030 12653727046 023215 0 ustar adrien adrien 0000000 0000000 - ! foo
- !<$:?> bar
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-8.19 0000664 0001750 0001750 00000000056 12653727046 023232 0 ustar adrien adrien 0000000 0000000 - sun: yellow
- ? earth: blue
: moon: white
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.8 0000664 0001750 0001750 00000000175 12653727046 023144 0 ustar adrien adrien 0000000 0000000 ---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
---
time: 20:03:47
player: Sammy Sosa
action: grand slam
...
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.11 0000664 0001750 0001750 00000000053 12653727046 023215 0 ustar adrien adrien 0000000 0000000 key: # Comment
# lines
value
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-9.4 0000664 0001750 0001750 00000000053 12653727046 023142 0 ustar adrien adrien 0000000 0000000 ---
{ matches
% : 20 }
...
---
# Empty
...
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-2.14 0000664 0001750 0001750 00000000077 12653727046 023222 0 ustar adrien adrien 0000000 0000000 --- >
Mark McGwire's
year was crippled
by a knee injury.
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-10.5 0000664 0001750 0001750 00000000110 12653727046 023205 0 ustar adrien adrien 0000000 0000000 YAML is a superset of JSON: !!bool true
Pluto is a planet: !!bool false
yamllint-1.2.1/tests/yaml-1.2-spec-examples/example-6.17 0000664 0001750 0001750 00000000034 12653727046 023222 0 ustar adrien adrien 0000000 0000000 %TAG ! !foo
%TAG ! !foo
bar
yamllint-1.2.1/tests/test_cli.py 0000664 0001750 0001750 00000021563 12675231644 017437 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
import os
import shutil
import tempfile
import unittest
import sys
from yamllint import cli
class CommandLineTestCase(unittest.TestCase):
def setUp(self):
self.wd = tempfile.mkdtemp(prefix='yamllint-tests-')
# .yaml file at root
with open(os.path.join(self.wd, 'a.yaml'), 'w') as f:
f.write('---\n'
'- 1 \n'
'- 2')
# .yml file at root
open(os.path.join(self.wd, 'empty.yml'), 'w').close()
# file in dir
os.mkdir(os.path.join(self.wd, 'sub'))
with open(os.path.join(self.wd, 'sub', 'ok.yaml'), 'w') as f:
f.write('---\n'
'key: value\n')
# file in very nested dir
dir = self.wd
for i in range(15):
dir = os.path.join(dir, 's')
os.mkdir(dir)
with open(os.path.join(dir, 'file.yaml'), 'w') as f:
f.write('---\n'
'key: value\n'
'key: other value\n')
# empty dir
os.mkdir(os.path.join(self.wd, 'empty-dir'))
# non-YAML file
with open(os.path.join(self.wd, 'no-yaml.json'), 'w') as f:
f.write('---\n'
'key: value\n')
def tearDown(self):
shutil.rmtree(self.wd)
def test_find_files_recursively(self):
self.assertEqual(
sorted(cli.find_files_recursively([self.wd])),
[os.path.join(self.wd, 'a.yaml'),
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, 'sub/ok.yaml')],
)
items = [os.path.join(self.wd, 'sub/ok.yaml'),
os.path.join(self.wd, 'empty-dir')]
self.assertEqual(
sorted(cli.find_files_recursively(items)),
[os.path.join(self.wd, 'sub/ok.yaml')],
)
items = [os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 's')]
self.assertEqual(
sorted(cli.find_files_recursively(items)),
[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')],
)
items = [os.path.join(self.wd, 'sub'),
os.path.join(self.wd, '/etc/another/file')]
self.assertEqual(
sorted(cli.find_files_recursively(items)),
[os.path.join(self.wd, '/etc/another/file'),
os.path.join(self.wd, 'sub/ok.yaml')],
)
def test_run_with_bad_arguments(self):
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(())
self.assertNotEqual(ctx.exception.code, 0)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertRegexpMatches(err, r'^usage')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('--unknown-arg', ))
self.assertNotEqual(ctx.exception.code, 0)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertRegexpMatches(err, r'^usage')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-c', './conf.yaml', '-d', 'relaxed', 'file'))
self.assertNotEqual(ctx.exception.code, 0)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertRegexpMatches(err, r'^Options --config-file and '
r'--config-data cannot be used')
def test_run_with_bad_config(self):
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-d', 'rules: {a: b}', 'file'))
self.assertEqual(ctx.exception.code, -1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertRegexpMatches(err, r'^invalid config: no such rule')
def test_run_with_empty_config(self):
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-d', '', 'file'))
self.assertEqual(ctx.exception.code, -1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertRegexpMatches(err, r'^invalid config: not a dict')
def test_run_version(self):
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('--version', ))
self.assertEqual(ctx.exception.code, 0)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertRegexpMatches(out + err, r'yamllint \d+\.\d+')
def test_run_non_existing_file(self):
file = os.path.join(self.wd, 'i-do-not-exist.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-f', 'parsable', file))
self.assertEqual(ctx.exception.code, -1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertRegexpMatches(err, r'No such file or directory')
def test_run_one_problem_file(self):
file = os.path.join(self.wd, 'a.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-f', 'parsable', file))
self.assertEqual(ctx.exception.code, 1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, (
'%s:2:4: [error] trailing spaces (trailing-spaces)\n'
'%s:3:4: [error] no new line character at the end of file '
'(new-line-at-end-of-file)\n') % (file, file))
self.assertEqual(err, '')
def test_run_one_ok_file(self):
file = os.path.join(self.wd, 'sub', 'ok.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-f', 'parsable', file))
self.assertEqual(ctx.exception.code, 0)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertEqual(err, '')
def test_run_empty_file(self):
file = os.path.join(self.wd, 'empty.yml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(('-f', 'parsable', file))
self.assertEqual(ctx.exception.code, 0)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, '')
self.assertEqual(err, '')
def test_run_multiple_files(self):
items = [os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 's')]
file = items[1] + '/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run(['-f', 'parsable'] + items)
self.assertEqual(ctx.exception.code, 1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, (
'%s:3:1: [error] duplication of key "key" in mapping '
'(key-duplicates)\n') % file)
self.assertEqual(err, '')
def test_run_colored_output(self):
file = os.path.join(self.wd, 'a.yaml')
sys.stdout, sys.stderr = StringIO(), StringIO()
with self.assertRaises(SystemExit) as ctx:
cli.run((file, ))
self.assertEqual(ctx.exception.code, 1)
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
self.assertEqual(out, (
'\033[4m%s\033[0m\n'
' \033[2m2:4\033[0m \033[31merror\033[0m '
'trailing spaces \033[2m(trailing-spaces)\033[0m\n'
' \033[2m3:4\033[0m \033[31merror\033[0m '
'no new line character at the end of file '
'\033[2m(new-line-at-end-of-file)\033[0m\n'
'\n' % file))
self.assertEqual(err, '')
yamllint-1.2.1/tests/test_parser.py 0000664 0001750 0001750 00000006750 12651202273 020153 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import unittest
import yaml
from yamllint.parser import (line_generator, token_generator,
token_or_line_generator, Line, Token)
class ParserTestCase(unittest.TestCase):
def test_line_generator(self):
e = list(line_generator(''))
self.assertEqual(len(e), 1)
self.assertEqual(e[0].line_no, 1)
self.assertEqual(e[0].start, 0)
self.assertEqual(e[0].end, 0)
e = list(line_generator('\n'))
self.assertEqual(len(e), 2)
e = list(line_generator(' \n'))
self.assertEqual(len(e), 2)
self.assertEqual(e[0].line_no, 1)
self.assertEqual(e[0].start, 0)
self.assertEqual(e[0].end, 1)
e = list(line_generator('\n\n'))
self.assertEqual(len(e), 3)
e = list(line_generator('---\n'
'this is line 1\n'
'line 2\n'
'\n'
'3\n'))
self.assertEqual(len(e), 6)
self.assertEqual(e[0].line_no, 1)
self.assertEqual(e[0].content, '---')
self.assertEqual(e[2].content, 'line 2')
self.assertEqual(e[3].content, '')
self.assertEqual(e[5].line_no, 6)
e = list(line_generator('test with\n'
'no newline\n'
'at the end'))
self.assertEqual(len(e), 3)
self.assertEqual(e[2].line_no, 3)
self.assertEqual(e[2].content, 'at the end')
def test_token_generator(self):
e = list(token_generator(''))
self.assertEqual(len(e), 2)
self.assertEqual(e[0].prev, None)
self.assertIsInstance(e[0].curr, yaml.Token)
self.assertIsInstance(e[0].next, yaml.Token)
self.assertEqual(e[1].prev, e[0].curr)
self.assertEqual(e[1].curr, e[0].next)
self.assertEqual(e[1].next, None)
e = list(token_generator('---\n'
'k: v\n'))
self.assertEqual(len(e), 9)
self.assertIsInstance(e[3].curr, yaml.KeyToken)
self.assertIsInstance(e[5].curr, yaml.ValueToken)
def test_token_or_line_generator(self):
e = list(token_or_line_generator('---\n'
'k: v\n'))
self.assertEqual(len(e), 12)
self.assertIsInstance(e[0], Token)
self.assertIsInstance(e[0].curr, yaml.StreamStartToken)
self.assertIsInstance(e[1], Token)
self.assertIsInstance(e[1].curr, yaml.DocumentStartToken)
self.assertIsInstance(e[2], Line)
self.assertIsInstance(e[3].curr, yaml.BlockMappingStartToken)
self.assertIsInstance(e[4].curr, yaml.KeyToken)
self.assertIsInstance(e[6].curr, yaml.ValueToken)
self.assertIsInstance(e[8], Line)
self.assertIsInstance(e[11], Line)
yamllint-1.2.1/tests/test_syntax_errors.py 0000664 0001750 0001750 00000006075 12653727046 021615 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from tests.common import RuleTestCase
class YamlLintTestCase(RuleTestCase):
rule_id = None # syntax error
def test_syntax_errors(self):
self.check('---\n'
'this is not: valid: YAML\n', None, problem=(2, 19))
self.check('---\n'
'this is: valid YAML\n'
'\n'
'this is an error: [\n'
'\n'
'...\n', None, problem=(6, 1))
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'
': - value 1\n'
' - value 2\n'
'...\n', None)
self.check('---\n'
'?\n'
' key\n'
': {a: 1}\n'
'...\n', None)
self.check('---\n'
'?\n'
' key\n'
':\n'
' val\n'
'...\n', None)
def test_mapping_between_sequences(self):
# This is valid YAML. See http://www.yaml.org/spec/1.2/spec.html,
# example 2.11
self.check('---\n'
'? - Detroit Tigers\n'
' - Chicago cubs\n'
':\n'
' - 2001-07-23\n'
'\n'
'? [New York Yankees,\n'
' 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)
yamllint-1.2.1/yamllint/ 0000775 0001750 0001750 00000000000 12675233100 015724 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/yamllint/conf/ 0000775 0001750 0001750 00000000000 12675233100 016651 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/yamllint/conf/default.yaml 0000664 0001750 0001750 00000001530 12670240422 021160 0 ustar adrien adrien 0000000 0000000 ---
rules:
braces:
min-spaces-inside: 0
max-spaces-inside: 0
brackets:
min-spaces-inside: 0
max-spaces-inside: 0
colons:
max-spaces-before: 0
max-spaces-after: 1
commas:
max-spaces-before: 0
min-spaces-after: 1
max-spaces-after: 1
comments:
level: warning
require-starting-space: yes
min-spaces-from-content: 2
comments-indentation:
level: warning
document-end: disable
document-start:
level: warning
present: yes
empty-lines:
max: 2
max-start: 0
max-end: 0
hyphens:
max-spaces-after: 1
indentation:
spaces: consistent
indent-sequences: yes
check-multi-line-strings: no
key-duplicates: enable
line-length:
max: 80
allow-non-breakable-words: yes
new-line-at-end-of-file: enable
new-lines:
type: unix
trailing-spaces: enable
yamllint-1.2.1/yamllint/conf/relaxed.yaml 0000664 0001750 0001750 00000000671 12670240422 021165 0 ustar adrien adrien 0000000 0000000 ---
extends: default
rules:
braces:
level: warning
max-spaces-inside: 1
brackets:
level: warning
max-spaces-inside: 1
colons:
level: warning
commas:
level: warning
comments: disable
comments-indentation: disable
document-start: disable
empty-lines:
level: warning
hyphens:
level: warning
indentation:
level: warning
indent-sequences: consistent
line-length:
level: warning
yamllint-1.2.1/yamllint/rules/ 0000775 0001750 0001750 00000000000 12675233100 017056 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/yamllint/rules/comments_indentation.py 0000664 0001750 0001750 00000005457 12655326364 023701 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to force comments to be indented like content.
.. rubric:: Examples
#. With ``comments-indentation: {}``
the following code snippet would **PASS**:
::
# Fibonacci
[0, 1, 1, 2, 3, 5]
the following code snippet would **FAIL**:
::
# Fibonacci
[0, 1, 1, 2, 3, 5]
the following code snippet would **PASS**:
::
list:
- 2
- 3
# - 4
- 5
the following code snippet would **FAIL**:
::
list:
- 2
- 3
# - 4
- 5
the following code snippet would **PASS**:
::
# This is the first object
obj1:
- item A
# - item B
# This is the second object
obj2: []
the following code snippet would **PASS**:
::
# This sentence
# is a block comment
the following code snippet would **FAIL**:
::
# This sentence
# is a block comment
"""
import yaml
from yamllint.linter import LintProblem
from yamllint.rules.common import get_line_indent, get_comments_between_tokens
ID = 'comments-indentation'
TYPE = 'token'
# Case A:
#
# prev: line:
# # commented line
# current: line
#
# Case B:
#
# prev: line
# # commented line 1
# # commented line 2
# current: line
def check(conf, token, prev, next, nextnext, context):
if prev is None:
return
curr_line_indent = token.start_mark.column
if isinstance(token, yaml.StreamEndToken):
curr_line_indent = 0
skip_first_line = True
if isinstance(prev, yaml.StreamStartToken):
skip_first_line = False
prev_line_indent = 0
else:
prev_line_indent = get_line_indent(prev)
if prev_line_indent <= curr_line_indent:
prev_line_indent = -1 # disable it
for comment in get_comments_between_tokens(
prev, token, skip_first_line=skip_first_line):
if comment.column - 1 == curr_line_indent:
prev_line_indent = -1 # disable it
elif comment.column - 1 != prev_line_indent:
yield LintProblem(comment.line, comment.column,
'comment not indented like content')
yamllint-1.2.1/yamllint/rules/new_lines.py 0000664 0001750 0001750 00000003042 12654457254 021431 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to force the type of new line characters.
.. rubric:: Options
* Set ``type`` to ``unix`` to use UNIX-typed new line characters (``\\n``), or
``dos`` to use DOS-typed new line characters (``\\r\\n``).
"""
from yamllint.linter import LintProblem
ID = 'new-lines'
TYPE = 'line'
CONF = {'type': ('unix', 'dos')}
def check(conf, line):
if line.start == 0 and len(line.buffer) > line.end:
if conf['type'] == 'dos':
if line.buffer[line.end - 1:line.end + 1] != '\r\n':
yield LintProblem(1, line.end - line.start + 1,
'wrong new line character: expected \\r\\n')
else:
if line.end > 0 and line.buffer[line.end - 1] == '\r':
yield LintProblem(1, line.end - line.start,
'wrong new line character: expected \\n')
yamllint-1.2.1/yamllint/rules/braces.py 0000664 0001750 0001750 00000005451 12655326364 020711 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the number of spaces inside braces (``{`` and ``}``).
.. rubric:: Options
* ``min-spaces-inside`` defines the minimal number of spaces required inside
braces.
* ``max-spaces-inside`` defines the maximal number of spaces allowed inside
braces.
.. rubric:: Examples
#. With ``braces: {min-spaces-inside: 0, max-spaces-inside: 0}``
the following code snippet would **PASS**:
::
object: {key1: 4, key2: 8}
the following code snippet would **FAIL**:
::
object: { key1: 4, key2: 8 }
#. With ``braces: {min-spaces-inside: 1, max-spaces-inside: 3}``
the following code snippet would **PASS**:
::
object: { key1: 4, key2: 8 }
the following code snippet would **PASS**:
::
object: { key1: 4, key2: 8 }
the following code snippet would **FAIL**:
::
object: { key1: 4, key2: 8 }
the following code snippet would **FAIL**:
::
object: {key1: 4, key2: 8 }
"""
import yaml
from yamllint.rules.common import spaces_after, spaces_before
ID = 'braces'
TYPE = 'token'
CONF = {'min-spaces-inside': int,
'max-spaces-inside': int}
def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.FlowMappingStartToken):
problem = spaces_after(token, prev, next,
min=conf['min-spaces-inside'],
max=conf['max-spaces-inside'],
min_desc='too few spaces inside braces',
max_desc='too many spaces inside braces')
if problem is not None:
yield problem
elif (isinstance(token, yaml.FlowMappingEndToken) and
(prev is None or
not isinstance(prev, yaml.FlowMappingStartToken))):
problem = spaces_before(token, prev, next,
min=conf['min-spaces-inside'],
max=conf['max-spaces-inside'],
min_desc='too few spaces inside braces',
max_desc='too many spaces inside braces')
if problem is not None:
yield problem
yamllint-1.2.1/yamllint/rules/__init__.py 0000664 0001750 0001750 00000003207 12654457254 021210 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from yamllint.rules import (
braces,
brackets,
colons,
commas,
comments,
comments_indentation,
document_end,
document_start,
empty_lines,
hyphens,
indentation,
key_duplicates,
line_length,
new_line_at_end_of_file,
new_lines,
trailing_spaces,
)
_RULES = {
braces.ID: braces,
brackets.ID: brackets,
colons.ID: colons,
commas.ID: commas,
comments.ID: comments,
comments_indentation.ID: comments_indentation,
document_end.ID: document_end,
document_start.ID: document_start,
empty_lines.ID: empty_lines,
hyphens.ID: hyphens,
indentation.ID: indentation,
key_duplicates.ID: key_duplicates,
line_length.ID: line_length,
new_line_at_end_of_file.ID: new_line_at_end_of_file,
new_lines.ID: new_lines,
trailing_spaces.ID: trailing_spaces,
}
def get(id):
if id not in _RULES:
raise ValueError('no such rule: "%s"' % id)
return _RULES[id]
yamllint-1.2.1/yamllint/rules/common.py 0000664 0001750 0001750 00000011337 12654457254 020744 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import string
import yaml
from yamllint.linter import LintProblem
def spaces_after(token, prev, next, min=-1, max=-1,
min_desc=None, max_desc=None):
if next is not None and token.end_mark.line == next.start_mark.line:
spaces = next.start_mark.pointer - token.end_mark.pointer
if max != - 1 and spaces > max:
return LintProblem(token.start_mark.line + 1,
next.start_mark.column, max_desc)
elif min != - 1 and spaces < min:
return LintProblem(token.start_mark.line + 1,
next.start_mark.column + 1, min_desc)
def spaces_before(token, prev, next, min=-1, max=-1,
min_desc=None, max_desc=None):
if (prev is not None and prev.end_mark.line == token.start_mark.line and
# Discard tokens (only scalars?) that end at the start of next line
(prev.end_mark.pointer == 0 or
prev.end_mark.buffer[prev.end_mark.pointer - 1] != '\n')):
spaces = token.start_mark.pointer - prev.end_mark.pointer
if max != - 1 and spaces > max:
return LintProblem(token.start_mark.line + 1,
token.start_mark.column, max_desc)
elif min != - 1 and spaces < min:
return LintProblem(token.start_mark.line + 1,
token.start_mark.column + 1, min_desc)
class Comment(object):
def __init__(self, line, column, buffer, pointer):
self.line = line
self.column = column
self.buffer = buffer
self.pointer = pointer
def __repr__(self):
end = self.buffer.find('\n', self.pointer)
if end == -1:
end = self.buffer.find('\0', self.pointer)
if end != -1:
return self.buffer[self.pointer:end]
return self.buffer[self.pointer:]
def __eq__(self, other):
return (self.line == other.line and
self.column == other.column and
str(self) == str(other))
def get_line_indent(token):
"""Finds the indent of the line the token starts in."""
start = token.start_mark.buffer.rfind('\n', 0,
token.start_mark.pointer) + 1
content = start
while token.start_mark.buffer[content] == ' ':
content += 1
return content - start
def get_real_end_line(token):
"""Finds the line on which the token really ends.
With pyyaml, scalar tokens often end on a next line.
"""
end_line = token.end_mark.line + 1
if not isinstance(token, yaml.ScalarToken):
return end_line
pos = token.end_mark.pointer - 1
while (pos >= token.start_mark.pointer - 1 and
token.end_mark.buffer[pos] in string.whitespace):
if token.end_mark.buffer[pos] == '\n':
end_line -= 1
pos -= 1
return end_line
def get_comments_between_tokens(token1, token2, skip_first_line=False):
if token2 is None:
buf = token1.end_mark.buffer[token1.end_mark.pointer:]
elif (token1.end_mark.line == token2.start_mark.line and
not isinstance(token1, yaml.StreamStartToken) and
not isinstance(token2, yaml.StreamEndToken)):
return
else:
buf = token1.end_mark.buffer[token1.end_mark.pointer:
token2.start_mark.pointer]
line_no = token1.end_mark.line + 1
column_no = token1.end_mark.column + 1
pointer = token1.end_mark.pointer
for line in buf.split('\n'):
if skip_first_line:
skip_first_line = False
else:
pos = line.find('#')
if pos != -1:
yield Comment(line_no, column_no + pos,
token1.end_mark.buffer, pointer + pos)
pointer += len(line) + 1
line_no += 1
column_no = 1
def is_explicit_key(token):
# explicit key:
# ? key
# : v
# or
# ?
# key
# : v
return (token.start_mark.pointer < token.end_mark.pointer and
token.start_mark.buffer[token.start_mark.pointer] == '?')
yamllint-1.2.1/yamllint/rules/trailing_spaces.py 0000664 0001750 0001750 00000003142 12654457254 022616 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to forbid trailing spaces at the end of lines.
.. rubric:: Examples
#. With ``trailing-spaces: {}``
the following code snippet would **PASS**:
::
this document doesn't contain
any trailing
spaces
the following code snippet would **FAIL**:
::
this document contains """ """
trailing spaces
on lines 1 and 3 """ """
"""
import string
from yamllint.linter import LintProblem
ID = 'trailing-spaces'
TYPE = 'line'
def check(conf, line):
if line.end == 0:
return
# YAML recognizes two white space characters: space and tab.
# http://yaml.org/spec/1.2/spec.html#id2775170
pos = line.end
while line.buffer[pos - 1] in string.whitespace and pos > line.start:
pos -= 1
if pos != line.end and line.buffer[pos] in ' \t':
yield LintProblem(line.line_no, pos - line.start + 1,
'trailing spaces')
yamllint-1.2.1/yamllint/rules/document_start.py 0000664 0001750 0001750 00000004541 12655326364 022504 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to require or forbid the use of document start marker (``---``).
.. rubric:: Options
* Set ``present`` to ``yes`` when the document start marker is required, or to
``no`` when it is forbidden.
.. rubric:: Examples
#. With ``document-start: {present: yes}``
the following code snippet would **PASS**:
::
---
this:
is: [a, document]
---
- this
- is: another one
the following code snippet would **FAIL**:
::
this:
is: [a, document]
---
- this
- is: another one
#. With ``document-start: {present: no}``
the following code snippet would **PASS**:
::
this:
is: [a, document]
...
the following code snippet would **FAIL**:
::
---
this:
is: [a, document]
...
"""
import yaml
from yamllint.linter import LintProblem
ID = 'document-start'
TYPE = 'token'
CONF = {'present': bool}
def check(conf, token, prev, next, nextnext, context):
if conf['present']:
if (isinstance(prev, (yaml.StreamStartToken,
yaml.DocumentEndToken,
yaml.DirectiveToken)) and
not isinstance(token, (yaml.DocumentStartToken,
yaml.DirectiveToken,
yaml.StreamEndToken))):
yield LintProblem(token.start_mark.line + 1, 1,
'missing document start "---"')
else:
if isinstance(token, yaml.DocumentStartToken):
yield LintProblem(token.start_mark.line + 1,
token.start_mark.column + 1,
'found forbidden document start "---"')
yamllint-1.2.1/yamllint/rules/new_line_at_end_of_file.py 0000664 0001750 0001750 00000002515 12654457254 024247 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to require a new line character (``\\n``) at the end of files.
The POSIX standard `requires the last line to end with a new line character
`_.
All UNIX tools expect a new line at the end of files. Most text editors use
this convention too.
"""
from yamllint.linter import LintProblem
ID = 'new-line-at-end-of-file'
TYPE = 'line'
def check(conf, line):
if line.end == len(line.buffer) and line.end > line.start:
yield LintProblem(line.line_no, line.end - line.start + 1,
'no new line character at the end of file')
yamllint-1.2.1/yamllint/rules/empty_lines.py 0000664 0001750 0001750 00000005367 12654457254 022012 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to set a maximal number of allowed consecutive blank lines.
.. rubric:: Options
* ``max`` defines the maximal number of empty lines allowed in the document.
* ``max-start`` defines the maximal number of empty lines allowed at the
beginning of the file. This option takes precedence over ``max``.
* ``max-end`` defines the maximal number of empty lines allowed at the end of
the file. This option takes precedence over ``max``.
.. rubric:: Examples
#. With ``empty-lines: {max: 1}``
the following code snippet would **PASS**:
::
- foo:
- 1
- 2
- bar: [3, 4]
the following code snippet would **FAIL**:
::
- foo:
- 1
- 2
- bar: [3, 4]
"""
from yamllint.linter import LintProblem
ID = 'empty-lines'
TYPE = 'line'
CONF = {'max': int,
'max-start': int,
'max-end': int}
def check(conf, line):
if line.start == line.end and line.end < len(line.buffer):
# Only alert on the last blank line of a serie
if (line.end < len(line.buffer) - 1 and
line.buffer[line.end + 1] == '\n'):
return
blank_lines = 0
while (line.start > blank_lines and
line.buffer[line.start - blank_lines - 1] == '\n'):
blank_lines += 1
max = conf['max']
# Special case: start of document
if line.start - blank_lines == 0:
blank_lines += 1 # first line doesn't have a preceding \n
max = conf['max-start']
# Special case: end of document
# NOTE: The last line of a file is always supposed to end with a new
# line. See POSIX definition of a line at:
if line.end == len(line.buffer) - 1 and line.buffer[line.end] == '\n':
# Allow the exception of the one-byte file containing '\n'
if line.end == 0:
return
max = conf['max-end']
if blank_lines > max:
yield LintProblem(line.line_no, 1, 'too many blank lines (%d > %d)'
% (blank_lines, max))
yamllint-1.2.1/yamllint/rules/hyphens.py 0000664 0001750 0001750 00000003644 12655326364 021132 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the number of spaces after hyphens (``-``).
.. rubric:: Options
* ``max-spaces-after`` defines the maximal number of spaces allowed after
hyphens.
.. rubric:: Examples
#. With ``hyphens: {max-spaces-after: 1}``
the following code snippet would **PASS**:
::
- first list:
- a
- b
- - 1
- 2
- 3
the following code snippet would **FAIL**:
::
- first list:
- a
- b
the following code snippet would **FAIL**:
::
- - 1
- 2
- 3
#. With ``hyphens: {max-spaces-after: 3}``
the following code snippet would **PASS**:
::
- key
- key2
- key42
the following code snippet would **FAIL**:
::
- key
- key2
- key42
"""
import yaml
from yamllint.rules.common import spaces_after
ID = 'hyphens'
TYPE = 'token'
CONF = {'max-spaces-after': int}
def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.BlockEntryToken):
problem = spaces_after(token, prev, next,
max=conf['max-spaces-after'],
max_desc='too many spaces after hyphen')
if problem is not None:
yield problem
yamllint-1.2.1/yamllint/rules/key_duplicates.py 0000664 0001750 0001750 00000005330 12655326364 022453 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to prevent multiple entries with the same key in mappings.
.. rubric:: Examples
#. With ``key-duplicates: {}``
the following code snippet would **PASS**:
::
- key 1: v
key 2: val
key 3: value
- {a: 1, b: 2, c: 3}
the following code snippet would **FAIL**:
::
- key 1: v
key 2: val
key 1: value
the following code snippet would **FAIL**:
::
- {a: 1, b: 2, b: 3}
the following code snippet would **FAIL**:
::
duplicated key: 1
"duplicated key": 2
other duplication: 1
? >-
other
duplication
: 2
"""
import yaml
from yamllint.linter import LintProblem
ID = 'key-duplicates'
TYPE = 'token'
CONF = {}
MAP, SEQ = range(2)
class Parent(object):
def __init__(self, type):
self.type = type
self.keys = []
def check(conf, token, prev, next, nextnext, context):
if 'stack' not in context:
context['stack'] = []
if isinstance(token, (yaml.BlockMappingStartToken,
yaml.FlowMappingStartToken)):
context['stack'].append(Parent(MAP))
elif isinstance(token, (yaml.BlockSequenceStartToken,
yaml.FlowSequenceStartToken)):
context['stack'].append(Parent(SEQ))
elif isinstance(token, (yaml.BlockEndToken,
yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken)):
context['stack'].pop()
elif (isinstance(token, yaml.KeyToken) and
isinstance(next, yaml.ScalarToken)):
# This check is done because KeyTokens can be found inside flow
# sequences... strange, but allowed.
if len(context['stack']) > 0 and context['stack'][-1].type == MAP:
if next.value in context['stack'][-1].keys:
yield LintProblem(
next.start_mark.line + 1, next.start_mark.column + 1,
'duplication of key "%s" in mapping' % next.value)
else:
context['stack'][-1].keys.append(next.value)
yamllint-1.2.1/yamllint/rules/line_length.py 0000664 0001750 0001750 00000005710 12654457254 021742 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to set a limit to lines length.
.. rubric:: Options
* ``max`` defines the maximal (inclusive) length of lines.
* ``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
instance. Use ``yes`` to allow, ``no`` to forbid.
.. rubric:: Examples
#. With ``line-length: {max: 70}``
the following code snippet would **PASS**:
::
long sentence:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
the following code snippet would **FAIL**:
::
long sentence:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
#. With ``line-length: {max: 60, allow-non-breakable-words: yes}``
the following code snippet would **PASS**:
::
this:
is:
- a:
http://localhost/very/very/very/very/very/very/very/very/long/url
# this comment is too long,
# but hard to split:
# http://localhost/another/very/very/very/very/very/very/very/very/long/url
the following code snippet would **FAIL**:
::
- this line is waaaaaaaaaaaaaay too long but could be easily splitted...
#. With ``line-length: {max: 60, allow-non-breakable-words: no}``
the following code snippet would **FAIL**:
::
this:
is:
- a:
http://localhost/very/very/very/very/very/very/very/very/long/url
"""
from yamllint.linter import LintProblem
ID = 'line-length'
TYPE = 'line'
CONF = {'max': int,
'allow-non-breakable-words': bool}
def check(conf, line):
if line.end - line.start > conf['max']:
if conf['allow-non-breakable-words']:
start = line.start
while start < line.end and line.buffer[start] == ' ':
start += 1
if start != line.end:
if line.buffer[start] == '#':
start += 2
if line.buffer.find(' ', start, line.end) == -1:
return
yield LintProblem(line.line_no, conf['max'] + 1,
'line too long (%d > %d characters)' %
(line.end - line.start, conf['max']))
yamllint-1.2.1/yamllint/rules/commas.py 0000664 0001750 0001750 00000007062 12655326364 020731 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the number of spaces before and after commas (``,``).
.. rubric:: Options
* ``max-spaces-before`` defines the maximal number of spaces allowed before
commas (use ``-1`` to disable).
* ``min-spaces-after`` defines the minimal number of spaces required after
commas.
* ``max-spaces-after`` defines the maximal number of spaces allowed after
commas (use ``-1`` to disable).
.. rubric:: Examples
#. With ``commas: {max-spaces-before: 0}``
the following code snippet would **PASS**:
::
strange var:
[10, 20, 30, {x: 1, y: 2}]
the following code snippet would **FAIL**:
::
strange var:
[10, 20 , 30, {x: 1, y: 2}]
#. With ``commas: {max-spaces-before: 2}``
the following code snippet would **PASS**:
::
strange var:
[10 , 20 , 30, {x: 1 , y: 2}]
#. With ``commas: {max-spaces-before: -1}``
the following code snippet would **PASS**:
::
strange var:
[10,
20 , 30
, {x: 1, y: 2}]
#. With ``commas: {min-spaces-after: 1, max-spaces-after: 1}``
the following code snippet would **PASS**:
::
strange var:
[10, 20,30, {x: 1, y: 2}]
the following code snippet would **FAIL**:
::
strange var:
[10, 20,30, {x: 1, y: 2}]
#. With ``commas: {min-spaces-after: 1, max-spaces-after: 3}``
the following code snippet would **PASS**:
::
strange var:
[10, 20, 30, {x: 1, y: 2}]
#. With ``commas: {min-spaces-after: 0, max-spaces-after: 1}``
the following code snippet would **PASS**:
::
strange var:
[10, 20,30, {x: 1, y: 2}]
"""
import yaml
from yamllint.linter import LintProblem
from yamllint.rules.common import spaces_after, spaces_before
ID = 'commas'
TYPE = 'token'
CONF = {'max-spaces-before': int,
'min-spaces-after': int,
'max-spaces-after': int}
def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.FlowEntryToken):
if (prev is not None and conf['max-spaces-before'] != -1 and
prev.end_mark.line < token.start_mark.line):
yield LintProblem(token.start_mark.line + 1,
max(1, token.start_mark.column),
'too many spaces before comma')
else:
problem = spaces_before(token, prev, next,
max=conf['max-spaces-before'],
max_desc='too many spaces before comma')
if problem is not None:
yield problem
problem = spaces_after(token, prev, next,
min=conf['min-spaces-after'],
max=conf['max-spaces-after'],
min_desc='too few spaces after comma',
max_desc='too many spaces after comma')
if problem is not None:
yield problem
yamllint-1.2.1/yamllint/rules/indentation.py 0000664 0001750 0001750 00000043166 12675231644 021771 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the indentation.
.. rubric:: Options
* ``spaces`` defines the indentation width, in spaces. Set either to an integer
(e.g. ``2`` or ``4``, representing the number of spaces in an indentation
level) or to ``consistent`` to allow any number, as long as it remains the
same within the file.
* ``indent-sequences`` defines whether block sequences should be indented or
not (when in a mapping, this indentation is not mandatory -- some people
perceive the ``-`` as part of the indentation). Possible values: ``yes``,
``no``, ``whatever`` and ``consistent``. ``consistent`` requires either all
block sequences to be indented, or none to be. ``whatever`` means either
indenting or not indenting individual block sequences is OK.
* ``check-multi-line-strings`` defines whether to lint indentation in
multi-line strings. Set to ``yes`` to enable, ``no`` to disable.
.. rubric:: Examples
#. With ``indentation: {spaces: 1}``
the following code snippet would **PASS**:
::
history:
- name: Unix
date: 1969
- name: Linux
date: 1991
nest:
recurse:
- haystack:
needle
#. With ``indentation: {spaces: 4}``
the following code snippet would **PASS**:
::
history:
- name: Unix
date: 1969
- name: Linux
date: 1991
nest:
recurse:
- haystack:
needle
the following code snippet would **FAIL**:
::
history:
- name: Unix
date: 1969
- name: Linux
date: 1991
nest:
recurse:
- haystack:
needle
#. With ``indentation: {spaces: consistent}``
the following code snippet would **PASS**:
::
history:
- name: Unix
date: 1969
- name: Linux
date: 1991
nest:
recurse:
- haystack:
needle
the following code snippet would **FAIL**:
::
some:
Russian:
dolls
#. With ``indentation: {spaces: 2, indent-sequences: no}``
the following code snippet would **PASS**:
::
list:
- flying
- spaghetti
- monster
the following code snippet would **FAIL**:
::
list:
- flying
- spaghetti
- monster
#. With ``indentation: {spaces: 2, indent-sequences: whatever}``
the following code snippet would **PASS**:
::
list:
- flying:
- spaghetti
- monster
- not flying:
- spaghetti
- sauce
#. With ``indentation: {spaces: 2, indent-sequences: consistent}``
the following code snippet would **PASS**:
::
- flying:
- spaghetti
- monster
- not flying:
- spaghetti
- sauce
the following code snippet would **FAIL**:
::
- flying:
- spaghetti
- monster
- not flying:
- spaghetti
- sauce
#. With ``indentation: {spaces: 4, check-multi-line-strings: yes}``
the following code snippet would **PASS**:
::
Blaise Pascal:
Je vous écris une longue lettre parce que
je n'ai pas le temps d'en écrire une courte.
the following code snippet would **PASS**:
::
Blaise Pascal: Je vous écris une longue lettre parce que
je n'ai pas le temps d'en écrire une courte.
the following code snippet would **FAIL**:
::
Blaise Pascal: Je vous écris une longue lettre parce que
je n'ai pas le temps d'en écrire une courte.
the following code snippet would **FAIL**:
::
C code:
void main() {
printf("foo");
}
the following code snippet would **PASS**:
::
C code:
void main() {
printf("bar");
}
"""
import yaml
from yamllint.linter import LintProblem
from yamllint.rules.common import is_explicit_key, get_real_end_line
ID = 'indentation'
TYPE = 'token'
CONF = {'spaces': (int, 'consistent'),
'indent-sequences': (bool, 'whatever', 'consistent'),
'check-multi-line-strings': bool}
ROOT, B_MAP, F_MAP, B_SEQ, F_SEQ, B_ENT, KEY, VAL = range(8)
labels = ('ROOT', 'B_MAP', 'F_MAP', 'B_SEQ', 'F_SEQ', 'B_ENT', 'KEY', 'VAL')
class Parent(object):
def __init__(self, type, indent, line_indent=None):
self.type = type
self.indent = indent
self.line_indent = line_indent
self.explicit_key = False
self.implicit_block_seq = False
def __repr__(self):
return '%s:%d' % (labels[self.type], self.indent)
def check_scalar_indentation(conf, token, context):
if token.start_mark.line == token.end_mark.line:
return
def compute_expected_indent(found_indent):
def detect_indent(base_indent):
if type(context['spaces']) is not int:
context['spaces'] = found_indent - base_indent
return base_indent + context['spaces']
if token.plain:
return token.start_mark.column
elif token.style in ('"', "'"):
return token.start_mark.column + 1
elif token.style in ('>', '|'):
if context['stack'][-1].type == B_ENT:
# - >
# multi
# line
return detect_indent(token.start_mark.column)
elif context['stack'][-1].type == KEY:
assert context['stack'][-1].explicit_key
# - ? >
# multi-line
# key
# : >
# multi-line
# value
return detect_indent(token.start_mark.column)
elif context['stack'][-1].type == VAL:
if token.start_mark.line + 1 > context['cur_line']:
# - key:
# >
# multi
# line
return detect_indent(context['stack'][-1].indent)
elif context['stack'][-2].explicit_key:
# - ? key
# : >
# multi-line
# value
return detect_indent(token.start_mark.column)
else:
# - key: >
# multi
# line
return detect_indent(context['stack'][-2].indent)
else:
return detect_indent(context['stack'][-1].indent)
expected_indent = None
line_no = token.start_mark.line + 1
line_start = token.start_mark.pointer
while True:
line_start = token.start_mark.buffer.find(
'\n', line_start, token.end_mark.pointer - 1) + 1
if line_start == 0:
break
line_no += 1
indent = 0
while token.start_mark.buffer[line_start + indent] == ' ':
indent += 1
if token.start_mark.buffer[line_start + indent] == '\n':
continue
if expected_indent is None:
expected_indent = compute_expected_indent(indent)
if indent != expected_indent:
yield LintProblem(line_no, indent + 1,
'wrong indentation: expected %d but found %d' %
(expected_indent, indent))
def _check(conf, token, prev, next, nextnext, context):
if 'stack' not in context:
context['stack'] = [Parent(ROOT, 0)]
context['cur_line'] = -1
context['spaces'] = conf['spaces']
context['indent-sequences'] = conf['indent-sequences']
# Step 1: Lint
is_visible = (
not isinstance(token, (yaml.StreamStartToken, yaml.StreamEndToken)) and
not isinstance(token, yaml.BlockEndToken) and
not (isinstance(token, yaml.ScalarToken) and token.value == ''))
first_in_line = (is_visible and
token.start_mark.line + 1 > context['cur_line'])
def detect_indent(base_indent, next):
if type(context['spaces']) is not int:
context['spaces'] = next.start_mark.column - base_indent
return base_indent + context['spaces']
if first_in_line:
found_indentation = token.start_mark.column
expected = context['stack'][-1].indent
if isinstance(token, (yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken)):
expected = context['stack'][-1].line_indent
elif (context['stack'][-1].type == KEY and
context['stack'][-1].explicit_key and
not isinstance(token, yaml.ValueToken)):
expected = detect_indent(expected, token)
if found_indentation != expected:
yield LintProblem(token.start_mark.line + 1, found_indentation + 1,
'wrong indentation: expected %d but found %d' %
(expected, found_indentation))
if (isinstance(token, yaml.ScalarToken) and
conf['check-multi-line-strings']):
for problem in check_scalar_indentation(conf, token, context):
yield problem
# Step 2.a:
if is_visible:
context['cur_line'] = get_real_end_line(token)
if first_in_line:
context['cur_line_indent'] = found_indentation
# Step 2.b: Update state
if isinstance(token, yaml.BlockMappingStartToken):
# - a: 1
# or
# - ? a
# : 1
# or
# - ?
# a
# : 1
assert isinstance(next, yaml.KeyToken)
assert next.start_mark.line == token.start_mark.line
indent = token.start_mark.column
context['stack'].append(Parent(B_MAP, indent))
elif isinstance(token, yaml.FlowMappingStartToken):
if next.start_mark.line == token.start_mark.line:
# - {a: 1, b: 2}
indent = next.start_mark.column
else:
# - {
# a: 1, b: 2
# }
indent = detect_indent(context['cur_line_indent'], next)
context['stack'].append(Parent(F_MAP, indent,
line_indent=context['cur_line_indent']))
elif isinstance(token, yaml.BlockSequenceStartToken):
# - - a
# - b
assert isinstance(next, yaml.BlockEntryToken)
assert next.start_mark.line == token.start_mark.line
indent = token.start_mark.column
context['stack'].append(Parent(B_SEQ, indent))
elif (isinstance(token, yaml.BlockEntryToken) and
# in case of an empty entry
not isinstance(next, (yaml.BlockEntryToken, yaml.BlockEndToken))):
# It looks like pyyaml doesn't issue BlockSequenceStartTokens when the
# list is not indented. We need to compensate that.
if context['stack'][-1].type != B_SEQ:
context['stack'].append(Parent(B_SEQ, token.start_mark.column))
context['stack'][-1].implicit_block_seq = True
if next.start_mark.line == token.end_mark.line:
# - item 1
# - item 2
indent = next.start_mark.column
else:
# -
# item 1
# -
# key:
# value
indent = detect_indent(token.start_mark.column, next)
context['stack'].append(Parent(B_ENT, indent))
elif isinstance(token, yaml.FlowSequenceStartToken):
if next.start_mark.line == token.start_mark.line:
# - [a, b]
indent = next.start_mark.column
else:
# - [
# a, b
# ]
indent = detect_indent(context['cur_line_indent'], next)
context['stack'].append(Parent(F_SEQ, indent,
line_indent=context['cur_line_indent']))
elif isinstance(token, yaml.KeyToken):
indent = context['stack'][-1].indent
context['stack'].append(Parent(KEY, indent))
context['stack'][-1].explicit_key = is_explicit_key(token)
elif isinstance(token, yaml.ValueToken):
assert context['stack'][-1].type == KEY
# Special cases:
# key: &anchor
# value
# and:
# key: !!tag
# value
if isinstance(next, (yaml.AnchorToken, yaml.TagToken)):
if (next.start_mark.line == prev.start_mark.line and
next.start_mark.line < nextnext.start_mark.line):
next = nextnext
# Only if value is not empty
if not isinstance(next, (yaml.BlockEndToken,
yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken,
yaml.KeyToken)):
if context['stack'][-1].explicit_key:
# ? k
# : value
# or
# ? k
# :
# value
indent = detect_indent(context['stack'][-1].indent, next)
elif next.start_mark.line == prev.start_mark.line:
# k: value
indent = next.start_mark.column
elif isinstance(next, (yaml.BlockSequenceStartToken,
yaml.BlockEntryToken)):
# NOTE: We add BlockEntryToken in the test above because
# sometimes BlockSequenceStartToken are not issued. Try
# yaml.scan()ning this:
# '- lib:\n'
# ' - var\n'
if context['indent-sequences'] is False:
indent = context['stack'][-1].indent
elif context['indent-sequences'] is True:
indent = detect_indent(context['stack'][-1].indent, next)
else: # 'whatever' or 'consistent'
if next.start_mark.column == context['stack'][-1].indent:
# key:
# - e1
# - e2
if context['indent-sequences'] == 'consistent':
context['indent-sequences'] = False
indent = context['stack'][-1].indent
else:
if context['indent-sequences'] == 'consistent':
context['indent-sequences'] = True
# key:
# - e1
# - e2
indent = detect_indent(context['stack'][-1].indent,
next)
else:
# k:
# value
indent = detect_indent(context['stack'][-1].indent, next)
context['stack'].append(Parent(VAL, indent))
consumed_current_token = False
while True:
if (context['stack'][-1].type == F_SEQ and
isinstance(token, yaml.FlowSequenceEndToken) and
not consumed_current_token):
context['stack'].pop()
consumed_current_token = True
elif (context['stack'][-1].type == F_MAP and
isinstance(token, yaml.FlowMappingEndToken) and
not consumed_current_token):
context['stack'].pop()
consumed_current_token = True
elif (context['stack'][-1].type in (B_MAP, B_SEQ) and
isinstance(token, yaml.BlockEndToken) and
not context['stack'][-1].implicit_block_seq and
not consumed_current_token):
context['stack'].pop()
consumed_current_token = True
elif (context['stack'][-1].type == B_ENT and
not isinstance(token, yaml.BlockEntryToken) and
context['stack'][-2].implicit_block_seq and
not isinstance(token, (yaml.AnchorToken, yaml.TagToken)) and
not isinstance(next, yaml.BlockEntryToken)):
context['stack'].pop()
context['stack'].pop()
elif (context['stack'][-1].type == B_ENT and
isinstance(next, (yaml.BlockEntryToken, yaml.BlockEndToken))):
context['stack'].pop()
elif (context['stack'][-1].type == VAL and
not isinstance(token, yaml.ValueToken) and
not isinstance(token, (yaml.AnchorToken, yaml.TagToken))):
assert context['stack'][-2].type == KEY
context['stack'].pop()
context['stack'].pop()
elif (context['stack'][-1].type == KEY and
isinstance(next, (yaml.BlockEndToken,
yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken,
yaml.KeyToken))):
# A key without a value: it's part of a set. Let's drop this key
# and leave room for the next one.
context['stack'].pop()
else:
break
def check(conf, token, prev, next, nextnext, context):
try:
for problem in _check(conf, token, prev, next, nextnext, context):
yield problem
except AssertionError:
yield LintProblem(token.start_mark.line + 1,
token.start_mark.column + 1,
'cannot infer indentation: unexpected token')
yamllint-1.2.1/yamllint/rules/colons.py 0000664 0001750 0001750 00000005305 12655326364 020745 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the number of spaces before and after colons (``:``).
.. rubric:: Options
* ``max-spaces-before`` defines the maximal number of spaces allowed before
colons (use ``-1`` to disable).
* ``max-spaces-after`` defines the maximal number of spaces allowed after
colons (use ``-1`` to disable).
.. rubric:: Examples
#. With ``colons: {max-spaces-before: 0, max-spaces-after: 1}``
the following code snippet would **PASS**:
::
object:
- a
- b
key: value
#. With ``colons: {max-spaces-before: 1}``
the following code snippet would **PASS**:
::
object :
- a
- b
the following code snippet would **FAIL**:
::
object :
- a
- b
#. With ``colons: {max-spaces-after: 2}``
the following code snippet would **PASS**:
::
first: 1
second: 2
third: 3
the following code snippet would **FAIL**:
::
first: 1
2nd: 2
third: 3
"""
import yaml
from yamllint.rules.common import spaces_after, spaces_before, is_explicit_key
ID = 'colons'
TYPE = 'token'
CONF = {'max-spaces-before': int,
'max-spaces-after': int}
def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.ValueToken):
problem = spaces_before(token, prev, next,
max=conf['max-spaces-before'],
max_desc='too many spaces before colon')
if problem is not None:
yield problem
problem = spaces_after(token, prev, next,
max=conf['max-spaces-after'],
max_desc='too many spaces after colon')
if problem is not None:
yield problem
if isinstance(token, yaml.KeyToken) and is_explicit_key(token):
problem = spaces_after(token, prev, next,
max=conf['max-spaces-after'],
max_desc='too many spaces after question mark')
if problem is not None:
yield problem
yamllint-1.2.1/yamllint/rules/brackets.py 0000664 0001750 0001750 00000005426 12655326364 021252 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the number of spaces inside brackets (``[`` and
``]``).
.. rubric:: Options
* ``min-spaces-inside`` defines the minimal number of spaces required inside
brackets.
* ``max-spaces-inside`` defines the maximal number of spaces allowed inside
brackets.
.. rubric:: Examples
#. With ``brackets: {min-spaces-inside: 0, max-spaces-inside: 0}``
the following code snippet would **PASS**:
::
object: [1, 2, abc]
the following code snippet would **FAIL**:
::
object: [ 1, 2, abc ]
#. With ``brackets: {min-spaces-inside: 1, max-spaces-inside: 3}``
the following code snippet would **PASS**:
::
object: [ 1, 2, abc ]
the following code snippet would **PASS**:
::
object: [ 1, 2, abc ]
the following code snippet would **FAIL**:
::
object: [ 1, 2, abc ]
the following code snippet would **FAIL**:
::
object: [1, 2, abc ]
"""
import yaml
from yamllint.rules.common import spaces_after, spaces_before
ID = 'brackets'
TYPE = 'token'
CONF = {'min-spaces-inside': int,
'max-spaces-inside': int}
def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.FlowSequenceStartToken):
problem = spaces_after(token, prev, next,
min=conf['min-spaces-inside'],
max=conf['max-spaces-inside'],
min_desc='too few spaces inside brackets',
max_desc='too many spaces inside brackets')
if problem is not None:
yield problem
elif (isinstance(token, yaml.FlowSequenceEndToken) and
(prev is None or
not isinstance(prev, yaml.FlowSequenceStartToken))):
problem = spaces_before(token, prev, next,
min=conf['min-spaces-inside'],
max=conf['max-spaces-inside'],
min_desc='too few spaces inside brackets',
max_desc='too many spaces inside brackets')
if problem is not None:
yield problem
yamllint-1.2.1/yamllint/rules/comments.py 0000664 0001750 0001750 00000005545 12655326364 021303 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to control the position and formatting of comments.
.. rubric:: Options
* Use ``require-starting-space`` to require a space character right after the
``#``. Set to ``yes`` to enable, ``no`` to disable.
* ``min-spaces-from-content`` is used to visually separate inline comments from
content. It defines the minimal required number of spaces between a comment
and its preceding content.
.. rubric:: Examples
#. With ``comments: {require-starting-space: yes}``
the following code snippet would **PASS**:
::
# This sentence
# is a block comment
the following code snippet would **FAIL**:
::
#This sentence
#is a block comment
#. With ``comments: {min-spaces-from-content: 2}``
the following code snippet would **PASS**:
::
x = 2 ^ 127 - 1 # Mersenne prime number
the following code snippet would **FAIL**:
::
x = 2 ^ 127 - 1 # Mersenne prime number
"""
import yaml
from yamllint.linter import LintProblem
from yamllint.rules.common import get_comments_between_tokens
ID = 'comments'
TYPE = 'token'
CONF = {'require-starting-space': bool,
'min-spaces-from-content': int}
def check(conf, token, prev, next, nextnext, context):
for comment in get_comments_between_tokens(token, next):
if (conf['min-spaces-from-content'] != -1 and
not isinstance(token, yaml.StreamStartToken) and
comment.line == token.end_mark.line + 1):
# Sometimes token end marks are on the next line
if token.end_mark.buffer[token.end_mark.pointer - 1] != '\n':
if (comment.pointer - token.end_mark.pointer <
conf['min-spaces-from-content']):
yield LintProblem(comment.line, comment.column,
'too few spaces before comment')
if (conf['require-starting-space'] and
comment.pointer + 1 < len(comment.buffer) and
comment.buffer[comment.pointer + 1] != ' ' and
comment.buffer[comment.pointer + 1] != '\n'):
yield LintProblem(comment.line, comment.column + 1,
'missing starting space in comment')
yamllint-1.2.1/yamllint/rules/document_end.py 0000664 0001750 0001750 00000005132 12655326364 022112 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""
Use this rule to require or forbid the use of document end marker (``...``).
.. rubric:: Options
* Set ``present`` to ``yes`` when the document end marker is required, or to
``no`` when it is forbidden.
.. rubric:: Examples
#. With ``document-end: {present: yes}``
the following code snippet would **PASS**:
::
---
this:
is: [a, document]
...
---
- this
- is: another one
...
the following code snippet would **FAIL**:
::
---
this:
is: [a, document]
---
- this
- is: another one
...
#. With ``document-end: {present: no}``
the following code snippet would **PASS**:
::
---
this:
is: [a, document]
---
- this
- is: another one
the following code snippet would **FAIL**:
::
---
this:
is: [a, document]
...
---
- this
- is: another one
"""
import yaml
from yamllint.linter import LintProblem
ID = 'document-end'
TYPE = 'token'
CONF = {'present': bool}
def check(conf, token, prev, next, nextnext, context):
if conf['present']:
if (isinstance(token, yaml.StreamEndToken) and
not (isinstance(prev, yaml.DocumentEndToken) or
isinstance(prev, yaml.StreamStartToken))):
yield LintProblem(token.start_mark.line, 1,
'missing document end "..."')
elif (isinstance(token, yaml.DocumentStartToken) and
not (isinstance(prev, yaml.DocumentEndToken) or
isinstance(prev, yaml.StreamStartToken))):
yield LintProblem(token.start_mark.line + 1, 1,
'missing document end "..."')
else:
if isinstance(token, yaml.DocumentEndToken):
yield LintProblem(token.start_mark.line + 1,
token.start_mark.column + 1,
'found forbidden document end "..."')
yamllint-1.2.1/yamllint/__init__.py 0000664 0001750 0001750 00000002111 12675232450 020037 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
"""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."""
APP_NAME = 'yamllint'
APP_VERSION = '1.2.1'
APP_DESCRIPTION = __doc__
__author__ = u'Adrien Vergé'
__copyright__ = u'Copyright 2016, Adrien Vergé'
__license__ = 'GPLv3'
__version__ = APP_VERSION
yamllint-1.2.1/yamllint/parser.py 0000664 0001750 0001750 00000004731 12655326364 017614 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import yaml
class Line(object):
def __init__(self, line_no, buffer, start, end):
self.line_no = line_no
self.start = start
self.end = end
self.buffer = buffer
@property
def content(self):
return self.buffer[self.start:self.end]
class Token(object):
def __init__(self, line_no, curr, prev, next, nextnext):
self.line_no = line_no
self.curr = curr
self.prev = prev
self.next = next
self.nextnext = nextnext
def line_generator(buffer):
line_no = 1
cur = 0
next = buffer.find('\n')
while next != -1:
yield Line(line_no, buffer, start=cur, end=next)
cur = next + 1
next = buffer.find('\n', cur)
line_no += 1
yield Line(line_no, buffer, start=cur, end=len(buffer))
def token_generator(buffer):
yaml_loader = yaml.BaseLoader(buffer)
try:
prev = None
curr = yaml_loader.get_token()
while curr is not None:
next = yaml_loader.get_token()
nextnext = yaml_loader.peek_token()
yield Token(curr.start_mark.line + 1, curr, prev, next, nextnext)
prev = curr
curr = next
except yaml.scanner.ScannerError:
pass
def token_or_line_generator(buffer):
"""Generator that mixes tokens and lines, ordering them by line number"""
token_gen = token_generator(buffer)
line_gen = line_generator(buffer)
token = next(token_gen, None)
line = next(line_gen, None)
while token is not None or line is not None:
if token is None or (line is not None and
token.line_no > line.line_no):
yield line
line = next(line_gen, None)
else:
yield token
token = next(token_gen, None)
yamllint-1.2.1/yamllint/linter.py 0000664 0001750 0001750 00000011513 12666346130 017604 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import yaml
from yamllint import parser
class LintProblem(object):
"""Represents a linting problem found by yamllint."""
def __init__(self, line, column, desc='', rule=None):
#: Line on which the problem was found (starting at 1)
self.line = line
#: Column on which the problem was found (starting at 1)
self.column = column
#: Human-readable description of the problem
self.desc = desc
#: Identifier of the rule that detected the problem
self.rule = rule
self.level = None
@property
def message(self):
if self.rule is not None:
return '%s (%s)' % (self.desc, self.rule)
return self.desc
def __eq__(self, other):
return (self.line == other.line and
self.column == other.column and
self.rule == other.rule)
def __lt__(self, other):
return (self.line < other.line or
(self.line == other.line and self.column < other.column))
def __repr__(self):
return '%d:%d: %s' % (self.line, self.column, self.message)
def get_costemic_problems(buffer, conf):
rules = conf.enabled_rules()
# Split token rules from line rules
token_rules = [r for r in rules if r.TYPE == 'token']
line_rules = [r for r in rules if r.TYPE == 'line']
context = {}
for rule in token_rules:
context[rule.ID] = {}
for elem in parser.token_or_line_generator(buffer):
if isinstance(elem, parser.Token):
for rule in token_rules:
rule_conf = conf.rules[rule.ID]
for problem in rule.check(rule_conf,
elem.curr, elem.prev, elem.next,
elem.nextnext,
context[rule.ID]):
problem.rule = rule.ID
problem.level = rule_conf['level']
yield problem
elif isinstance(elem, parser.Line):
for rule in line_rules:
rule_conf = conf.rules[rule.ID]
for problem in rule.check(rule_conf, elem):
problem.rule = rule.ID
problem.level = rule_conf['level']
yield problem
def get_syntax_error(buffer):
try:
list(yaml.parse(buffer, Loader=yaml.BaseLoader))
except yaml.error.MarkedYAMLError as e:
problem = LintProblem(e.problem_mark.line + 1,
e.problem_mark.column + 1,
'syntax error: ' + e.problem)
problem.level = 'error'
return problem
def _run(buffer, conf):
# If the document contains a syntax error, save it and yield it at the
# right line
syntax_error = get_syntax_error(buffer)
for problem in get_costemic_problems(buffer, conf):
# Insert the syntax error (if any) at the right place...
if (syntax_error and syntax_error.line <= problem.line and
syntax_error.column <= problem.column):
yield syntax_error
# If there is already a yamllint error at the same place, discard
# it as it is probably redundant (and maybe it's just a 'warning',
# in which case the script won't even exit with a failure status).
if (syntax_error.line == problem.line and
syntax_error.column == problem.column):
syntax_error = None
continue
syntax_error = None
yield problem
if syntax_error:
yield syntax_error
def run(input, conf):
"""Lints a YAML source.
Returns a generator of LintProblem objects.
:param input: buffer, string or stream to read from
:param conf: yamllint configuration object
"""
if type(input) in (type(b''), type(u'')): # compat with Python 2 & 3
return _run(input, conf)
elif hasattr(input, 'read'): # Python 2's file or Python 3's io.IOBase
# We need to have everything in memory to parse correctly
content = input.read()
return _run(content, conf)
else:
raise TypeError('input should be a string or a stream')
yamllint-1.2.1/yamllint/config.py 0000664 0001750 0001750 00000011363 12675231644 017562 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
import os.path
import yaml
import yamllint.rules
class YamlLintConfigError(Exception):
pass
class YamlLintConfig(object):
def __init__(self, content=None, file=None):
assert (content is None) ^ (file is None)
if file is not None:
with open(file) as f:
content = f.read()
self.parse(content)
self.validate()
def enabled_rules(self):
return [yamllint.rules.get(id) for id, val in self.rules.items()
if val is not False]
def extend(self, base_config):
assert isinstance(base_config, YamlLintConfig)
for rule in self.rules:
if (type(self.rules[rule]) == dict and
rule in base_config.rules and
base_config.rules[rule] is not False):
base_config.rules[rule].update(self.rules[rule])
else:
base_config.rules[rule] = self.rules[rule]
self.rules = base_config.rules
def parse(self, raw_content):
try:
conf = yaml.safe_load(raw_content)
except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e)
if type(conf) != dict:
raise YamlLintConfigError('invalid config: not a dict')
self.rules = conf.get('rules', {})
# Does this conf override another conf that we need to load?
if 'extends' in conf:
path = get_extended_config_file(conf['extends'])
base = YamlLintConfig(file=path)
try:
self.extend(base)
except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e)
def validate(self):
for id in self.rules:
try:
rule = yamllint.rules.get(id)
except Exception as e:
raise YamlLintConfigError('invalid config: %s' % e)
self.rules[id] = validate_rule_conf(rule, self.rules[id])
def validate_rule_conf(rule, conf):
if conf is False or conf == 'disable':
return False
elif conf == 'enable':
conf = {}
if type(conf) == dict:
if 'level' not in conf:
conf['level'] = 'error'
elif conf['level'] not in ('error', 'warning'):
raise YamlLintConfigError(
'invalid config: level should be "error" or "warning"')
options = getattr(rule, 'CONF', {})
for optkey in conf:
if optkey == 'level':
continue
if optkey not in options:
raise YamlLintConfigError(
'invalid config: unknown option "%s" for rule "%s"' %
(optkey, rule.ID))
if type(options[optkey]) == tuple:
if (conf[optkey] not in options[optkey] and
type(conf[optkey]) not in options[optkey]):
raise YamlLintConfigError(
'invalid config: option "%s" of "%s" should be in %s'
% (optkey, rule.ID, options[optkey]))
else:
if type(conf[optkey]) != options[optkey]:
raise YamlLintConfigError(
'invalid config: option "%s" of "%s" should be %s'
% (optkey, rule.ID, options[optkey].__name__))
for optkey in options:
if optkey not in conf:
raise YamlLintConfigError(
'invalid config: missing option "%s" for rule "%s"' %
(optkey, rule.ID))
else:
raise YamlLintConfigError(('invalid config: rule "%s": should be '
'either "enable", "disable" or a dict')
% rule.ID)
return conf
def get_extended_config_file(name):
# Is it a standard conf shipped with yamllint...
if '/' not in name:
std_conf = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'conf', name + '.yaml')
if os.path.isfile(std_conf):
return std_conf
# or a custom conf on filesystem?
return name
yamllint-1.2.1/yamllint/cli.py 0000664 0001750 0001750 00000011314 12675231644 017060 0 ustar adrien adrien 0000000 0000000 # -*- 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 .
from __future__ import print_function
import os.path
import sys
import argparse
from yamllint import APP_DESCRIPTION, APP_NAME, APP_VERSION
from yamllint.config import YamlLintConfig, YamlLintConfigError
from yamllint import linter
def find_files_recursively(items):
for item in items:
if os.path.isdir(item):
for root, dirnames, filenames in os.walk(item):
for filename in [f for f in filenames
if f.endswith(('.yml', '.yaml'))]:
yield os.path.join(root, filename)
else:
yield item
class Format(object):
@staticmethod
def parsable(problem, filename):
return ('%(file)s:%(line)s:%(column)s: [%(level)s] %(message)s' %
{'file': filename,
'line': problem.line,
'column': problem.column,
'level': problem.level,
'message': problem.message})
@staticmethod
def standard(problem, filename):
line = ' \033[2m%d:%d\033[0m' % (problem.line, problem.column)
line += max(20 - len(line), 0) * ' '
if problem.level == 'warning':
line += '\033[33m%s\033[0m' % problem.level
else:
line += '\033[31m%s\033[0m' % problem.level
line += max(38 - len(line), 0) * ' '
line += problem.desc
if problem.rule:
line += ' \033[2m(%s)\033[0m' % problem.rule
return line
def run(argv=None):
parser = argparse.ArgumentParser(prog=APP_NAME,
description=APP_DESCRIPTION)
parser.add_argument('files', metavar='FILE_OR_DIR', nargs='+',
help='files to check')
parser.add_argument('-c', '--config-file', dest='config_file',
action='store', help='path to a custom configuration')
parser.add_argument('-d', '--config-data', dest='config_data',
action='store',
help='custom configuration (as YAML source)')
parser.add_argument('-f', '--format',
choices=('parsable', 'standard'), default='standard',
help='format for parsing output')
parser.add_argument('-v', '--version', action='version',
version='%s %s' % (APP_NAME, APP_VERSION))
# TODO: read from stdin when no filename?
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)
try:
if args.config_data is not None:
if args.config_data != '' and ':' not in args.config_data:
args.config_data = 'extends: ' + args.config_data
conf = YamlLintConfig(content=args.config_data)
elif args.config_file is not None:
conf = YamlLintConfig(file=args.config_file)
elif os.path.isfile('.yamllint'):
conf = YamlLintConfig(file='.yamllint')
else:
conf = YamlLintConfig('extends: default')
except YamlLintConfigError as e:
print(e, file=sys.stderr)
sys.exit(-1)
return_code = 0
for file in find_files_recursively(args.files):
try:
first = True
with open(file) as f:
for problem in linter.run(f, conf):
if args.format == 'parsable':
print(Format.parsable(problem, file))
else:
if first:
print('\033[4m%s\033[0m' % file)
first = False
print(Format.standard(problem, file))
if return_code == 0 and problem.level == 'error':
return_code = 1
if not first and args.format != 'parsable':
print('')
except EnvironmentError as e:
print(e, file=sys.stderr)
return_code = -1
sys.exit(return_code)
yamllint-1.2.1/README.rst 0000664 0001750 0001750 00000004102 12675173711 015572 0 ustar adrien adrien 0000000 0000000 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
:alt: CI tests status
.. image::
https://coveralls.io/repos/github/adrienverge/yamllint/badge.svg?branch=master
:target: https://coveralls.io/github/adrienverge/yamllint?branch=master
:alt: Code coverage status
.. image:: https://readthedocs.org/projects/yamllint/badge/?version=latest
:target: http://yamllint.readthedocs.org/en/latest/?badge=latest
:alt: Documentation status
Written in Python (compatible with Python 2 & 3).
Documentation
-------------
http://yamllint.readthedocs.org/
Short overview
--------------
Screenshot
^^^^^^^^^^
.. image:: docs/screenshot.png
:alt: yamllint screenshot
Installation
^^^^^^^^^^^^
On Fedora / CentOS:
.. code:: bash
sudo dnf install yamllint
On Debian 9+ / Ubuntu 16.04+:
.. code:: bash
sudo apt-get install yamllint
On older Debian / Ubuntu versions:
.. code:: bash
sudo add-apt-repository -y ppa:adrienverge/ppa && sudo apt-get update
sudo apt-get install yamllint
Alternatively using pip, the Python package manager:
.. code:: bash
sudo pip install yamllint
Usage
^^^^^
.. code:: bash
# Lint one or more files
yamllint my_file.yml my_other_file.yaml ...
.. code:: bash
# Lint all YAML files in a directory
yamllint .
.. code:: bash
# Use a pre-defined lint configuration
yamllint -d relaxed file.yaml
# Use a custom lint configuration
yamllint -c ~/myconfig file.yml
.. code:: bash
# Output a parsable format (for syntax checking in editors like Vim, emacs...)
yamllint -f parsable file.yaml
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
yamllint-1.2.1/docs/ 0000775 0001750 0001750 00000000000 12675233100 015023 5 ustar adrien adrien 0000000 0000000 yamllint-1.2.1/docs/index.rst 0000664 0001750 0001750 00000000642 12653752650 016702 0 ustar adrien adrien 0000000 0000000 yamllint documentation
======================
.. automodule:: yamllint
Screenshot
----------
.. image:: screenshot.png
:alt: yamllint screenshot
.. note::
The default output format is inspired by `eslint `_, a
great linting tool for Javascript.
Table of contents
-----------------
.. toctree::
:maxdepth: 2
quickstart
configuration
rules
development
text_editors
yamllint-1.2.1/docs/text_editors.rst 0000664 0001750 0001750 00000001555 12675173704 020315 0 ustar adrien adrien 0000000 0000000 Integration with text editors
=============================
Most text editors support syntax checking and highlighting, to visually report
syntax errors and warnings to the user. yamllint can be used to syntax-check
YAML source, but a bit of configuration is required depending on your favorite
text editor.
Vim
---
Assuming that the `syntastic `_ plugin
is installed, add to your ``.vimrc``:
::
let g:syntastic_yaml_checkers = ['yamllint']
Neovim
------
Assuming that the `neomake `_ plugin is
installed, yamllint is supported by default. It is automatically enabled when
editing YAML files.
Other text editors
------------------
.. rubric:: Help wanted!
Your favorite text editor is not listed here? Help us improve by adding a
section (by opening a pull-request or issue on GitHub).
yamllint-1.2.1/docs/Makefile 0000664 0001750 0001750 00000015162 12650464423 016477 0 ustar adrien adrien 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/yamllint.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/yamllint.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/yamllint"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/yamllint"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
yamllint-1.2.1/docs/development.rst 0000664 0001750 0001750 00000000264 12651202273 020102 0 ustar adrien adrien 0000000 0000000 Development
===========
yamllint provides both a script and a Python module. The latter can be used to
write your own linting tools:
.. automodule:: yamllint.linter
:members:
yamllint-1.2.1/docs/rules.rst 0000664 0001750 0001750 00000002775 12653743430 016732 0 ustar adrien adrien 0000000 0000000 Rules
=====
When linting a document with yamllint, a series of rules (such as
``line-length``, ``trailing-spaces``, etc.) are checked against.
A :doc:`configuration file ` can be used to enable or disable
these rules, to set their level (*error* or *warning*), but also to tweak their
options.
This page describes the rules and their options.
.. contents:: List of rules
:local:
:depth: 1
braces
------
.. automodule:: yamllint.rules.braces
brackets
--------
.. automodule:: yamllint.rules.brackets
colons
------
.. automodule:: yamllint.rules.colons
commas
------
.. automodule:: yamllint.rules.commas
comments
--------
.. automodule:: yamllint.rules.comments
comments-indentation
--------------------
.. automodule:: yamllint.rules.comments_indentation
document-end
------------
.. automodule:: yamllint.rules.document_end
document-start
--------------
.. automodule:: yamllint.rules.document_start
empty-lines
-----------
.. automodule:: yamllint.rules.empty_lines
hyphens
-------
.. automodule:: yamllint.rules.hyphens
indentation
-----------
.. automodule:: yamllint.rules.indentation
key-duplicates
--------------
.. automodule:: yamllint.rules.key_duplicates
line-length
-----------
.. automodule:: yamllint.rules.line_length
new-line-at-end-of-file
-----------------------
.. automodule:: yamllint.rules.new_line_at_end_of_file
new-lines
---------
.. automodule:: yamllint.rules.new_lines
trailing-spaces
---------------
.. automodule:: yamllint.rules.trailing_spaces
yamllint-1.2.1/docs/configuration.rst 0000664 0001750 0001750 00000005272 12670240422 020432 0 ustar adrien adrien 0000000 0000000 Configuration
=============
yamllint uses a set of *rules* to check sources files for problems. Each rule is
independent from the others, and can be enabled, disabled or tweaked. All these
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.yaml
Default configuration
---------------------
Unless told otherwise, yamllint uses its ``default`` configuration:
.. literalinclude:: ../yamllint/conf/default.yaml
:language: yaml
Details on rules can be found on :doc:`the rules page `.
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
-----------------------------------
When writing a custom configuration file, you don't need to redefine every rule.
Just extend the ``default`` configuration (or any already-existing configuration
file).
For instance, if you just want to disable the ``comments-indentation`` rule,
your file could look like this:
.. code-block:: yaml
# This is my first, very own configuration file for yamllint!
# It extends the default conf by adjusting some options.
extends: default
rules:
comments-indentation: disable # don't bother me with this rule
Similarly, if you want to set the ``line-length`` rule as a warning and be less
strict on block sequences indentation:
.. code-block:: yaml
extends: default
rules:
# 80 chars should be enough, but don't fail if a line is longer
line-length:
max: 80
level: warning
# accept both key:
# - item
#
# and key:
# - item
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.yaml
Errors and warnings
-------------------
Problems detected by yamllint can be raised either as errors or as warnings.
In both cases, the script will output them (with different colors when using the
``standard`` output format), but the exit code can be different. More precisely,
the script will exit will a failure code *only when* there is one or more
error(s).
yamllint-1.2.1/docs/screenshot.png 0000664 0001750 0001750 00000121401 12653750154 017716 0 ustar adrien adrien 0000000 0000000 PNG
IHDR uh tIME&4k- IDATx{XW8 \7DQ"uFh(M,*DM&J;A֘YDc$Hh." DPX⊀Bff{yz`NWשStwun# aaaڥaaa8qfaaNaagaaęaaa8qfnCDUG:= vOçʽ46zaac~FFF֑6pYYFKKNӟԧ'^=m00]8!sK=Ow&=}Mt
'}3qW'0}~w@u-ؼHwdOAAfϞ-(ӧeAAA8vQ]]
J/++555شi<vفikP]],ڪcO?2V|[[-444]g}hjjByy9y(lmmZTWWu/O`a!'&FFbAݒ:ijї?V} ʔJ%mܸQPva9s&ѠA(!!Z/9sFN+bt#"*(( oooR(4dJKKL?Rt[GLF~w'K."$BA'Oz'$%ߥĐhxb!{{{JNNFwXXXXXzǙ'wdݓXLО-C׃@f @WJsXXXXPMM