From 0b0251bacc99bbfe5f37a33042b78ad7a8666b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Tue, 19 Jan 2016 22:26:32 +0100 Subject: [PATCH] Rules: indentation: Add the 'indent-sequences' option Using either 'yes', 'no' or 'whatever', the user will be able to choose whether to force block sequence items to be indented, to force them not to be indented, or don't care, respectively. --- tests/rules/test_colons.py | 6 +- tests/rules/test_comments_indentation.py | 2 +- tests/rules/test_hyphens.py | 16 +- tests/rules/test_indentation.py | 204 +++++++++++++++++++++-- yamllint/conf/default.yml | 2 +- yamllint/rules/indentation.py | 24 ++- 6 files changed, 218 insertions(+), 36 deletions(-) diff --git a/tests/rules/test_colons.py b/tests/rules/test_colons.py index c9aaaf2..98a4171 100644 --- a/tests/rules/test_colons.py +++ b/tests/rules/test_colons.py @@ -42,7 +42,7 @@ class ColonTestCase(RuleTestCase): ' - p: kdjf\n' ' - q: val0\n' ' - q2:\n' - ' - val1\n' + ' - val1\n' '...\n', conf) self.check('---\n' 'object:\n' @@ -67,7 +67,7 @@ class ColonTestCase(RuleTestCase): ' - o: {k1: v1}\n' ' - o: {k1: v1}\n' ' - q2:\n' - ' - val1\n' + ' - val1\n' '...\n', conf) self.check('---\n' 'a: {b: {c: d, e : f}}\n', conf) @@ -94,7 +94,7 @@ class ColonTestCase(RuleTestCase): '...\n', conf, problem=(2, 4)) self.check('---\n' '- lib :\n' - ' - var\n' + ' - var\n' '...\n', conf, problem=(2, 6)) self.check('---\n' 'a: {b: {c : d, e : f}}\n', conf, diff --git a/tests/rules/test_comments_indentation.py b/tests/rules/test_comments_indentation.py index dcd6921..1362cc1 100644 --- a/tests/rules/test_comments_indentation.py +++ b/tests/rules/test_comments_indentation.py @@ -115,7 +115,7 @@ class CommentsIndentationTestCase(RuleTestCase): ' # comments\n' ' b: 2\n', conf) self.check('---\n' - 'mylist:\n' + 'my list for today:\n' ' - todo 1\n' ' - todo 2\n' ' # commented for now\n' diff --git a/tests/rules/test_hyphens.py b/tests/rules/test_hyphens.py index dfd2810..20c4422 100644 --- a/tests/rules/test_hyphens.py +++ b/tests/rules/test_hyphens.py @@ -36,12 +36,12 @@ class HyphenTestCase(RuleTestCase): '- elem2\n', conf) self.check('---\n' 'object:\n' - '- elem1\n' - '- elem2\n', conf) + ' - elem1\n' + ' - elem2\n', conf) self.check('---\n' 'object:\n' - '- elem1\n' - '- elem2\n', conf) + ' - elem1\n' + ' - elem2\n', conf) self.check('---\n' 'object:\n' ' subobject:\n' @@ -69,12 +69,12 @@ class HyphenTestCase(RuleTestCase): '- elem2\n', conf, problem=(2, 3)) self.check('---\n' 'object:\n' - '- elem1\n' - '- elem2\n', conf, problem=(4, 3)) + ' - elem1\n' + ' - elem2\n', conf, problem=(4, 5)) self.check('---\n' 'object:\n' - '- elem1\n' - '- elem2\n', conf, problem1=(3, 3), problem2=(4, 3)) + ' - elem1\n' + ' - elem2\n', conf, problem1=(3, 5), problem2=(4, 5)) self.check('---\n' 'object:\n' ' subobject:\n' diff --git a/tests/rules/test_indentation.py b/tests/rules/test_indentation.py index 8eb7174..f497776 100644 --- a/tests/rules/test_indentation.py +++ b/tests/rules/test_indentation.py @@ -48,7 +48,20 @@ class IndentationTestCase(RuleTestCase): '...\n', conf) def test_one_space(self): - conf = 'indentation: {spaces: 1}' + 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' @@ -63,7 +76,20 @@ class IndentationTestCase(RuleTestCase): '...\n', conf) def test_two_spaces(self): - conf = 'indentation: {spaces: 2}' + 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' @@ -78,7 +104,20 @@ class IndentationTestCase(RuleTestCase): '...\n', conf) def test_three_spaces(self): - conf = 'indentation: {spaces: 3}' + 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' @@ -92,8 +131,122 @@ class IndentationTestCase(RuleTestCase): ' date: 1991\n' '...\n', conf) - def test_under_indented(self): + 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_flow_mappings(self): + conf = 'indentation: {spaces: 2}' + 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' + '}\n', conf, problem=(3, 3)) + 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=(3, 4)) + self.check('---\n' + 'a: {\n' + ' x: 1,\n' + ' y, z: 1\n' + ' }\n', conf, problem=(5, 3)) + + def test_flow_sequences(self): conf = 'indentation: {spaces: 2}' + self.check('---\n' + 'a: [x,\n' + ' y,\n' + ' z]\n', conf) + self.check('---\n' + 'a: [x,\n' + ' y,\n' + ' z]\n', conf, problem=(3, 4)) + self.check('---\n' + 'a: [x,\n' + ' y,\n' + ' z]\n', conf, problem=(3, 6)) + self.check('---\n' + 'a: [x,\n' + ' y, z\n' + ']\n', conf, problem=(3, 3)) + self.check('---\n' + 'a: [\n' + ' x,\n' + ' 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=(3, 4)) + self.check('---\n' + 'a: [\n' + ' x,\n' + ' y, z\n' + ' ]\n', conf, problem=(5, 3)) + + def test_under_indented(self): + conf = 'indentation: {spaces: 2, indent-sequences: yes}' self.check('---\n' 'object:\n' ' val: 1\n' @@ -109,7 +262,7 @@ class IndentationTestCase(RuleTestCase): ' - name: Unix\n' ' date: 1969\n' '...\n', conf, problem=(5, 6, 'syntax')) - conf = 'indentation: {spaces: 4}' + conf = 'indentation: {spaces: 4, indent-sequences: yes}' self.check('---\n' 'object:\n' ' val: 1\n' @@ -127,7 +280,7 @@ class IndentationTestCase(RuleTestCase): '...\n', conf, problem=(5, 10, 'syntax')) def test_over_indented(self): - conf = 'indentation: {spaces: 2}' + conf = 'indentation: {spaces: 2, indent-sequences: yes}' self.check('---\n' 'object:\n' ' val: 1\n' @@ -143,7 +296,7 @@ class IndentationTestCase(RuleTestCase): ' - name: Unix\n' ' date: 1969\n' '...\n', conf, problem=(5, 12, 'syntax')) - conf = 'indentation: {spaces: 4}' + conf = 'indentation: {spaces: 4, indent-sequences: yes}' self.check('---\n' 'object:\n' ' val: 1\n' @@ -165,7 +318,7 @@ class IndentationTestCase(RuleTestCase): self.check('---\n' ' - el1\n' ' - el2:\n' - ' - subel\n' + ' - subel\n' '...\n', conf, problem=(2, 3)) self.check('---\n' @@ -174,24 +327,32 @@ class IndentationTestCase(RuleTestCase): ' - 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: 2, indent-sequences: yes}' self.check('---\n' 'long_string: >\n' ' bla bla blah\n' ' blah bla bla\n' - '...\n', None) + '...\n', conf) self.check('---\n' '- long_string: >\n' ' bla bla blah\n' ' blah bla bla\n' - '...\n', None) + '...\n', conf) self.check('---\n' 'obj:\n' ' - long_string: >\n' ' bla bla blah\n' ' blah bla bla\n' - '...\n', None) + '...\n', conf) def test_empty_value(self): conf = 'indentation: {spaces: 2}' @@ -233,8 +394,23 @@ class IndentationTestCase(RuleTestCase): '- 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: 2}' self.check('---\n' 'a:\n' ' b:\n' @@ -243,19 +419,19 @@ class IndentationTestCase(RuleTestCase): ' e:\n' ' f:\n' 'g:\n' - '...\n', None) + '...\n', conf) self.check('---\n' 'a:\n' ' b:\n' ' c:\n' ' d:\n' - '...\n', None, problem=(5, 4, 'syntax')) + '...\n', conf, problem=(5, 4, 'syntax')) self.check('---\n' 'a:\n' ' b:\n' ' c:\n' ' d:\n' - '...\n', None, problem=(5, 2, 'syntax')) + '...\n', conf, problem=(5, 2, 'syntax')) def test_first_line(self): conf = ('indentation: {spaces: 2}\n' diff --git a/yamllint/conf/default.yml b/yamllint/conf/default.yml index bca683f..b2c5013 100644 --- a/yamllint/conf/default.yml +++ b/yamllint/conf/default.yml @@ -31,7 +31,7 @@ rules: max-spaces-after: 1 indentation: spaces: 2 - # indent-sequences: no + indent-sequences: yes line-length: max: 80 new-line-at-end-of-file: {level: error} diff --git a/yamllint/rules/indentation.py b/yamllint/rules/indentation.py index 67bfccc..d1cec5b 100644 --- a/yamllint/rules/indentation.py +++ b/yamllint/rules/indentation.py @@ -22,7 +22,8 @@ from yamllint.rules.common import is_explicit_key ID = 'indentation' TYPE = 'token' -CONF = {'spaces': int} +CONF = {'spaces': int, + 'indent-sequences': (True, False, 'whatever')} ROOT, MAP, B_SEQ, F_SEQ, KEY, VAL = range(6) @@ -164,16 +165,21 @@ def check(conf, token, prev, next, context): # yaml.scan()ning this: # '- lib:\n' # ' - var\n' - if next.start_mark.column == context['stack'][-1].indent: - # key: - # - e1 - # - e2 + if conf['indent-sequences'] is False: indent = context['stack'][-1].indent - else: - # key: - # - e1 - # - e2 + elif conf['indent-sequences'] is True: indent = context['stack'][-1].indent + conf['spaces'] + else: # 'whatever' + if next.start_mark.column == context['stack'][-1].indent: + # key: + # - e1 + # - e2 + indent = context['stack'][-1].indent + else: + # key: + # - e1 + # - e2 + indent = context['stack'][-1].indent + conf['spaces'] else: # k: # value