truthy: Don't carry %YAML version into the next document

A `%YAML` directive applies only to the document it introduces, but the
rule only reset its cached spec version on a `...` DocumentEndToken. When
documents are separated by `---` alone (no `...`), the version of the
previous document leaked into the next one, which has no directive of its
own and should be treated as YAML 1.1:

    %YAML 1.2
    ---
    on: 1
    ---
    on: 2

The second `on` is a YAML 1.1 truthy value and should be flagged, but the
leaked 1.2 version suppressed it.

Reset the cached version when a `---` marker starts a document that has no
directive of its own (a directive always precedes the marker), so every
document is linted against its own spec version.
This commit is contained in:
Sarath Francis
2026-06-26 09:14:18 +02:00
committed by Adrien Vergé
parent 122853fd37
commit 754ccb9992
2 changed files with 22 additions and 0 deletions
+13
View File
@@ -186,6 +186,19 @@ class TruthyTestCase(RuleTestCase):
'boolean6: !!bool NO\n',
conf)
def test_explicit_yaml_version_does_not_leak_to_next_document(self):
conf = ('truthy: enable\n'
'document-start: disable\n')
# A %YAML directive only applies to the document it introduces. A
# following directive-less document (separated by '---', without
# '...') must be linted as YAML 1.1, where 'on' is truthy.
self.check('%YAML 1.2\n'
'---\n'
'on: 1\n'
'---\n'
'on: 2\n',
conf, problem1=(5, 1))
def test_check_keys_disabled(self):
conf = ('truthy:\n'
' allowed-values: []\n'
+9
View File
@@ -168,6 +168,15 @@ def yaml_spec_version_for_document(context):
def check(conf, token, prev, next, nextnext, context):
if isinstance(token, yaml.tokens.DirectiveToken) and token.name == 'YAML':
context['yaml_spec_version'] = token.value
elif isinstance(token, yaml.tokens.DocumentStartToken):
# A new document starts with this '---' marker. Its spec version is
# set by a directive, which always precedes the marker, so only forget
# the previous document's version when this document has no directive
# of its own -- otherwise the version would leak into a directive-less
# document separated by '---' (no '...' DocumentEndToken to reset it).
if not isinstance(prev, yaml.tokens.DirectiveToken):
context.pop('yaml_spec_version', None)
context.pop('bad_truthy_values', None)
elif isinstance(token, yaml.tokens.DocumentEndToken):
context.pop('yaml_spec_version', None)
context.pop('bad_truthy_values', None)