Skip to content

Commit a21def3

Browse files
committed
Add an --unsafe option to check-yaml
1 parent e80813e commit a21def3

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ Add this to your `.pre-commit-config.yaml`
5252
- `check-yaml` - Attempts to load all yaml files to verify syntax.
5353
- `--allow-multiple-documents` - allow yaml files which use the
5454
[multi-document syntax](http://www.yaml.org/spec/1.2/spec.html#YAML)
55+
- `--unsafe` - Instaed of loading the files, simply parse them for syntax.
56+
A syntax-only check enables extensions and unsafe constructs which would
57+
otherwise be forbidden. Using this option removes all guarantees of
58+
portability to other yaml implementations.
59+
Implies `--allow-multiple-documents`.
5560
- `debug-statements` - Check for pdb / ipdb / pudb statements in code.
5661
- `detect-aws-credentials` - Checks for the existence of AWS secrets that you
5762
have set up with the AWS CLI.

pre_commit_hooks/check_yaml.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import print_function
22

33
import argparse
4+
import collections
45
import sys
56

67
import yaml
@@ -11,24 +12,52 @@
1112
Loader = yaml.SafeLoader
1213

1314

15+
def _exhaust(gen):
16+
for _ in gen:
17+
pass
18+
19+
20+
def _parse_unsafe(*args, **kwargs):
21+
_exhaust(yaml.parse(*args, **kwargs))
22+
23+
1424
def _load_all(*args, **kwargs):
15-
# need to exhaust the generator
16-
return tuple(yaml.load_all(*args, **kwargs))
25+
_exhaust(yaml.load_all(*args, **kwargs))
26+
27+
28+
Key = collections.namedtuple('Key', ('multi', 'unsafe'))
29+
LOAD_FNS = {
30+
Key(multi=False, unsafe=False): yaml.load,
31+
Key(multi=False, unsafe=True): _parse_unsafe,
32+
Key(multi=True, unsafe=False): _load_all,
33+
Key(multi=True, unsafe=True): _parse_unsafe,
34+
}
1735

1836

1937
def check_yaml(argv=None):
2038
parser = argparse.ArgumentParser()
2139
parser.add_argument(
22-
'-m', '--allow-multiple-documents', dest='yaml_load_fn',
23-
action='store_const', const=_load_all, default=yaml.load,
40+
'-m', '--multi', '--allow-multiple-documents', action='store_true',
41+
)
42+
parser.add_argument(
43+
'--unsafe', action='store_true',
44+
help=(
45+
'Instead of loading the files, simply parse them for syntax. '
46+
'A syntax-only check enables extensions and unsafe contstructs '
47+
'which would otherwise be forbidden. Using this option removes '
48+
'all guarantees of portability to other yaml implementations. '
49+
'Implies --allow-multiple-documents'
50+
),
2451
)
2552
parser.add_argument('filenames', nargs='*', help='Yaml filenames to check.')
2653
args = parser.parse_args(argv)
2754

55+
load_fn = LOAD_FNS[Key(multi=args.multi, unsafe=args.unsafe)]
56+
2857
retval = 0
2958
for filename in args.filenames:
3059
try:
31-
args.yaml_load_fn(open(filename), Loader=Loader)
60+
load_fn(open(filename), Loader=Loader)
3261
except yaml.YAMLError as exc:
3362
print(exc)
3463
retval = 1

tests/check_yaml_test.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_check_yaml_allow_multiple_documents(tmpdir):
2222
f = tmpdir.join('test.yaml')
2323
f.write('---\nfoo\n---\nbar\n')
2424

25-
# should failw without the setting
25+
# should fail without the setting
2626
assert check_yaml((f.strpath,))
2727

2828
# should pass when we allow multiple documents
@@ -33,3 +33,22 @@ def test_fails_even_with_allow_multiple_documents(tmpdir):
3333
f = tmpdir.join('test.yaml')
3434
f.write('[')
3535
assert check_yaml(('--allow-multiple-documents', f.strpath))
36+
37+
38+
def test_check_yaml_unsafe(tmpdir):
39+
f = tmpdir.join('test.yaml')
40+
f.write(
41+
'some_foo: !vault |\n'
42+
' $ANSIBLE_VAULT;1.1;AES256\n'
43+
' deadbeefdeadbeefdeadbeef\n',
44+
)
45+
# should fail "safe" check
46+
assert check_yaml((f.strpath,))
47+
# should pass when we allow unsafe documents
48+
assert not check_yaml(('--unsafe', f.strpath))
49+
50+
51+
def test_check_yaml_unsafe_still_fails_on_syntax_errors(tmpdir):
52+
f = tmpdir.join('test.yaml')
53+
f.write('[')
54+
assert check_yaml(('--unsafe', f.strpath))

0 commit comments

Comments
 (0)