Skip to content

Commit

Permalink
Allow only non-empty brackets/braces
Browse files Browse the repository at this point in the history
We'd like to disallow brackets and braces in our YAML, but there's a
catch: the only way to describe an empty array or hash in YAML is to
supply an empty one (`[]` or `{}`). Otherwise, the value will be null.

This commit adds a `non-empty` option to `forbid` for brackets and
braces. When it is set, all flow and sequence mappings will cause errors
_except_ for empty ones.
  • Loading branch information
rustygeldmacher authored Dec 15, 2020
1 parent 22335b2 commit ee4d163
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 6 deletions.
24 changes: 24 additions & 0 deletions tests/rules/test_braces.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ def test_forbid(self):
' a: 1\n'
'}\n', conf, problem=(2, 8))

conf = ('braces:\n'
' forbid: non-empty\n')
self.check('---\n'
'dict:\n'
' a: 1\n', conf)
self.check('---\n'
'dict: {}\n', conf)
self.check('---\n'
'dict: {\n'
'}\n', conf)
self.check('---\n'
'dict: {\n'
'# commented: value\n'
'# another: value2\n'
'}\n', conf)
self.check('---\n'
'dict: {a}\n', conf, problem=(2, 8))
self.check('---\n'
'dict: {a: 1}\n', conf, problem=(2, 8))
self.check('---\n'
'dict: {\n'
' a: 1\n'
'}\n', conf, problem=(2, 8))

def test_min_spaces(self):
conf = ('braces:\n'
' max-spaces-inside: -1\n'
Expand Down
23 changes: 23 additions & 0 deletions tests/rules/test_brackets.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,29 @@ def test_forbid(self):
' b\n'
']\n', conf, problem=(2, 9))

conf = ('brackets:\n'
' forbid: non-empty\n')
self.check('---\n'
'array:\n'
' - a\n'
' - b\n', conf)
self.check('---\n'
'array: []\n', conf)
self.check('---\n'
'array: [\n\n'
']\n', conf)
self.check('---\n'
'array: [\n'
'# a comment\n'
']\n', conf)
self.check('---\n'
'array: [a, b]\n', conf, problem=(2, 9))
self.check('---\n'
'array: [\n'
' a,\n'
' b\n'
']\n', conf, problem=(2, 9))

def test_min_spaces(self):
conf = ('brackets:\n'
' max-spaces-inside: -1\n'
Expand Down
27 changes: 24 additions & 3 deletions yamllint/rules/braces.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
* ``forbid`` is used to forbid the use of flow mappings which are denoted by
surrounding braces (``{`` and ``}``). Use ``true`` to forbid the use of flow
mappings completely.
mappings completely. Use ``non-empty`` to forbid the use of all flow
mappings except for empty ones.
* ``min-spaces-inside`` defines the minimal number of spaces required inside
braces.
* ``max-spaces-inside`` defines the maximal number of spaces allowed inside
Expand Down Expand Up @@ -60,6 +61,18 @@
object: { key1: 4, key2: 8 }
#. With ``braces: {forbid: non-empty}``
the following code snippet would **PASS**:
::
object: {}
the following code snippet would **FAIL**:
::
object: { key1: 4, key2: 8 }
#. With ``braces: {min-spaces-inside: 0, max-spaces-inside: 0}``
the following code snippet would **PASS**:
Expand Down Expand Up @@ -128,7 +141,7 @@

ID = 'braces'
TYPE = 'token'
CONF = {'forbid': bool,
CONF = {'forbid': (bool, 'non-empty'),
'min-spaces-inside': int,
'max-spaces-inside': int,
'min-spaces-inside-empty': int,
Expand All @@ -141,7 +154,15 @@


def check(conf, token, prev, next, nextnext, context):
if conf['forbid'] and isinstance(token, yaml.FlowMappingStartToken):
if (conf['forbid'] is True and
isinstance(token, yaml.FlowMappingStartToken)):
yield LintProblem(token.start_mark.line + 1,
token.end_mark.column + 1,
'forbidden flow mapping')

elif (conf['forbid'] == 'non-empty' and
isinstance(token, yaml.FlowMappingStartToken) and
not isinstance(next, yaml.FlowMappingEndToken)):
yield LintProblem(token.start_mark.line + 1,
token.end_mark.column + 1,
'forbidden flow mapping')
Expand Down
27 changes: 24 additions & 3 deletions yamllint/rules/brackets.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
* ``forbid`` is used to forbid the use of flow sequences which are denoted by
surrounding brackets (``[`` and ``]``). Use ``true`` to forbid the use of
flow sequences completely.
flow sequences completely. Use ``non-empty`` to forbid the use of all flow
sequences except for empty ones.
* ``min-spaces-inside`` defines the minimal number of spaces required inside
brackets.
* ``max-spaces-inside`` defines the maximal number of spaces allowed inside
Expand Down Expand Up @@ -61,6 +62,18 @@
object: [ 1, 2, abc ]
#. With ``brackets: {forbid: non-empty}``
the following code snippet would **PASS**:
::
object: []
the following code snippet would **FAIL**:
::
object: [ 1, 2, abc ]
#. With ``brackets: {min-spaces-inside: 0, max-spaces-inside: 0}``
the following code snippet would **PASS**:
Expand Down Expand Up @@ -129,7 +142,7 @@

ID = 'brackets'
TYPE = 'token'
CONF = {'forbid': bool,
CONF = {'forbid': (bool, 'non-empty'),
'min-spaces-inside': int,
'max-spaces-inside': int,
'min-spaces-inside-empty': int,
Expand All @@ -142,7 +155,15 @@


def check(conf, token, prev, next, nextnext, context):
if conf['forbid'] and isinstance(token, yaml.FlowSequenceStartToken):
if (conf['forbid'] is True and
isinstance(token, yaml.FlowSequenceStartToken)):
yield LintProblem(token.start_mark.line + 1,
token.end_mark.column + 1,
'forbidden flow sequence')

elif (conf['forbid'] == 'non-empty' and
isinstance(token, yaml.FlowSequenceStartToken) and
not isinstance(next, yaml.FlowSequenceEndToken)):
yield LintProblem(token.start_mark.line + 1,
token.end_mark.column + 1,
'forbidden flow sequence')
Expand Down

0 comments on commit ee4d163

Please sign in to comment.