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.
Prevent yamllint crash upon unescaped (embedded) non-printable
characters:
$ printf 'key: val\000ue\n' | yamllint -
…
yaml.reader.ReaderError: unacceptable character #x0000: special characters are not allowed
in "<unicode string>", position 8
PyYAML raises a ReaderError for control characters such as NUL or DEL.
It is a YAMLError but, unlike the parser/scanner errors yamllint already
handles, not a MarkedYAMLError, so it escaped get_syntax_error() and
crashed the whole run. The same input also broke the token generator,
since BaseLoader() itself raises the error before any token is produced.
Catch ReaderError in get_syntax_error() and derive its line/column from
the flat buffer position, and tolerate it in token_or_comment_generator()
the same way ScannerError is, so cosmetic rules still run on the
printable lines. Such input is now reported as a regular syntax error.
To follow Git's implementation, use `GitIgnoreSpec.from_lines(…)`. The
change for using this is Git allows including files from excluded
directories which directly contradicts the gitignore docs.
Thanks to Wong Hoi Sing Edison for the initial proposal.
Fixes https://github.com/adrienverge/yamllint/issues/800.
Python 3.9 is officially "end-of-life" since 2025-10-31.
Note: Python 3.14 is officially supported since commit 823a96e "CI: Test
more versions of Python".
Commit e3d54cc was missing a reference to the new `consistent`
functionality in `quote-type`.
Thanks to @kleinschrader in adrienverge/yamllint#776 for noticing this.
Strings in a document may be single or double, but must be consistent.
The first string found is assumed to be the canonical quote type, and
any subsequent quotes will be compared to it.
Closes: adrienverge/yamllint#763
This reverts commit 0cb7b0d.
Most if not all build backends pick up files with standard names by
default, especially `LICEN[CS]E*`. That's the case with setuptools:
https://setuptools.pypa.io/en/latest/userguide/miscellaneous.html
No need to explicitly specify licence files, implicit is fine.
In the current version, the error message states `TypeError: 'NoneType' object
is not iterable` when the 'rules' in the config file is not a dict (gh-274.) It
would be helpful to improve the error message.
Additionally, it is for consistency, as other elements (`ignore`, `locale`,
etc.) have similar error checks.
On double-quoted multiline strings, quotes aren't needed if lines are
broken on spaces, e.g.:
multiline:
"this is a sentence
cut into words"
But quotes are needed when at least one line ends with a backslash
character (`\`), meaning that the next spaces should be removed:
multiline:
"https://example.com/a/very/very\
/very/very/long/URL"
This commit fixes that.
Fixes https://github.com/adrienverge/yamllint/issues/275
Some of the functions in the test package are automatically run by test
frameworks and some functions in the test package are not. How do test
frameworks determine which functions should get run automatically? The
answer to that question depends on what test framework you are using.
Python’s built-in unittest framework uses the unittest.TestCase class to
figure out which which function should get run automatically. You have
to put your functions in subclasses or instances of the
unittest.TestCase class or else unittest won’t automatically run your
code [1].
The pytest framework works differently. By default, pytest will still
look for unittest.TestCase subclasses and instances, but it will also
run functions with names that begin with “test” even if those functions
aren’t inside any classes or instances [2].
When I had first written the test_codec_built_in_equivalent() function,
I had only tested it with the unittest framework. The unittest framework
does not run that function automatically because it’s not inside a
unittest.TestCase subclass or instance. The pytest framework, on the
other hand, will try to run test_codec_built_in_equivalent()
automatically because it’s name starts with “test”.
test_codec_built_in_equivalent() has one mandatory parameter, but pytest
doesn’t know what value to use for that parameter, so pytest will fail
to run that function.
This change prevents pytest from failing to run that function by
renaming it to built_in_equivalent_of_test_codec(). The function was
never supposed to be run automatically anyway.
Fixes#734.
[1]: <https://docs.python.org/3/library/unittest.html#organizing-test-code>
[2]: <https://docs.pytest.org/en/stable/explanation/goodpractices.html#conventions-for-python-test-discovery>
This fixes a problem in the custom versions `v1.37.0.devN` built for
publishing on TestPyPI since commit 325fafa "Publish each master commit
with a unique version on TestPyPI".
Such versions are constructed by suffixing `.devN`, where `N` is the
number of commits since last tags. In the `N = 0` case, we need to add
`--long` to `git describe --tags`. Otherwise it yields `v1.37.0` instead
of `v1.37.0-0-gbe92e15`, and the CI fails, e.g. on
https://github.com/adrienverge/yamllint/actions/runs/14017589005/job/39245225221
packaging.version.InvalidVersion: Invalid version: '1.37.0.devv1.37.0'
The previous few commits have removed all calls to open() that use its
default encoding. That being said, it’s still possible that code added
in the future will contain that same mistake. This commit makes it so
that the CI test job will fail if that mistake is made again.
Unfortunately, it doesn’t look like coverage.py allows you to specify -X
options [1] or warning filters [2] when running your tests [3]. To work
around this problem, I’m running all of the Python code, including
coverage.py itself, with -X warn_default_encoding and
-W error::EncodingWarning. As a result, the CI test job will also fail
if coverage.py uses open()’s default encoding. Hopefully, coverage.py
won’t do that. If it does, then we can always temporarily revert this
commit.
[1]: <https://docs.python.org/3.12/using/cmdline.html#cmdoption-X>
[2]: <https://docs.python.org/3.12/using/cmdline.html#cmdoption-W>
[3]: <https://coverage.readthedocs.io/en/7.4.0/cmd.html#execution-coverage-run>
In general, using open()’s default encoding is a mistake [1]. This
change makes sure that every time open() is called, the encoding
parameter is specified. Specifically, it makes it so that all tests
succeed when run like this:
python -X warn_default_encoding -W error::EncodingWarning -m unittest discover
[1]: <https://peps.python.org/pep-0597/#using-the-default-encoding-is-a-common-mistake>
Before this change, yamllint would decode files on the ignore-from-file
list using open()’s default encoding [1][2]. This can cause decoding to
fail in some situations (see the previous commit message for details).
This change makes yamllint automatically detect the encoding for files
on the ignore-from-file list. It uses the same algorithm that it uses
for detecting the encoding of YAML files, so the same limitations apply:
files must use UTF-8, UTF-16 or UTF-32 and they must begin with either a
byte order mark or an ASCII character.
[1]: <https://docs.python.org/3.12/library/fileinput.html#fileinput.input>
[2]: <https://docs.python.org/3.12/library/fileinput.html#fileinput.FileInput>
Before this change, yamllint would use a character encoding
autodetection algorithm in order to determine the character encoding of
all YAML files that it processed, unless the YAML file was sent to
yamllint via stdin. This change makes it so that yamllint always uses
the character encoding detection algorithm, even if the YAML file is
sent to yamllint via stdin.
Before this change, one of yamllint’s tests would replace sys.stdin with
a StringIO object. This change makes it so that that test replaces
sys.stdin with a file object instead of a StringIO object. Before this
change, it was OK to use a StringIO object because yamllint never tried
to access sys.stdin.buffer. It’s no longer OK to use a StringIO because
yamllint now tries to access sys.stdin.buffer. File objects do have a
buffer attribute, so we can use a file object instead.