Compare commits
	
		
			1 Commits 
		
	
	
		
			master
			...
			proto/fix-
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								 | 
						5cad95ba4b | 10 years ago | 
@ -1,4 +0,0 @@
 | 
			
		||||
[flake8]
 | 
			
		||||
import-order-style = pep8
 | 
			
		||||
application-import-names = yamllint
 | 
			
		||||
ignore = W503,W504
 | 
			
		||||
@ -1,61 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
name: CI
 | 
			
		||||
 | 
			
		||||
on:  # yamllint disable-line rule:truthy
 | 
			
		||||
  push:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches:
 | 
			
		||||
      - master
 | 
			
		||||
 | 
			
		||||
permissions:
 | 
			
		||||
  contents: read
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  lint:
 | 
			
		||||
    name: Linters
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
      - name: Set up Python
 | 
			
		||||
        uses: actions/setup-python@v4
 | 
			
		||||
      - run:
 | 
			
		||||
          pip install flake8 flake8-import-order sphinx rstcheck[sphinx] doc8
 | 
			
		||||
      - run: pip install .
 | 
			
		||||
      - run: flake8 .
 | 
			
		||||
      - run: doc8 $(git ls-files '*.rst')
 | 
			
		||||
      - run: rstcheck --ignore-directives automodule $(git ls-files '*.rst')
 | 
			
		||||
      - run: yamllint --strict $(git ls-files '*.yaml' '*.yml')
 | 
			
		||||
      - run: make -C docs html
 | 
			
		||||
      - name: Check for broken links in documentation
 | 
			
		||||
        run: make -C docs linkcheck
 | 
			
		||||
 | 
			
		||||
  test:
 | 
			
		||||
    name: Tests
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        python-version:
 | 
			
		||||
          - '3.7'
 | 
			
		||||
          - '3.8'
 | 
			
		||||
          - '3.9'
 | 
			
		||||
          - '3.10'
 | 
			
		||||
          - '3.11'
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
      - name: Set up Python ${{ matrix.python-version }}
 | 
			
		||||
        uses: actions/setup-python@v4
 | 
			
		||||
        with:
 | 
			
		||||
          python-version: ${{ matrix.python-version }}
 | 
			
		||||
      - name: Append GitHub Actions system path
 | 
			
		||||
        run: echo "$HOME/.local/bin" >> $GITHUB_PATH
 | 
			
		||||
      - run: pip install coverage
 | 
			
		||||
      - run: pip install .
 | 
			
		||||
      # https://github.com/AndreMiras/coveralls-python-action/issues/18
 | 
			
		||||
      - run: echo -e "[run]\nrelative_files = True" > .coveragerc
 | 
			
		||||
      - run: coverage run -m unittest discover
 | 
			
		||||
      - name: Coveralls
 | 
			
		||||
        uses: AndreMiras/coveralls-python-action@develop
 | 
			
		||||
@ -1,11 +0,0 @@
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# For use with pre-commit.
 | 
			
		||||
# See usage instructions at https://pre-commit.com
 | 
			
		||||
 | 
			
		||||
- id: yamllint
 | 
			
		||||
  name: yamllint
 | 
			
		||||
  description: This hook runs yamllint.
 | 
			
		||||
  entry: yamllint
 | 
			
		||||
  language: python
 | 
			
		||||
  types: [file, yaml]
 | 
			
		||||
@ -0,0 +1,17 @@
 | 
			
		||||
---
 | 
			
		||||
language: python
 | 
			
		||||
python:
 | 
			
		||||
  - 2.7
 | 
			
		||||
  - 3.3
 | 
			
		||||
  - 3.4
 | 
			
		||||
  - 3.5
 | 
			
		||||
  - nightly
 | 
			
		||||
install:
 | 
			
		||||
  - pip install pyyaml flake8 coveralls
 | 
			
		||||
  - pip install .
 | 
			
		||||
script:
 | 
			
		||||
  - flake8 .
 | 
			
		||||
  - yamllint $(git ls-files '*.yaml' '*.yml')
 | 
			
		||||
  - coverage run --source=yamllint setup.py test
 | 
			
		||||
after_success:
 | 
			
		||||
  coveralls
 | 
			
		||||
@ -1,279 +0,0 @@
 | 
			
		||||
Changelog
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
1.32.0 (2023-05-22)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Look for configuration file in parent directories
 | 
			
		||||
- Rule ``anchors``: add new option ``forbid-unused-anchors``
 | 
			
		||||
 | 
			
		||||
1.31.0 (2023-04-21)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Build: migrate from ``setup.py`` to ``pyproject.toml``
 | 
			
		||||
- Docs: update some outdated URLs
 | 
			
		||||
- Rule ``colons``: prevent error when space before is mandatory
 | 
			
		||||
 | 
			
		||||
1.30.0 (2023-03-22)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Rule ``anchors``: add new rule to detect undeclared or duplicated anchors
 | 
			
		||||
- Python API: prevent using ``is_file_ignored()`` with null ``filepath``
 | 
			
		||||
- Docs: fix misleading Python API example
 | 
			
		||||
- Docs: fix plain text code snippet example
 | 
			
		||||
- Docs: update pre-commit hook example
 | 
			
		||||
 | 
			
		||||
1.29.0 (2023-01-10)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add support for Python 3.11, drop support for Python 3.6
 | 
			
		||||
- Rule ``float-values``: fix bug on strings containing fordidden values
 | 
			
		||||
- Stop releasing universal wheels
 | 
			
		||||
- Use proper Python 3 I/O type for file reading
 | 
			
		||||
- Rule ``indentation``: fix ``indent-sequences`` in nested collections
 | 
			
		||||
- Docs: clarify ``disable-line`` and parser errors, give a workaround
 | 
			
		||||
- Refactors to apply some pyupgrade suggestions
 | 
			
		||||
- Allow using a list of strings in ``ignore`` configuration
 | 
			
		||||
- Add ``--list-files`` command line option
 | 
			
		||||
 | 
			
		||||
1.28.0 (2022-09-12)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Better compress PNG image in documentation
 | 
			
		||||
- Remove ``__future__`` imports specific to Python 2
 | 
			
		||||
- Remove inheritance from ``object`` specific to Python 2
 | 
			
		||||
- Simplify GitHub Actions example in documentation
 | 
			
		||||
- Update ALE vim plugin link in documentation
 | 
			
		||||
- Update license to latest version of GPLv3
 | 
			
		||||
- Pre-compile disable/enable rules regexes
 | 
			
		||||
- Rule ``quoted-strings``: add ``allow-quoted-quotes`` option
 | 
			
		||||
- Add option ``ignore-from-file`` in config
 | 
			
		||||
 | 
			
		||||
1.27.1 (2022-07-08)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix failing test on ``key-duplicates`` for old PyYAML versions
 | 
			
		||||
 | 
			
		||||
1.27.0 (2022-07-08)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add support for Python 3.10, drop Python 3.5
 | 
			
		||||
- Fix GitHub Actions workflow
 | 
			
		||||
- Refactor ``--format=auto`` logic
 | 
			
		||||
- Update GitHub format output to use groups
 | 
			
		||||
- Rule ``comments``: allow whitespace after the shebang marker
 | 
			
		||||
- Multiple minor fixes in documentation
 | 
			
		||||
- Configure Sphinx to make man page show up in apropos
 | 
			
		||||
- Attempt to clarify configuration file location in documentation
 | 
			
		||||
- Rule ``key-duplicates``: don't crash on redundant closing brackets or braces
 | 
			
		||||
- Use ``rstcheck`` to lint documentation on the CI
 | 
			
		||||
- Remove UTF-8 headers in Python files, since Python 2 isn't supported
 | 
			
		||||
- Add various tests to increase coverage
 | 
			
		||||
- Rule ``octal-values``: pre-compile regex for performance
 | 
			
		||||
- Add sections for Visual Studio Code and IntelliJ in documentation
 | 
			
		||||
- Rule ``new-lines``: add the ``type: platform`` config option
 | 
			
		||||
- Add the new rule ``float-values``
 | 
			
		||||
 | 
			
		||||
1.26.3 (2021-08-21)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Restore runtime dependency ``setuptools`` for Python < 3.8
 | 
			
		||||
 | 
			
		||||
1.26.2 (2021-08-03)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix ``python_requires`` to comply with PEP 345 and PEP 440
 | 
			
		||||
 | 
			
		||||
1.26.1 (2021-04-06)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Remove runtime dependency ``setuptools`` for Python < 3.8
 | 
			
		||||
- Fix ``line_length`` to skip all hash signs starting comment
 | 
			
		||||
 | 
			
		||||
1.26.0 (2021-01-29)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- End support for Python 2 and Python 3.4, add support for Python 3.9
 | 
			
		||||
- Add ``forbid: non-empty`` option to ``braces`` and ``brackets`` rules
 | 
			
		||||
- Fix ``quoted-strings`` for explicit octal recognition
 | 
			
		||||
- Add documentation for integration with Arcanist
 | 
			
		||||
- Fix typos in changelog and README
 | 
			
		||||
- Stop using deprecated ``python setup.py test`` in tests
 | 
			
		||||
 | 
			
		||||
1.25.0 (2020-09-29)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Run tests on Travis both with and without UTF-8 locales
 | 
			
		||||
- Improve documentation with default values to rules with options
 | 
			
		||||
- Improve documentation with a Python API usage example
 | 
			
		||||
- Fix documentation on ``commas`` examples
 | 
			
		||||
- Packaging: move setuptools' configuration from ``setup.py`` to ``setup.cfg``
 | 
			
		||||
- Packaging: add extra info in PyPI metadata
 | 
			
		||||
- Improve documentation on ``yaml-files``
 | 
			
		||||
- Fix ``octal-values`` to prevent detection of ``8`` and ``9`` as octal values
 | 
			
		||||
- Fix ``quoted-strings`` Fix detecting strings with hashtag as requiring quotes
 | 
			
		||||
- Add ``forbid`` configuration to the ``braces`` and ``brackets`` rules
 | 
			
		||||
- Fix runtime dependencies missing ``setuptools``
 | 
			
		||||
- Add a new output format for GitHub Annotations (``--format github``)
 | 
			
		||||
- Fix DOS lines messing with rule IDs in directives
 | 
			
		||||
 | 
			
		||||
1.24.2 (2020-07-16)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add ``locale`` config option and make ``key-ordering`` locale-aware
 | 
			
		||||
 | 
			
		||||
1.24.1 (2020-07-15)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Revert ``locale`` config option from version 1.24.0 because of a bug
 | 
			
		||||
 | 
			
		||||
1.24.0 (2020-07-15)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Specify config with environment variable ``YAMLLINT_CONFIG_FILE``
 | 
			
		||||
- Fix bug with CRLF in ``new-lines`` and ``require-starting-space``
 | 
			
		||||
- Do not run linter on directories whose names look like YAML files
 | 
			
		||||
- Add ``locale`` config option and make ``key-ordering`` locale-aware
 | 
			
		||||
 | 
			
		||||
1.23.0 (2020-04-17)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Allow rules to validate their configuration
 | 
			
		||||
- Add options ``extra-required`` and ``extra-allowed`` to ``quoted-strings``
 | 
			
		||||
 | 
			
		||||
1.22.1 (2020-04-15)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix ``quoted-strings`` rule with ``only-when-needed`` on corner cases
 | 
			
		||||
 | 
			
		||||
1.22.0 (2020-04-13)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add ``check-keys`` option to the ``truthy`` rule
 | 
			
		||||
- Fix ``quoted-strings`` rule not working on sequences items
 | 
			
		||||
- Sunset Python 2
 | 
			
		||||
 | 
			
		||||
1.21.0 (2020-03-24)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix ``new-lines`` rule on Python 3 with DOS line endings
 | 
			
		||||
- Fix ``quoted-strings`` rule not working for string values matching scalars
 | 
			
		||||
- Add ``required: only-when-needed`` option to the ``quoted-strings`` rule
 | 
			
		||||
 | 
			
		||||
1.20.0 (2019-12-26)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add --no-warnings option to suppress warning messages
 | 
			
		||||
- Use 'syntax' as rule name upon syntax errors
 | 
			
		||||
 | 
			
		||||
1.19.0 (2019-11-19)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Allow disabling all checks for a file with ``# yamllint disable-file``
 | 
			
		||||
 | 
			
		||||
1.18.0 (2019-10-15)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Lint ``.yamllint`` config file by default
 | 
			
		||||
- Also read config from ``.yamllint.yml`` and ``.yamllint.yaml``
 | 
			
		||||
- Improve documentation for ``yaml-files``
 | 
			
		||||
- Update documentation for ``pre-commit``
 | 
			
		||||
- Explicitly disable ``empty-values`` and ``octal-values`` rules
 | 
			
		||||
 | 
			
		||||
1.17.0 (2019-08-12)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Simplify installation instructions in the README
 | 
			
		||||
- Add OpenBSD installation instructions
 | 
			
		||||
- Make YAML file extensions configurable
 | 
			
		||||
 | 
			
		||||
1.16.0 (2019-06-07)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add FreeBSD installation instructions
 | 
			
		||||
- Fix the ``line`` rule to correctly handle DOS new lines
 | 
			
		||||
- Add the ``allowed-values`` option to the ``truthy`` rule
 | 
			
		||||
- Allow configuration options to be a list of enums
 | 
			
		||||
 | 
			
		||||
1.15.0 (2019-02-11)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Allow linting from standard input with ``yamllint -``
 | 
			
		||||
 | 
			
		||||
1.14.0 (2019-01-14)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix documentation code snippets
 | 
			
		||||
- Drop Python 2.6 and 3.3 support, add Python 3.7 support
 | 
			
		||||
- Update documentation and tests for ``line-length`` + Unicode + Python 2
 | 
			
		||||
- Allow rule configurations to lack options
 | 
			
		||||
- Add a new ``ignore-shebangs`` option for the ``comments`` rule
 | 
			
		||||
 | 
			
		||||
1.13.0 (2018-11-14)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Use ``isinstance(x, y)`` instead of ``type(x) == y``
 | 
			
		||||
- Add a new ``-f colored`` option
 | 
			
		||||
- Update documentation about colored output when run from CLI
 | 
			
		||||
 | 
			
		||||
1.12.1 (2018-10-17)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix the ``quoted-strings`` rule, broken implementation
 | 
			
		||||
- Fix missing documentation for the ``quoted-strings`` rule
 | 
			
		||||
 | 
			
		||||
1.12.0 (2018-10-04)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add a new ``quoted-strings`` rule
 | 
			
		||||
- Update installation documentation for pip, CentOS, Debian, Ubuntu, Mac OS
 | 
			
		||||
 | 
			
		||||
1.11.1 (2018-04-06)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Handle merge keys (``<<``) in the ``key-duplicates`` rule
 | 
			
		||||
- Update documentation about pre-commit
 | 
			
		||||
- Make examples for ``ignore`` rule clearer
 | 
			
		||||
- Clarify documentation on the 'truthy' rule
 | 
			
		||||
- Fix crash in parser due to a change in PyYAML > 3.12
 | 
			
		||||
 | 
			
		||||
1.11.0 (2018-02-21)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Add a new ``octal-values`` rule
 | 
			
		||||
 | 
			
		||||
1.10.0 (2017-11-05)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
- Fix colored output on Windows
 | 
			
		||||
- Check documentation compilation on continuous integration
 | 
			
		||||
- Add a new ``empty-values`` rule
 | 
			
		||||
- Make sure test files are included in dist bundle
 | 
			
		||||
- Tests: Use en_US.UTF-8 locale when C.UTF-8 not available
 | 
			
		||||
- Tests: Dynamically detect Python executable path
 | 
			
		||||
 | 
			
		||||
1.9.0 (2017-10-16)
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
- Add a new ``key-ordering`` rule
 | 
			
		||||
- Fix indentation rule for key following empty list
 | 
			
		||||
 | 
			
		||||
1.8.2 (2017-10-10)
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
- Be clearer about the ``ignore`` conf type
 | 
			
		||||
- Update pre-commit hook file
 | 
			
		||||
- Add documentation for pre-commit
 | 
			
		||||
 | 
			
		||||
1.8.1 (2017-07-04)
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
- Require pathspec >= 0.5.3
 | 
			
		||||
- Support Python 2.6
 | 
			
		||||
- Add a changelog
 | 
			
		||||
 | 
			
		||||
1.8.0 (2017-06-28)
 | 
			
		||||
------------------
 | 
			
		||||
 | 
			
		||||
- Refactor argparse with mutually_exclusive_group
 | 
			
		||||
- Add support to ignore paths in configuration
 | 
			
		||||
@ -1,48 +0,0 @@
 | 
			
		||||
Contributing
 | 
			
		||||
============
 | 
			
		||||
 | 
			
		||||
Pull requests are the best way to propose changes to the codebase.
 | 
			
		||||
Contributions are welcome, but they have to meet some criteria.
 | 
			
		||||
 | 
			
		||||
Pull Request Process
 | 
			
		||||
--------------------
 | 
			
		||||
 | 
			
		||||
1. Fork this Git repository and create your branch from ``master``.
 | 
			
		||||
 | 
			
		||||
2. Make sure the tests pass:
 | 
			
		||||
 | 
			
		||||
   .. code:: bash
 | 
			
		||||
 | 
			
		||||
    pip install --user .
 | 
			
		||||
    python -m unittest discover  # all tests...
 | 
			
		||||
    python -m unittest tests/rules/test_commas.py  # or just some tests (faster)
 | 
			
		||||
 | 
			
		||||
3. If you add code that should be tested, add tests.
 | 
			
		||||
 | 
			
		||||
4. Make sure the linters pass:
 | 
			
		||||
 | 
			
		||||
   .. code:: bash
 | 
			
		||||
 | 
			
		||||
    flake8 .
 | 
			
		||||
 | 
			
		||||
   If you added/modified documentation:
 | 
			
		||||
 | 
			
		||||
   .. code:: bash
 | 
			
		||||
 | 
			
		||||
    doc8 $(git ls-files '*.rst')
 | 
			
		||||
 | 
			
		||||
   If you touched YAML files:
 | 
			
		||||
 | 
			
		||||
   .. code:: bash
 | 
			
		||||
 | 
			
		||||
    yamllint --strict $(git ls-files '*.yaml' '*.yml')
 | 
			
		||||
 | 
			
		||||
5. If relevant, update documentation (either in ``docs`` directly or in rules
 | 
			
		||||
   files themselves).
 | 
			
		||||
 | 
			
		||||
6. Write a `good commit message
 | 
			
		||||
   <http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html>`_.
 | 
			
		||||
   If the pull request has multiple commits, each must be atomic (single
 | 
			
		||||
   irreducible change that makes sense on its own).
 | 
			
		||||
 | 
			
		||||
7. Then, open a pull request.
 | 
			
		||||
@ -0,0 +1,3 @@
 | 
			
		||||
include LICENSE
 | 
			
		||||
include README.rst
 | 
			
		||||
include docs/*
 | 
			
		||||
@ -1,136 +0,0 @@
 | 
			
		||||
Disable with comments
 | 
			
		||||
=====================
 | 
			
		||||
 | 
			
		||||
Disabling checks for a specific line
 | 
			
		||||
------------------------------------
 | 
			
		||||
 | 
			
		||||
To prevent yamllint from reporting problems for a specific line, add a
 | 
			
		||||
directive comment (``# yamllint disable-line ...``) on that line, or on the
 | 
			
		||||
line above. For instance:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # The following mapping contains the same key twice,
 | 
			
		||||
 # but I know what I'm doing:
 | 
			
		||||
 key: value 1
 | 
			
		||||
 key: value 2  # yamllint disable-line rule:key-duplicates
 | 
			
		||||
 | 
			
		||||
 - This line is waaaaaaaaaay too long but yamllint will not report anything about it.  # yamllint disable-line rule:line-length
 | 
			
		||||
   This line will be checked by yamllint.
 | 
			
		||||
 | 
			
		||||
or:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # The following mapping contains the same key twice,
 | 
			
		||||
 # but I know what I'm doing:
 | 
			
		||||
 key: value 1
 | 
			
		||||
 # yamllint disable-line rule:key-duplicates
 | 
			
		||||
 key: value 2
 | 
			
		||||
 | 
			
		||||
 # yamllint disable-line rule:line-length
 | 
			
		||||
 - This line is waaaaaaaaaay too long but yamllint will not report anything about it.
 | 
			
		||||
   This line will be checked by yamllint.
 | 
			
		||||
 | 
			
		||||
It is possible, although not recommend, to disabled **all** rules for a
 | 
			
		||||
specific line:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # yamllint disable-line
 | 
			
		||||
 -  {    all : rules ,are disabled   for this line}
 | 
			
		||||
 | 
			
		||||
You can't make yamllint ignore invalid YAML syntax on a line (which generates a
 | 
			
		||||
`syntax error`), such as when templating a YAML file with Jinja. In some cases,
 | 
			
		||||
you can workaround this by putting the templating syntax in a YAML comment. See
 | 
			
		||||
`Putting template flow control in comments`_.
 | 
			
		||||
 | 
			
		||||
If you need to disable multiple rules, it is allowed to chain rules like this:
 | 
			
		||||
``# yamllint disable-line rule:hyphens rule:commas rule:indentation``.
 | 
			
		||||
 | 
			
		||||
Disabling checks for all (or part of) the file
 | 
			
		||||
----------------------------------------------
 | 
			
		||||
 | 
			
		||||
To prevent yamllint from reporting problems for the whole file, or for a block
 | 
			
		||||
of lines within the file, use ``# yamllint disable ...`` and ``# yamllint
 | 
			
		||||
enable ...`` directive comments. For instance:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # yamllint disable rule:colons
 | 
			
		||||
 - Lorem       : ipsum
 | 
			
		||||
   dolor       : sit amet,
 | 
			
		||||
   consectetur : adipiscing elit
 | 
			
		||||
 # yamllint enable rule:colons
 | 
			
		||||
 | 
			
		||||
 - rest of the document...
 | 
			
		||||
 | 
			
		||||
It is possible, although not recommend, to disabled **all** rules:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # yamllint disable
 | 
			
		||||
 - Lorem       :
 | 
			
		||||
         ipsum:
 | 
			
		||||
           dolor : [   sit,amet]
 | 
			
		||||
 -         consectetur : adipiscing elit
 | 
			
		||||
 # yamllint enable
 | 
			
		||||
 | 
			
		||||
If you need to disable multiple rules, it is allowed to chain rules like this:
 | 
			
		||||
``# yamllint disable rule:hyphens rule:commas rule:indentation``.
 | 
			
		||||
 | 
			
		||||
Disabling all checks for a file
 | 
			
		||||
-------------------------------
 | 
			
		||||
 | 
			
		||||
To prevent yamllint from reporting problems for a specific file, add the
 | 
			
		||||
directive comment ``# yamllint disable-file`` as the first line of the file.
 | 
			
		||||
For instance:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # yamllint disable-file
 | 
			
		||||
 # The following mapping contains the same key twice, but I know what I'm doing:
 | 
			
		||||
 key: value 1
 | 
			
		||||
 key: value 2
 | 
			
		||||
 | 
			
		||||
 - This line is waaaaaaaaaay too long but yamllint will not report anything about it.
 | 
			
		||||
 | 
			
		||||
or:
 | 
			
		||||
 | 
			
		||||
.. code-block:: jinja
 | 
			
		||||
 | 
			
		||||
 # yamllint disable-file
 | 
			
		||||
 # This file is not valid YAML because it is a Jinja template
 | 
			
		||||
 {% if extra_info %}
 | 
			
		||||
 key1: value1
 | 
			
		||||
 {% endif %}
 | 
			
		||||
 key2: value2
 | 
			
		||||
 | 
			
		||||
Putting template flow control in comments
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Alternatively for templating you can wrap the template statements in comments
 | 
			
		||||
to make it a valid YAML file. As long as the templating language doesn't use
 | 
			
		||||
the same comment symbol, it should be a valid template and valid YAML (pre and
 | 
			
		||||
post-template processing).
 | 
			
		||||
 | 
			
		||||
Example of a Jinja2 code that cannot be parsed as YAML because it contains
 | 
			
		||||
invalid tokens ``{%`` and ``%}``:
 | 
			
		||||
 | 
			
		||||
.. code-block:: text
 | 
			
		||||
 | 
			
		||||
 # This file IS NOT valid YAML and will produce syntax errors
 | 
			
		||||
 {% if extra_info %}
 | 
			
		||||
 key1: value1
 | 
			
		||||
 {% endif %}
 | 
			
		||||
 key2: value2
 | 
			
		||||
 | 
			
		||||
But it can be fixed using YAML comments:
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 # This file IS valid YAML because the Jinja is in a YAML comment
 | 
			
		||||
 # {% if extra_info %}
 | 
			
		||||
 key1: value1
 | 
			
		||||
 # {% endif %}
 | 
			
		||||
 key2: value2
 | 
			
		||||
@ -1,67 +0,0 @@
 | 
			
		||||
Integration with other software
 | 
			
		||||
===============================
 | 
			
		||||
 | 
			
		||||
Integration with pre-commit
 | 
			
		||||
---------------------------
 | 
			
		||||
 | 
			
		||||
You can integrate yamllint in the `pre-commit <https://pre-commit.com/>`_ tool.
 | 
			
		||||
Here is an example, to add in your .pre-commit-config.yaml
 | 
			
		||||
 | 
			
		||||
.. code:: yaml
 | 
			
		||||
 | 
			
		||||
  ---
 | 
			
		||||
  # Update the rev variable with the release version that you want, from the yamllint repo
 | 
			
		||||
  # You can pass your custom .yamllint with args attribute.
 | 
			
		||||
  repos:
 | 
			
		||||
    - repo: https://github.com/adrienverge/yamllint.git
 | 
			
		||||
      rev: v1.29.0
 | 
			
		||||
      hooks:
 | 
			
		||||
        - id: yamllint
 | 
			
		||||
          args: [--strict, -c=/path/to/.yamllint]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Integration with GitHub Actions
 | 
			
		||||
-------------------------------
 | 
			
		||||
 | 
			
		||||
yamllint auto-detects when it's running inside of `GitHub
 | 
			
		||||
Actions <https://github.com/features/actions>`_ and automatically uses the
 | 
			
		||||
suited output format to decorate code with linting errors. You can also force
 | 
			
		||||
the GitHub Actions output with ``yamllint --format github``.
 | 
			
		||||
 | 
			
		||||
A minimal example workflow using GitHub Actions:
 | 
			
		||||
 | 
			
		||||
.. code:: yaml
 | 
			
		||||
 | 
			
		||||
   ---
 | 
			
		||||
   on: push  # yamllint disable-line rule:truthy
 | 
			
		||||
 | 
			
		||||
   jobs:
 | 
			
		||||
     lint:
 | 
			
		||||
       runs-on: ubuntu-latest
 | 
			
		||||
       steps:
 | 
			
		||||
         - uses: actions/checkout@v3
 | 
			
		||||
 | 
			
		||||
         - name: Install yamllint
 | 
			
		||||
           run: pip install yamllint
 | 
			
		||||
 | 
			
		||||
         - name: Lint YAML files
 | 
			
		||||
           run: yamllint .
 | 
			
		||||
 | 
			
		||||
Integration with Arcanist
 | 
			
		||||
-------------------------
 | 
			
		||||
 | 
			
		||||
You can configure yamllint to run on ``arc lint``. Here is an example
 | 
			
		||||
``.arclint`` file that makes use of this configuration.
 | 
			
		||||
 | 
			
		||||
.. code:: json
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    "linters": {
 | 
			
		||||
      "yamllint": {
 | 
			
		||||
        "type": "script-and-regex",
 | 
			
		||||
        "script-and-regex.script": "yamllint",
 | 
			
		||||
        "script-and-regex.regex": "/^(?P<line>\\d+):(?P<offset>\\d+) +(?P<severity>warning|error) +(?P<message>.*) +\\((?P<name>.*)\\)$/m",
 | 
			
		||||
        "include": "(\\.(yml|yaml)$)"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
											
												Binary file not shown.
											
										
									
								| 
		 Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 41 KiB  | 
@ -1,54 +0,0 @@
 | 
			
		||||
[project]
 | 
			
		||||
name = "yamllint"
 | 
			
		||||
description = "A linter for YAML files."
 | 
			
		||||
readme = {file = "README.rst", content-type = "text/x-rst"}
 | 
			
		||||
requires-python = ">=3.7"
 | 
			
		||||
license = {text = "GPL-3.0-or-later"}
 | 
			
		||||
authors = [{name = "Adrien Vergé"}]
 | 
			
		||||
keywords = ["yaml", "lint", "linter", "syntax", "checker"]
 | 
			
		||||
classifiers = [
 | 
			
		||||
    "Development Status :: 5 - Production/Stable",
 | 
			
		||||
    "Environment :: Console",
 | 
			
		||||
    "Intended Audience :: Developers",
 | 
			
		||||
    "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
 | 
			
		||||
    "Programming Language :: Python",
 | 
			
		||||
    "Topic :: Software Development",
 | 
			
		||||
    "Topic :: Software Development :: Debuggers",
 | 
			
		||||
    "Topic :: Software Development :: Quality Assurance",
 | 
			
		||||
    "Topic :: Software Development :: Testing",
 | 
			
		||||
]
 | 
			
		||||
dependencies = [
 | 
			
		||||
    "pathspec >= 0.5.3",
 | 
			
		||||
    "pyyaml",
 | 
			
		||||
]
 | 
			
		||||
dynamic = ["version"]
 | 
			
		||||
 | 
			
		||||
[project.optional-dependencies]
 | 
			
		||||
dev = [
 | 
			
		||||
    "doc8",
 | 
			
		||||
    "flake8",
 | 
			
		||||
    "flake8-import-order",
 | 
			
		||||
    "rstcheck[sphinx]",
 | 
			
		||||
    "sphinx",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[project.scripts]
 | 
			
		||||
yamllint = "yamllint.cli:run"
 | 
			
		||||
 | 
			
		||||
[project.urls]
 | 
			
		||||
homepage = "https://github.com/adrienverge/yamllint"
 | 
			
		||||
repository = "https://github.com/adrienverge/yamllint"
 | 
			
		||||
documentation = "https://yamllint.readthedocs.io"
 | 
			
		||||
 | 
			
		||||
[build-system]
 | 
			
		||||
build-backend = "setuptools.build_meta"
 | 
			
		||||
requires = ["setuptools >= 61"]
 | 
			
		||||
 | 
			
		||||
[tool.setuptools]
 | 
			
		||||
packages = ["yamllint", "yamllint.conf", "yamllint.rules"]
 | 
			
		||||
 | 
			
		||||
[tool.setuptools.package-data]
 | 
			
		||||
yamllint = ["conf/*.yaml"]
 | 
			
		||||
 | 
			
		||||
[tool.setuptools.dynamic]
 | 
			
		||||
version = {attr = "yamllint.__version__"}
 | 
			
		||||
@ -1,19 +0,0 @@
 | 
			
		||||
# Copyright (C) 2016 Adrien Vergé
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import locale
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
locale.setlocale(locale.LC_ALL, 'C')
 | 
			
		||||
@ -1,281 +0,0 @@
 | 
			
		||||
# Copyright (C) 2023 Adrien Vergé
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AnchorsTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'anchors'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = 'anchors: disable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- &f_m {k: v}\n'
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'
 | 
			
		||||
                   '---\n'  # redeclare anchors in a new document
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &y 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'    # declared in a previous document
 | 
			
		||||
                   '- *f_m\n'  # never declared
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'  # declared after
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping 1: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'block mapping 2: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &x 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_forbid_undeclared_aliases(self):
 | 
			
		||||
        conf = ('anchors:\n'
 | 
			
		||||
                '  forbid-undeclared-aliases: true\n'
 | 
			
		||||
                '  forbid-duplicated-anchors: false\n'
 | 
			
		||||
                '  forbid-unused-anchors: false\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- &f_m {k: v}\n'
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'
 | 
			
		||||
                   '---\n'  # redeclare anchors in a new document
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &y 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'    # declared in a previous document
 | 
			
		||||
                   '- *f_m\n'  # never declared
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'  # declared after
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '...\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping 1: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'block mapping 2: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &x 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf,
 | 
			
		||||
                   problem1=(9, 3),
 | 
			
		||||
                   problem2=(10, 3),
 | 
			
		||||
                   problem3=(11, 3),
 | 
			
		||||
                   problem4=(12, 3),
 | 
			
		||||
                   problem5=(13, 3),
 | 
			
		||||
                   problem6=(25, 7),
 | 
			
		||||
                   problem7=(28, 37))
 | 
			
		||||
 | 
			
		||||
    def test_forbid_duplicated_anchors(self):
 | 
			
		||||
        conf = ('anchors:\n'
 | 
			
		||||
                '  forbid-undeclared-aliases: false\n'
 | 
			
		||||
                '  forbid-duplicated-anchors: true\n'
 | 
			
		||||
                '  forbid-unused-anchors: false\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- &f_m {k: v}\n'
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'
 | 
			
		||||
                   '---\n'  # redeclare anchors in a new document
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &y 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'    # declared in a previous document
 | 
			
		||||
                   '- *f_m\n'  # never declared
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'  # declared after
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '...\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping 1: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'block mapping 2: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &x 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf,
 | 
			
		||||
                   problem1=(5, 3),
 | 
			
		||||
                   problem2=(6, 3),
 | 
			
		||||
                   problem3=(22, 18),
 | 
			
		||||
                   problem4=(28, 20))
 | 
			
		||||
 | 
			
		||||
    def test_forbid_unused_anchors(self):
 | 
			
		||||
        conf = ('anchors:\n'
 | 
			
		||||
                '  forbid-undeclared-aliases: false\n'
 | 
			
		||||
                '  forbid-duplicated-anchors: false\n'
 | 
			
		||||
                '  forbid-unused-anchors: true\n')
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- &f_m {k: v}\n'
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'
 | 
			
		||||
                   '---\n'  # redeclare anchors in a new document
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'
 | 
			
		||||
                   '- *s\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &y 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- &i 42\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &b true\n'
 | 
			
		||||
                   '- &s hello\n'
 | 
			
		||||
                   '- *b\n'
 | 
			
		||||
                   '- *i\n'    # declared in a previous document
 | 
			
		||||
                   '- *f_m\n'  # never declared
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_m\n'
 | 
			
		||||
                   '- *f_s\n'  # declared after
 | 
			
		||||
                   '- &f_s [1, 2]\n'
 | 
			
		||||
                   '...\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping: &b_m\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   'block mapping 1: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'block mapping 2: &b_m_bis\n'
 | 
			
		||||
                   '  key: value\n'
 | 
			
		||||
                   'extended:\n'
 | 
			
		||||
                   '  <<: *b_m\n'
 | 
			
		||||
                   '  foo: bar\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '{a: 1, &x b: 2, c: &x 3, *x : 4, e: *y}\n'
 | 
			
		||||
                   '...\n', conf,
 | 
			
		||||
                   problem1=(2, 3),
 | 
			
		||||
                   problem2=(7, 3),
 | 
			
		||||
                   problem3=(14, 3),
 | 
			
		||||
                   problem4=(17, 16),
 | 
			
		||||
                   problem5=(22, 18))
 | 
			
		||||
@ -1,260 +0,0 @@
 | 
			
		||||
# Copyright (C) 2017 Greg Dubicki
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmptyValuesTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'empty-values'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = ('empty-values: disable\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   ' bar:\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{a:}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: {a:}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- {a:}\n'
 | 
			
		||||
                   '- {a:, b: 2}\n'
 | 
			
		||||
                   '- {a: 1, b:}\n'
 | 
			
		||||
                   '- {a: 1, b: , }\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{a: {b: , c: {d: 4, e:}}, f:}\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_disabled(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: false,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   'bar: aaa\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_single_line(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'implicitly-null:\n', conf, problem1=(2, 17))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'implicitly-null:with-colons:in-key:\n', conf,
 | 
			
		||||
                   problem1=(2, 36))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'implicitly-null:with-colons:in-key2:\n', conf,
 | 
			
		||||
                   problem1=(2, 37))
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_all_lines(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   'bar:\n'
 | 
			
		||||
                   'foobar:\n', conf, problem1=(2, 5),
 | 
			
		||||
                   problem2=(3, 5), problem3=(4, 8))
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_explicit_end_of_document(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   '...\n', conf, problem1=(2, 5))
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_not_end_of_document(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   'bar:\n'
 | 
			
		||||
                   ' aaa\n', conf, problem1=(2, 5))
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_different_level(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   ' bar:\n'
 | 
			
		||||
                   'aaa: bbb\n', conf, problem1=(3, 6))
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_empty_flow_mapping(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: {a:}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- {a:, b: 2}\n'
 | 
			
		||||
                   '- {a: 1, b:}\n'
 | 
			
		||||
                   '- {a: 1, b: , }\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_empty_block_sequence(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   '  -\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_not_empty_or_explicit_null(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   ' bar:\n'
 | 
			
		||||
                   '  aaa\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'explicitly-null: null\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'explicitly-null:with-colons:in-key: null\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'false-null: nulL\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'empty-string: \'\'\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'nullable-boolean: false\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'nullable-int: 0\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'First occurrence: &anchor Foo\n'
 | 
			
		||||
                   'Second occurrence: *anchor\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_various_explicit_null(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'null-alias: ~\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'null-key1: {?: val}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'null-key2: {? !!null "": val}\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_block_mappings_comments(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: true,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n'
 | 
			
		||||
                'comments: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'empty:  # comment\n'
 | 
			
		||||
                   'foo:\n'
 | 
			
		||||
                   '  bar: # comment\n', conf,
 | 
			
		||||
                   problem1=(2, 7),
 | 
			
		||||
                   problem2=(4, 7))
 | 
			
		||||
 | 
			
		||||
    def test_in_flow_mappings_disabled(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: false,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: false}\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{a:}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: {a:}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- {a:}\n'
 | 
			
		||||
                   '- {a:, b: 2}\n'
 | 
			
		||||
                   '- {a: 1, b:}\n'
 | 
			
		||||
                   '- {a: 1, b: , }\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{a: {b: , c: {d: 4, e:}}, f:}\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_flow_mappings_single_line(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: false,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: true}\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{a:}\n', conf,
 | 
			
		||||
                   problem=(2, 4))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: {a:}\n', conf,
 | 
			
		||||
                   problem=(2, 9))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- {a:}\n'
 | 
			
		||||
                   '- {a:, b: 2}\n'
 | 
			
		||||
                   '- {a: 1, b:}\n'
 | 
			
		||||
                   '- {a: 1, b: , }\n', conf,
 | 
			
		||||
                   problem1=(2, 6),
 | 
			
		||||
                   problem2=(3, 6),
 | 
			
		||||
                   problem3=(4, 12),
 | 
			
		||||
                   problem4=(5, 12))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{a: {b: , c: {d: 4, e:}}, f:}\n', conf,
 | 
			
		||||
                   problem1=(2, 8),
 | 
			
		||||
                   problem2=(2, 23),
 | 
			
		||||
                   problem3=(2, 29))
 | 
			
		||||
 | 
			
		||||
    def test_in_flow_mappings_multi_line(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: false,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: true}\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: {\n'
 | 
			
		||||
                   '  a:\n'
 | 
			
		||||
                   '}\n', conf,
 | 
			
		||||
                   problem=(3, 5))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{\n'
 | 
			
		||||
                   '  a: {\n'
 | 
			
		||||
                   '    b: ,\n'
 | 
			
		||||
                   '    c: {\n'
 | 
			
		||||
                   '      d: 4,\n'
 | 
			
		||||
                   '      e:\n'
 | 
			
		||||
                   '    }\n'
 | 
			
		||||
                   '  },\n'
 | 
			
		||||
                   '  f:\n'
 | 
			
		||||
                   '}\n', conf,
 | 
			
		||||
                   problem1=(4, 7),
 | 
			
		||||
                   problem2=(7, 9),
 | 
			
		||||
                   problem3=(10, 5))
 | 
			
		||||
 | 
			
		||||
    def test_in_flow_mappings_various_explicit_null(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: false,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: true}\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{explicit-null: null}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{null-alias: ~}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'null-key1: {?: val}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'null-key2: {? !!null "": val}\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_in_flow_mappings_comments(self):
 | 
			
		||||
        conf = ('empty-values: {forbid-in-block-mappings: false,\n'
 | 
			
		||||
                '               forbid-in-flow-mappings: true}\n'
 | 
			
		||||
                'braces: disable\n'
 | 
			
		||||
                'commas: disable\n'
 | 
			
		||||
                'comments: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '{\n'
 | 
			
		||||
                   '  a: {\n'
 | 
			
		||||
                   '    b: ,  # comment\n'
 | 
			
		||||
                   '    c: {\n'
 | 
			
		||||
                   '      d: 4,  # comment\n'
 | 
			
		||||
                   '      e:  # comment\n'
 | 
			
		||||
                   '    }\n'
 | 
			
		||||
                   '  },\n'
 | 
			
		||||
                   '  f:  # comment\n'
 | 
			
		||||
                   '}\n', conf,
 | 
			
		||||
                   problem1=(4, 7),
 | 
			
		||||
                   problem2=(7, 9),
 | 
			
		||||
                   problem3=(10, 5))
 | 
			
		||||
@ -1,128 +0,0 @@
 | 
			
		||||
# Copyright (C) 2022 the yamllint contributors
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FloatValuesTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'float-values'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = 'float-values: disable\n'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 0.0\n'
 | 
			
		||||
                   '- .NaN\n'
 | 
			
		||||
                   '- .INF\n'
 | 
			
		||||
                   '- .1\n'
 | 
			
		||||
                   '- 10e-6\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
 | 
			
		||||
    def test_numeral_before_decimal(self):
 | 
			
		||||
        conf = (
 | 
			
		||||
            'float-values:\n'
 | 
			
		||||
            '  require-numeral-before-decimal: true\n'
 | 
			
		||||
            '  forbid-scientific-notation: false\n'
 | 
			
		||||
            '  forbid-nan: false\n'
 | 
			
		||||
            '  forbid-inf: false\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 0.0\n'
 | 
			
		||||
                   '- .1\n'
 | 
			
		||||
                   '- \'.1\'\n'
 | 
			
		||||
                   '- string.1\n'
 | 
			
		||||
                   '- .1string\n'
 | 
			
		||||
                   '- !custom_tag .2\n'
 | 
			
		||||
                   '- &angle1 0.0\n'
 | 
			
		||||
                   '- *angle1\n'
 | 
			
		||||
                   '- &angle2 .3\n'
 | 
			
		||||
                   '- *angle2\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(3, 3),
 | 
			
		||||
                   problem2=(10, 11))
 | 
			
		||||
 | 
			
		||||
    def test_scientific_notation(self):
 | 
			
		||||
        conf = (
 | 
			
		||||
            'float-values:\n'
 | 
			
		||||
            '  require-numeral-before-decimal: false\n'
 | 
			
		||||
            '  forbid-scientific-notation: true\n'
 | 
			
		||||
            '  forbid-nan: false\n'
 | 
			
		||||
            '  forbid-inf: false\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 10e6\n'
 | 
			
		||||
                   '- 10e-6\n'
 | 
			
		||||
                   '- 0.00001\n'
 | 
			
		||||
                   '- \'10e-6\'\n'
 | 
			
		||||
                   '- string10e-6\n'
 | 
			
		||||
                   '- 10e-6string\n'
 | 
			
		||||
                   '- !custom_tag 10e-6\n'
 | 
			
		||||
                   '- &angle1 0.000001\n'
 | 
			
		||||
                   '- *angle1\n'
 | 
			
		||||
                   '- &angle2 10e-6\n'
 | 
			
		||||
                   '- *angle2\n'
 | 
			
		||||
                   '- &angle3 10e6\n'
 | 
			
		||||
                   '- *angle3\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(2, 3),
 | 
			
		||||
                   problem2=(3, 3),
 | 
			
		||||
                   problem3=(11, 11),
 | 
			
		||||
                   problem4=(13, 11))
 | 
			
		||||
 | 
			
		||||
    def test_nan(self):
 | 
			
		||||
        conf = (
 | 
			
		||||
            'float-values:\n'
 | 
			
		||||
            '  require-numeral-before-decimal: false\n'
 | 
			
		||||
            '  forbid-scientific-notation: false\n'
 | 
			
		||||
            '  forbid-nan: true\n'
 | 
			
		||||
            '  forbid-inf: false\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- .NaN\n'
 | 
			
		||||
                   '- .NAN\n'
 | 
			
		||||
                   '- \'.NaN\'\n'
 | 
			
		||||
                   '- a.NaN\n'
 | 
			
		||||
                   '- .NaNa\n'
 | 
			
		||||
                   '- !custom_tag .NaN\n'
 | 
			
		||||
                   '- &angle .nan\n'
 | 
			
		||||
                   '- *angle\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(2, 3),
 | 
			
		||||
                   problem2=(3, 3),
 | 
			
		||||
                   problem3=(8, 10))
 | 
			
		||||
 | 
			
		||||
    def test_inf(self):
 | 
			
		||||
        conf = (
 | 
			
		||||
            'float-values:\n'
 | 
			
		||||
            '  require-numeral-before-decimal: false\n'
 | 
			
		||||
            '  forbid-scientific-notation: false\n'
 | 
			
		||||
            '  forbid-nan: false\n'
 | 
			
		||||
            '  forbid-inf: true\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- .inf\n'
 | 
			
		||||
                   '- .INF\n'
 | 
			
		||||
                   '- -.inf\n'
 | 
			
		||||
                   '- -.INF\n'
 | 
			
		||||
                   '- \'.inf\'\n'
 | 
			
		||||
                   '- ∞.infinity\n'
 | 
			
		||||
                   '- .infinity∞\n'
 | 
			
		||||
                   '- !custom_tag .inf\n'
 | 
			
		||||
                   '- &angle .inf\n'
 | 
			
		||||
                   '- *angle\n'
 | 
			
		||||
                   '- &angle -.inf\n'
 | 
			
		||||
                   '- *angle\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(2, 3),
 | 
			
		||||
                   problem2=(3, 3),
 | 
			
		||||
                   problem3=(4, 3),
 | 
			
		||||
                   problem4=(5, 3),
 | 
			
		||||
                   problem5=(10, 10),
 | 
			
		||||
                   problem6=(12, 10))
 | 
			
		||||
@ -1,149 +0,0 @@
 | 
			
		||||
# Copyright (C) 2017 Johannes F. Knauf
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import locale
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class KeyOrderingTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'key-ordering'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = 'key-ordering: disable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'block mapping:\n'
 | 
			
		||||
                   '  secondkey: a\n'
 | 
			
		||||
                   '  firstkey: b\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'flow mapping:\n'
 | 
			
		||||
                   '  {secondkey: a, firstkey: b}\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'second: before_first\n'
 | 
			
		||||
                   'at: root\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'nested but OK:\n'
 | 
			
		||||
                   '  second: {first: 1}\n'
 | 
			
		||||
                   '  third:\n'
 | 
			
		||||
                   '    second: 2\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_enabled(self):
 | 
			
		||||
        conf = 'key-ordering: enable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'block mapping:\n'
 | 
			
		||||
                   '  secondkey: a\n'
 | 
			
		||||
                   '  firstkey: b\n', conf,
 | 
			
		||||
                   problem=(4, 3))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'flow mapping:\n'
 | 
			
		||||
                   '  {secondkey: a, firstkey: b}\n', conf,
 | 
			
		||||
                   problem=(3, 18))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'second: before_first\n'
 | 
			
		||||
                   'at: root\n', conf,
 | 
			
		||||
                   problem=(3, 1))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'nested but OK:\n'
 | 
			
		||||
                   '  second: {first: 1}\n'
 | 
			
		||||
                   '  third:\n'
 | 
			
		||||
                   '    second: 2\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_word_length(self):
 | 
			
		||||
        conf = 'key-ordering: enable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'a: 1\n'
 | 
			
		||||
                   'ab: 1\n'
 | 
			
		||||
                   'abc: 1\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'a: 1\n'
 | 
			
		||||
                   'abc: 1\n'
 | 
			
		||||
                   'ab: 1\n', conf,
 | 
			
		||||
                   problem=(4, 1))
 | 
			
		||||
 | 
			
		||||
    def test_key_duplicates(self):
 | 
			
		||||
        conf = ('key-duplicates: disable\n'
 | 
			
		||||
                'key-ordering: enable')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key: 1\n'
 | 
			
		||||
                   'key: 2\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_case(self):
 | 
			
		||||
        conf = 'key-ordering: enable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'T-shirt: 1\n'
 | 
			
		||||
                   'T-shirts: 2\n'
 | 
			
		||||
                   't-shirt: 3\n'
 | 
			
		||||
                   't-shirts: 4\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'T-shirt: 1\n'
 | 
			
		||||
                   't-shirt: 2\n'
 | 
			
		||||
                   'T-shirts: 3\n'
 | 
			
		||||
                   't-shirts: 4\n', conf,
 | 
			
		||||
                   problem=(4, 1))
 | 
			
		||||
 | 
			
		||||
    def test_accents(self):
 | 
			
		||||
        conf = 'key-ordering: enable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'hair: true\n'
 | 
			
		||||
                   'hais: true\n'
 | 
			
		||||
                   'haïr: true\n'
 | 
			
		||||
                   'haïssable: true\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'haïr: true\n'
 | 
			
		||||
                   'hais: true\n', conf,
 | 
			
		||||
                   problem=(3, 1))
 | 
			
		||||
 | 
			
		||||
    def test_key_tokens_in_flow_sequences(self):
 | 
			
		||||
        conf = 'key-ordering: enable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '[\n'
 | 
			
		||||
                   '  key: value, mappings, in, flow: sequence\n'
 | 
			
		||||
                   ']\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_locale_case(self):
 | 
			
		||||
        self.addCleanup(locale.setlocale, locale.LC_ALL, (None, None))
 | 
			
		||||
        try:
 | 
			
		||||
            locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
 | 
			
		||||
        except locale.Error:  # pragma: no cover
 | 
			
		||||
            self.skipTest('locale en_US.UTF-8 not available')
 | 
			
		||||
        conf = ('key-ordering: enable')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   't-shirt: 1\n'
 | 
			
		||||
                   'T-shirt: 2\n'
 | 
			
		||||
                   't-shirts: 3\n'
 | 
			
		||||
                   'T-shirts: 4\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   't-shirt: 1\n'
 | 
			
		||||
                   't-shirts: 2\n'
 | 
			
		||||
                   'T-shirt: 3\n'
 | 
			
		||||
                   'T-shirts: 4\n', conf,
 | 
			
		||||
                   problem=(4, 1))
 | 
			
		||||
 | 
			
		||||
    def test_locale_accents(self):
 | 
			
		||||
        self.addCleanup(locale.setlocale, locale.LC_ALL, (None, None))
 | 
			
		||||
        try:
 | 
			
		||||
            locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
 | 
			
		||||
        except locale.Error:  # pragma: no cover
 | 
			
		||||
            self.skipTest('locale en_US.UTF-8 not available')
 | 
			
		||||
        conf = ('key-ordering: enable')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'hair: true\n'
 | 
			
		||||
                   'haïr: true\n'
 | 
			
		||||
                   'hais: true\n'
 | 
			
		||||
                   'haïssable: true\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'hais: true\n'
 | 
			
		||||
                   'haïr: true\n', conf,
 | 
			
		||||
                   problem=(3, 1))
 | 
			
		||||
@ -1,80 +0,0 @@
 | 
			
		||||
# Copyright (C) 2016 Adrien Vergé
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OctalValuesTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'octal-values'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = ('octal-values: disable\n'
 | 
			
		||||
                'new-line-at-end-of-file: disable\n'
 | 
			
		||||
                'document-start: disable\n')
 | 
			
		||||
        self.check('user-city: 010', conf)
 | 
			
		||||
        self.check('user-city: 0o10', conf)
 | 
			
		||||
 | 
			
		||||
    def test_implicit_octal_values(self):
 | 
			
		||||
        conf = ('octal-values:\n'
 | 
			
		||||
                '  forbid-implicit-octal: true\n'
 | 
			
		||||
                '  forbid-explicit-octal: false\n'
 | 
			
		||||
                'new-line-at-end-of-file: disable\n'
 | 
			
		||||
                'document-start: disable\n')
 | 
			
		||||
        self.check('after-tag: !custom_tag 010', conf)
 | 
			
		||||
        self.check('user-city: 010', conf, problem=(1, 15))
 | 
			
		||||
        self.check('user-city: abc', conf)
 | 
			
		||||
        self.check('user-city: 010,0571', conf)
 | 
			
		||||
        self.check("user-city: '010'", conf)
 | 
			
		||||
        self.check('user-city: "010"', conf)
 | 
			
		||||
        self.check('user-city:\n'
 | 
			
		||||
                   '  - 010', conf, problem=(2, 8))
 | 
			
		||||
        self.check('user-city: [010]', conf, problem=(1, 16))
 | 
			
		||||
        self.check('user-city: {beijing: 010}', conf, problem=(1, 25))
 | 
			
		||||
        self.check('explicit-octal: 0o10', conf)
 | 
			
		||||
        self.check('not-number: 0abc', conf)
 | 
			
		||||
        self.check('zero: 0', conf)
 | 
			
		||||
        self.check('hex-value: 0x10', conf)
 | 
			
		||||
        self.check('number-values:\n'
 | 
			
		||||
                   '  - 0.10\n'
 | 
			
		||||
                   '  - .01\n'
 | 
			
		||||
                   '  - 0e3\n', conf)
 | 
			
		||||
        self.check('with-decimal-digits: 012345678', conf)
 | 
			
		||||
        self.check('with-decimal-digits: 012345679', conf)
 | 
			
		||||
 | 
			
		||||
    def test_explicit_octal_values(self):
 | 
			
		||||
        conf = ('octal-values:\n'
 | 
			
		||||
                '  forbid-implicit-octal: false\n'
 | 
			
		||||
                '  forbid-explicit-octal: true\n'
 | 
			
		||||
                'new-line-at-end-of-file: disable\n'
 | 
			
		||||
                'document-start: disable\n')
 | 
			
		||||
        self.check('user-city: 0o10', conf, problem=(1, 16))
 | 
			
		||||
        self.check('user-city: abc', conf)
 | 
			
		||||
        self.check('user-city: 0o10,0571', conf)
 | 
			
		||||
        self.check("user-city: '0o10'", conf)
 | 
			
		||||
        self.check('user-city:\n'
 | 
			
		||||
                   '  - 0o10', conf, problem=(2, 9))
 | 
			
		||||
        self.check('user-city: [0o10]', conf, problem=(1, 17))
 | 
			
		||||
        self.check('user-city: {beijing: 0o10}', conf, problem=(1, 26))
 | 
			
		||||
        self.check('implicit-octal: 010', conf)
 | 
			
		||||
        self.check('not-number: 0oabc', conf)
 | 
			
		||||
        self.check('zero: 0', conf)
 | 
			
		||||
        self.check('hex-value: 0x10', conf)
 | 
			
		||||
        self.check('number-values:\n'
 | 
			
		||||
                   '  - 0.10\n'
 | 
			
		||||
                   '  - .01\n'
 | 
			
		||||
                   '  - 0e3\n', conf)
 | 
			
		||||
        self.check('user-city: "010"', conf)
 | 
			
		||||
        self.check('with-decimal-digits: 0o012345678', conf)
 | 
			
		||||
        self.check('with-decimal-digits: 0o012345679', conf)
 | 
			
		||||
@ -1,558 +0,0 @@
 | 
			
		||||
# Copyright (C) 2018 ClearScore
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
from yamllint import config
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QuotedTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'quoted-strings'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = 'quoted-strings: disable'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: bar\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: "bar"\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo: \'bar\'\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'bar: 123\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'bar: "123"\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_quote_type_any(self):
 | 
			
		||||
        conf = 'quoted-strings: {quote-type: any}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'                          # fails
 | 
			
		||||
                   'string2: "foo"\n'
 | 
			
		||||
                   'string3: "true"\n'
 | 
			
		||||
                   'string4: "123"\n'
 | 
			
		||||
                   'string5: \'bar\'\n'
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'                               # fails
 | 
			
		||||
                   '  - "foo"\n'
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf, problem1=(4, 10), problem2=(17, 5),
 | 
			
		||||
                   problem3=(19, 12), problem4=(20, 15))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'               # fails
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf, problem1=(9, 3))
 | 
			
		||||
 | 
			
		||||
    def test_quote_type_single(self):
 | 
			
		||||
        conf = 'quoted-strings: {quote-type: single}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'                          # fails
 | 
			
		||||
                   'string2: "foo"\n'                        # fails
 | 
			
		||||
                   'string3: "true"\n'                       # fails
 | 
			
		||||
                   'string4: "123"\n'                        # fails
 | 
			
		||||
                   'string5: \'bar\'\n'
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'                               # fails
 | 
			
		||||
                   '  - "foo"\n'                             # fails
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf, problem1=(4, 10), problem2=(5, 10), problem3=(6, 10),
 | 
			
		||||
                   problem4=(7, 10), problem5=(17, 5), problem6=(18, 5),
 | 
			
		||||
                   problem7=(19, 12), problem8=(19, 17), problem9=(20, 15),
 | 
			
		||||
                   problem10=(20, 23))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'               # fails
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf, problem1=(9, 3), problem2=(12, 3))
 | 
			
		||||
 | 
			
		||||
    def test_quote_type_double(self):
 | 
			
		||||
        conf = 'quoted-strings: {quote-type: double}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'                          # fails
 | 
			
		||||
                   'string2: "foo"\n'
 | 
			
		||||
                   'string3: "true"\n'
 | 
			
		||||
                   'string4: "123"\n'
 | 
			
		||||
                   'string5: \'bar\'\n'                      # fails
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'                               # fails
 | 
			
		||||
                   '  - "foo"\n'
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf, problem1=(4, 10), problem2=(8, 10), problem3=(17, 5),
 | 
			
		||||
                   problem4=(19, 12), problem5=(20, 15))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'               # fails
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf, problem1=(9, 3))
 | 
			
		||||
 | 
			
		||||
    def test_any_quotes_not_required(self):
 | 
			
		||||
        conf = 'quoted-strings: {quote-type: any, required: false}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'
 | 
			
		||||
                   'string2: "foo"\n'
 | 
			
		||||
                   'string3: "true"\n'
 | 
			
		||||
                   'string4: "123"\n'
 | 
			
		||||
                   'string5: \'bar\'\n'
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'                               # fails
 | 
			
		||||
                   '  - "foo"\n'
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
 | 
			
		||||
    def test_single_quotes_not_required(self):
 | 
			
		||||
        conf = 'quoted-strings: {quote-type: single, required: false}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'
 | 
			
		||||
                   'string2: "foo"\n'                        # fails
 | 
			
		||||
                   'string3: "true"\n'                       # fails
 | 
			
		||||
                   'string4: "123"\n'                        # fails
 | 
			
		||||
                   'string5: \'bar\'\n'
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'                               # fails
 | 
			
		||||
                   '  - "foo"\n'
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf, problem1=(5, 10), problem2=(6, 10), problem3=(7, 10),
 | 
			
		||||
                   problem4=(18, 5), problem5=(19, 17), problem6=(20, 23))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'            # fails
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf, problem1=(12, 3))
 | 
			
		||||
 | 
			
		||||
    def test_only_when_needed(self):
 | 
			
		||||
        conf = 'quoted-strings: {required: only-when-needed}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'
 | 
			
		||||
                   'string2: "foo"\n'                        # fails
 | 
			
		||||
                   'string3: "true"\n'
 | 
			
		||||
                   'string4: "123"\n'
 | 
			
		||||
                   'string5: \'bar\'\n'                      # fails
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'
 | 
			
		||||
                   '  - "foo"\n'                             # fails
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf, problem1=(5, 10), problem2=(8, 10), problem3=(18, 5),
 | 
			
		||||
                   problem4=(19, 17), problem5=(20, 23))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'            # fails
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf, problem1=(12, 3))
 | 
			
		||||
 | 
			
		||||
    def test_only_when_needed_single_quotes(self):
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: only-when-needed}\n')
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'boolean1: true\n'
 | 
			
		||||
                   'number1: 123\n'
 | 
			
		||||
                   'string1: foo\n'
 | 
			
		||||
                   'string2: "foo"\n'                        # fails
 | 
			
		||||
                   'string3: "true"\n'                       # fails
 | 
			
		||||
                   'string4: "123"\n'                        # fails
 | 
			
		||||
                   'string5: \'bar\'\n'                      # fails
 | 
			
		||||
                   'string6: !!str genericstring\n'
 | 
			
		||||
                   'string7: !!str 456\n'
 | 
			
		||||
                   'string8: !!str "quotedgenericstring"\n'
 | 
			
		||||
                   'binary: !!binary binstring\n'
 | 
			
		||||
                   'integer: !!int intstring\n'
 | 
			
		||||
                   'boolean2: !!bool boolstring\n'
 | 
			
		||||
                   'boolean3: !!bool "quotedboolstring"\n'
 | 
			
		||||
                   'block-seq:\n'
 | 
			
		||||
                   '  - foo\n'
 | 
			
		||||
                   '  - "foo"\n'                             # fails
 | 
			
		||||
                   'flow-seq: [foo, "foo"]\n'                # fails
 | 
			
		||||
                   'flow-map: {a: foo, b: "foo"}\n',         # fails
 | 
			
		||||
                   conf, problem1=(5, 10), problem2=(6, 10), problem3=(7, 10),
 | 
			
		||||
                   problem4=(8, 10), problem5=(18, 5), problem6=(19, 17),
 | 
			
		||||
                   problem7=(20, 23))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'multiline string 1: |\n'
 | 
			
		||||
                   '  line 1\n'
 | 
			
		||||
                   '  line 2\n'
 | 
			
		||||
                   'multiline string 2: >\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 3:\n'
 | 
			
		||||
                   '  word 1\n'
 | 
			
		||||
                   '  word 2\n'
 | 
			
		||||
                   'multiline string 4:\n'
 | 
			
		||||
                   '  "word 1\\\n'            # fails
 | 
			
		||||
                   '   word 2"\n',
 | 
			
		||||
                   conf, problem1=(12, 3))
 | 
			
		||||
 | 
			
		||||
    def test_only_when_needed_corner_cases(self):
 | 
			
		||||
        conf = 'quoted-strings: {required: only-when-needed}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- ""\n'
 | 
			
		||||
                   '- "- item"\n'
 | 
			
		||||
                   '- "key: value"\n'
 | 
			
		||||
                   '- "%H:%M:%S"\n'
 | 
			
		||||
                   '- "%wheel ALL=(ALL) NOPASSWD: ALL"\n'
 | 
			
		||||
                   '- \'"quoted"\'\n'
 | 
			
		||||
                   '- "\'foo\' == \'bar\'"\n'
 | 
			
		||||
                   '- "\'Mac\' in ansible_facts.product_name"\n'
 | 
			
		||||
                   '- \'foo # bar\'\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'k1: ""\n'
 | 
			
		||||
                   'k2: "- item"\n'
 | 
			
		||||
                   'k3: "key: value"\n'
 | 
			
		||||
                   'k4: "%H:%M:%S"\n'
 | 
			
		||||
                   'k5: "%wheel ALL=(ALL) NOPASSWD: ALL"\n'
 | 
			
		||||
                   'k6: \'"quoted"\'\n'
 | 
			
		||||
                   'k7: "\'foo\' == \'bar\'"\n'
 | 
			
		||||
                   'k8: "\'Mac\' in ansible_facts.product_name"\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- ---\n'
 | 
			
		||||
                   '- "---"\n'                     # fails
 | 
			
		||||
                   '- ----------\n'
 | 
			
		||||
                   '- "----------"\n'              # fails
 | 
			
		||||
                   '- :wq\n'
 | 
			
		||||
                   '- ":wq"\n',                    # fails
 | 
			
		||||
                   conf, problem1=(3, 3), problem2=(5, 3), problem3=(7, 3))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'k1: ---\n'
 | 
			
		||||
                   'k2: "---"\n'                   # fails
 | 
			
		||||
                   'k3: ----------\n'
 | 
			
		||||
                   'k4: "----------"\n'            # fails
 | 
			
		||||
                   'k5: :wq\n'
 | 
			
		||||
                   'k6: ":wq"\n',                  # fails
 | 
			
		||||
                   conf, problem1=(3, 5), problem2=(5, 5), problem3=(7, 5))
 | 
			
		||||
 | 
			
		||||
    def test_only_when_needed_extras(self):
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: true\n'
 | 
			
		||||
                '  extra-allowed: [^http://]\n')
 | 
			
		||||
        self.assertRaises(config.YamlLintConfigError, self.check, '', conf)
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: true\n'
 | 
			
		||||
                '  extra-required: [^http://]\n')
 | 
			
		||||
        self.assertRaises(config.YamlLintConfigError, self.check, '', conf)
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: false\n'
 | 
			
		||||
                '  extra-allowed: [^http://]\n')
 | 
			
		||||
        self.assertRaises(config.YamlLintConfigError, self.check, '', conf)
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: true\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 123\n'
 | 
			
		||||
                   '- "123"\n'
 | 
			
		||||
                   '- localhost\n'                  # fails
 | 
			
		||||
                   '- "localhost"\n'
 | 
			
		||||
                   '- http://localhost\n'           # fails
 | 
			
		||||
                   '- "http://localhost"\n'
 | 
			
		||||
                   '- ftp://localhost\n'            # fails
 | 
			
		||||
                   '- "ftp://localhost"\n',
 | 
			
		||||
                   conf, problem1=(4, 3), problem2=(6, 3), problem3=(8, 3))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: only-when-needed\n'
 | 
			
		||||
                '  extra-allowed: [^ftp://]\n'
 | 
			
		||||
                '  extra-required: [^http://]\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 123\n'
 | 
			
		||||
                   '- "123"\n'
 | 
			
		||||
                   '- localhost\n'
 | 
			
		||||
                   '- "localhost"\n'                # fails
 | 
			
		||||
                   '- http://localhost\n'           # fails
 | 
			
		||||
                   '- "http://localhost"\n'
 | 
			
		||||
                   '- ftp://localhost\n'
 | 
			
		||||
                   '- "ftp://localhost"\n',
 | 
			
		||||
                   conf, problem1=(5, 3), problem2=(6, 3))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: false\n'
 | 
			
		||||
                '  extra-required: [^http://, ^ftp://]\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 123\n'
 | 
			
		||||
                   '- "123"\n'
 | 
			
		||||
                   '- localhost\n'
 | 
			
		||||
                   '- "localhost"\n'
 | 
			
		||||
                   '- http://localhost\n'           # fails
 | 
			
		||||
                   '- "http://localhost"\n'
 | 
			
		||||
                   '- ftp://localhost\n'            # fails
 | 
			
		||||
                   '- "ftp://localhost"\n',
 | 
			
		||||
                   conf, problem1=(6, 3), problem2=(8, 3))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings:\n'
 | 
			
		||||
                '  required: only-when-needed\n'
 | 
			
		||||
                '  extra-allowed: [^ftp://, ";$", " "]\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- localhost\n'
 | 
			
		||||
                   '- "localhost"\n'                # fails
 | 
			
		||||
                   '- ftp://localhost\n'
 | 
			
		||||
                   '- "ftp://localhost"\n'
 | 
			
		||||
                   '- i=i+1\n'
 | 
			
		||||
                   '- "i=i+1"\n'                # fails
 | 
			
		||||
                   '- i=i+2;\n'
 | 
			
		||||
                   '- "i=i+2;"\n'
 | 
			
		||||
                   '- foo\n'
 | 
			
		||||
                   '- "foo"\n'                      # fails
 | 
			
		||||
                   '- foo bar\n'
 | 
			
		||||
                   '- "foo bar"\n',
 | 
			
		||||
                   conf, problem1=(3, 3), problem2=(7, 3), problem3=(11, 3))
 | 
			
		||||
 | 
			
		||||
    def test_octal_values(self):
 | 
			
		||||
        conf = 'quoted-strings: {required: true}\n'
 | 
			
		||||
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- 100\n'
 | 
			
		||||
                   '- 0100\n'
 | 
			
		||||
                   '- 0o100\n'
 | 
			
		||||
                   '- 777\n'
 | 
			
		||||
                   '- 0777\n'
 | 
			
		||||
                   '- 0o777\n'
 | 
			
		||||
                   '- 800\n'
 | 
			
		||||
                   '- 0800\n'
 | 
			
		||||
                   '- 0o800\n'
 | 
			
		||||
                   '- "0800"\n'
 | 
			
		||||
                   '- "0o800"\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(9, 3), problem2=(10, 3))
 | 
			
		||||
 | 
			
		||||
    def test_allow_quoted_quotes(self):
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: false,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo1: "[barbaz]"\n'          # fails
 | 
			
		||||
                   'foo2: "[bar\'baz]"\n',       # fails
 | 
			
		||||
                   conf, problem1=(2, 7), problem2=(3, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: false,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: true}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo1: "[barbaz]"\n'          # fails
 | 
			
		||||
                   'foo2: "[bar\'baz]"\n',
 | 
			
		||||
                   conf, problem1=(2, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: true,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo1: "[barbaz]"\n'          # fails
 | 
			
		||||
                   'foo2: "[bar\'baz]"\n',       # fails
 | 
			
		||||
                   conf, problem1=(2, 7), problem2=(3, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: true,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: true}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo1: "[barbaz]"\n'          # fails
 | 
			
		||||
                   'foo2: "[bar\'baz]"\n',
 | 
			
		||||
                   conf, problem1=(2, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: only-when-needed,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: false}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo1: "[barbaz]"\n'          # fails
 | 
			
		||||
                   'foo2: "[bar\'baz]"\n',       # fails
 | 
			
		||||
                   conf, problem1=(2, 7), problem2=(3, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: single,\n'
 | 
			
		||||
                '                 required: only-when-needed,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: true}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'foo1: "[barbaz]"\n'          # fails
 | 
			
		||||
                   'foo2: "[bar\'baz]"\n',
 | 
			
		||||
                   conf, problem1=(2, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: double,\n'
 | 
			
		||||
                '                 required: false,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: false}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"          # fails
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",       # fails
 | 
			
		||||
                   conf, problem1=(2, 7), problem2=(3, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: double,\n'
 | 
			
		||||
                '                 required: false,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: true}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"          # fails
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",
 | 
			
		||||
                   conf, problem1=(2, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: double,\n'
 | 
			
		||||
                '                 required: true,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: false}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"          # fails
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",       # fails
 | 
			
		||||
                   conf, problem1=(2, 7), problem2=(3, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: double,\n'
 | 
			
		||||
                '                 required: true,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: true}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"          # fails
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",
 | 
			
		||||
                   conf, problem1=(2, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: double,\n'
 | 
			
		||||
                '                 required: only-when-needed,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: false}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"          # fails
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",       # fails
 | 
			
		||||
                   conf, problem1=(2, 7), problem2=(3, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: double,\n'
 | 
			
		||||
                '                 required: only-when-needed,\n'
 | 
			
		||||
                '                 allow-quoted-quotes: true}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"          # fails
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",
 | 
			
		||||
                   conf, problem1=(2, 7))
 | 
			
		||||
 | 
			
		||||
        conf = ('quoted-strings: {quote-type: any}\n')
 | 
			
		||||
        self.check("---\n"
 | 
			
		||||
                   "foo1: '[barbaz]'\n"
 | 
			
		||||
                   "foo2: '[bar\"baz]'\n",
 | 
			
		||||
                   conf)
 | 
			
		||||
@ -1,145 +0,0 @@
 | 
			
		||||
# Copyright (C) 2016 Peter Ericson
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TruthyTestCase(RuleTestCase):
 | 
			
		||||
    rule_id = 'truthy'
 | 
			
		||||
 | 
			
		||||
    def test_disabled(self):
 | 
			
		||||
        conf = 'truthy: disable'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '1: True\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'True: 1\n', conf)
 | 
			
		||||
 | 
			
		||||
    def test_enabled(self):
 | 
			
		||||
        conf = 'truthy: enable\n'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '1: True\n'
 | 
			
		||||
                   'True: 1\n',
 | 
			
		||||
                   conf, problem1=(2, 4), problem2=(3, 1))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '1: "True"\n'
 | 
			
		||||
                   '"True": 1\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '[\n'
 | 
			
		||||
                   '  true, false,\n'
 | 
			
		||||
                   '  "false", "FALSE",\n'
 | 
			
		||||
                   '  "true", "True",\n'
 | 
			
		||||
                   '  True, FALSE,\n'
 | 
			
		||||
                   '  on, OFF,\n'
 | 
			
		||||
                   '  NO, Yes\n'
 | 
			
		||||
                   ']\n', conf,
 | 
			
		||||
                   problem1=(6, 3), problem2=(6, 9),
 | 
			
		||||
                   problem3=(7, 3), problem4=(7, 7),
 | 
			
		||||
                   problem5=(8, 3), problem6=(8, 7))
 | 
			
		||||
 | 
			
		||||
    def test_different_allowed_values(self):
 | 
			
		||||
        conf = ('truthy:\n'
 | 
			
		||||
                '  allowed-values: ["yes", "no"]\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key1: foo\n'
 | 
			
		||||
                   'key2: yes\n'
 | 
			
		||||
                   'key3: bar\n'
 | 
			
		||||
                   'key4: no\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key1: true\n'
 | 
			
		||||
                   'key2: Yes\n'
 | 
			
		||||
                   'key3: false\n'
 | 
			
		||||
                   'key4: no\n'
 | 
			
		||||
                   'key5: yes\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(2, 7), problem2=(3, 7),
 | 
			
		||||
                   problem3=(4, 7))
 | 
			
		||||
 | 
			
		||||
    def test_combined_allowed_values(self):
 | 
			
		||||
        conf = ('truthy:\n'
 | 
			
		||||
                '  allowed-values: ["yes", "no", "true", "false"]\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key1: foo\n'
 | 
			
		||||
                   'key2: yes\n'
 | 
			
		||||
                   'key3: bar\n'
 | 
			
		||||
                   'key4: no\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key1: true\n'
 | 
			
		||||
                   'key2: Yes\n'
 | 
			
		||||
                   'key3: false\n'
 | 
			
		||||
                   'key4: no\n'
 | 
			
		||||
                   'key5: yes\n',
 | 
			
		||||
                   conf, problem1=(3, 7))
 | 
			
		||||
 | 
			
		||||
    def test_no_allowed_values(self):
 | 
			
		||||
        conf = ('truthy:\n'
 | 
			
		||||
                '  allowed-values: []\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key1: foo\n'
 | 
			
		||||
                   'key2: bar\n', conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'key1: true\n'
 | 
			
		||||
                   'key2: yes\n'
 | 
			
		||||
                   'key3: false\n'
 | 
			
		||||
                   'key4: no\n', conf,
 | 
			
		||||
                   problem1=(2, 7), problem2=(3, 7),
 | 
			
		||||
                   problem3=(4, 7), problem4=(5, 7))
 | 
			
		||||
 | 
			
		||||
    def test_explicit_types(self):
 | 
			
		||||
        conf = 'truthy: enable\n'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'string1: !!str True\n'
 | 
			
		||||
                   'string2: !!str yes\n'
 | 
			
		||||
                   'string3: !!str off\n'
 | 
			
		||||
                   'encoded: !!binary |\n'
 | 
			
		||||
                   '           True\n'
 | 
			
		||||
                   '           OFF\n'
 | 
			
		||||
                   '           pad==\n'  # this decodes as 'N\xbb\x9e8Qii'
 | 
			
		||||
                   'boolean1: !!bool true\n'
 | 
			
		||||
                   'boolean2: !!bool "false"\n'
 | 
			
		||||
                   'boolean3: !!bool FALSE\n'
 | 
			
		||||
                   'boolean4: !!bool True\n'
 | 
			
		||||
                   'boolean5: !!bool off\n'
 | 
			
		||||
                   'boolean6: !!bool NO\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
 | 
			
		||||
    def test_check_keys_disabled(self):
 | 
			
		||||
        conf = ('truthy:\n'
 | 
			
		||||
                '  allowed-values: []\n'
 | 
			
		||||
                '  check-keys: false\n'
 | 
			
		||||
                'key-duplicates: disable\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'YES: 0\n'
 | 
			
		||||
                   'Yes: 0\n'
 | 
			
		||||
                   'yes: 0\n'
 | 
			
		||||
                   'No: 0\n'
 | 
			
		||||
                   'No: 0\n'
 | 
			
		||||
                   'no: 0\n'
 | 
			
		||||
                   'TRUE: 0\n'
 | 
			
		||||
                   'True: 0\n'
 | 
			
		||||
                   'true: 0\n'
 | 
			
		||||
                   'FALSE: 0\n'
 | 
			
		||||
                   'False: 0\n'
 | 
			
		||||
                   'false: 0\n'
 | 
			
		||||
                   'ON: 0\n'
 | 
			
		||||
                   'On: 0\n'
 | 
			
		||||
                   'on: 0\n'
 | 
			
		||||
                   'OFF: 0\n'
 | 
			
		||||
                   'Off: 0\n'
 | 
			
		||||
                   'off: 0\n'
 | 
			
		||||
                   'YES:\n'
 | 
			
		||||
                   '  Yes:\n'
 | 
			
		||||
                   '    yes:\n'
 | 
			
		||||
                   '      on: 0\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
@ -1,84 +0,0 @@
 | 
			
		||||
# Copyright (C) 2017 Adrien Vergé
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import shutil
 | 
			
		||||
import subprocess
 | 
			
		||||
import tempfile
 | 
			
		||||
import sys
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PYTHON = sys.executable or 'python'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ModuleTestCase(unittest.TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.wd = tempfile.mkdtemp(prefix='yamllint-tests-')
 | 
			
		||||
 | 
			
		||||
        # file with only one warning
 | 
			
		||||
        with open(os.path.join(self.wd, 'warn.yaml'), 'w') as f:
 | 
			
		||||
            f.write('key: value\n')
 | 
			
		||||
 | 
			
		||||
        # file in dir
 | 
			
		||||
        os.mkdir(os.path.join(self.wd, 'sub'))
 | 
			
		||||
        with open(os.path.join(self.wd, 'sub', 'nok.yaml'), 'w') as f:
 | 
			
		||||
            f.write('---\n'
 | 
			
		||||
                    'list: [  1, 1, 2, 3, 5, 8]  \n')
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        shutil.rmtree(self.wd)
 | 
			
		||||
 | 
			
		||||
    def test_run_module_no_args(self):
 | 
			
		||||
        with self.assertRaises(subprocess.CalledProcessError) as ctx:
 | 
			
		||||
            subprocess.check_output([PYTHON, '-m', 'yamllint'],
 | 
			
		||||
                                    stderr=subprocess.STDOUT)
 | 
			
		||||
        self.assertEqual(ctx.exception.returncode, 2)
 | 
			
		||||
        self.assertRegex(ctx.exception.output.decode(), r'^usage: yamllint')
 | 
			
		||||
 | 
			
		||||
    def test_run_module_on_bad_dir(self):
 | 
			
		||||
        with self.assertRaises(subprocess.CalledProcessError) as ctx:
 | 
			
		||||
            subprocess.check_output([PYTHON, '-m', 'yamllint',
 | 
			
		||||
                                     '/does/not/exist'],
 | 
			
		||||
                                    stderr=subprocess.STDOUT)
 | 
			
		||||
        self.assertRegex(ctx.exception.output.decode(),
 | 
			
		||||
                         r'No such file or directory')
 | 
			
		||||
 | 
			
		||||
    def test_run_module_on_file(self):
 | 
			
		||||
        out = subprocess.check_output(
 | 
			
		||||
            [PYTHON, '-m', 'yamllint', os.path.join(self.wd, 'warn.yaml')])
 | 
			
		||||
        lines = out.decode().splitlines()
 | 
			
		||||
        self.assertIn('/warn.yaml', lines[0])
 | 
			
		||||
        self.assertEqual('\n'.join(lines[1:]),
 | 
			
		||||
                         '  1:1       warning  missing document start "---"'
 | 
			
		||||
                         '  (document-start)\n')
 | 
			
		||||
 | 
			
		||||
    def test_run_module_on_dir(self):
 | 
			
		||||
        with self.assertRaises(subprocess.CalledProcessError) as ctx:
 | 
			
		||||
            subprocess.check_output([PYTHON, '-m', 'yamllint', self.wd])
 | 
			
		||||
        self.assertEqual(ctx.exception.returncode, 1)
 | 
			
		||||
 | 
			
		||||
        files = ctx.exception.output.decode().split('\n\n')
 | 
			
		||||
        self.assertIn(
 | 
			
		||||
            '/warn.yaml\n'
 | 
			
		||||
            '  1:1       warning  missing document start "---"'
 | 
			
		||||
            '  (document-start)',
 | 
			
		||||
            files[0])
 | 
			
		||||
        self.assertIn(
 | 
			
		||||
            '/sub/nok.yaml\n'
 | 
			
		||||
            '  2:9       error    too many spaces inside brackets'
 | 
			
		||||
            '  (brackets)\n'
 | 
			
		||||
            '  2:27      error    trailing spaces  (trailing-spaces)',
 | 
			
		||||
            files[1])
 | 
			
		||||
@ -1,432 +0,0 @@
 | 
			
		||||
# Copyright (C) 2016 Adrien Vergé
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from tests.common import RuleTestCase
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class YamllintDirectivesTestCase(RuleTestCase):
 | 
			
		||||
    conf = ('commas: disable\n'
 | 
			
		||||
            'trailing-spaces: {}\n'
 | 
			
		||||
            'colons: {max-spaces-before: 1}\n')
 | 
			
		||||
 | 
			
		||||
    def test_disable_directive(self):
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(4, 8, 'colons'),
 | 
			
		||||
                   problem3=(6, 7, 'colons'),
 | 
			
		||||
                   problem4=(6, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '# yamllint disable\n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem=(3, 18, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint enable\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(8, 7, 'colons'),
 | 
			
		||||
                   problem2=(8, 26, 'trailing-spaces'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_directive_with_rules(self):
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '# yamllint disable rule:trailing-spaces\n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(5, 8, 'colons'),
 | 
			
		||||
                   problem3=(7, 7, 'colons'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable rule:trailing-spaces\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint enable rule:trailing-spaces\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(5, 8, 'colons'),
 | 
			
		||||
                   problem2=(8, 7, 'colons'),
 | 
			
		||||
                   problem3=(8, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable rule:trailing-spaces\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint enable\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(5, 8, 'colons'),
 | 
			
		||||
                   problem2=(8, 7, 'colons'),
 | 
			
		||||
                   problem3=(8, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint enable rule:trailing-spaces\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem=(8, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable rule:colons\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '# yamllint disable rule:trailing-spaces\n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint enable rule:colons\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(4, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(9, 7, 'colons'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_line_directive(self):
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '# yamllint disable-line\n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(7, 7, 'colons'),
 | 
			
		||||
                   problem3=(7, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon  # yamllint disable-line\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(6, 7, 'colons'),
 | 
			
		||||
                   problem3=(6, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]  # yamllint disable-line\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(4, 8, 'colons'),
 | 
			
		||||
                   problem3=(6, 7, 'colons'),
 | 
			
		||||
                   problem4=(6, 26, 'trailing-spaces'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_line_directive_with_rules(self):
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable-line rule:colons\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(4, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(5, 8, 'colons'),
 | 
			
		||||
                   problem3=(7, 7, 'colons'),
 | 
			
		||||
                   problem4=(7, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces  # yamllint disable-line rule:colons  \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 55, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(4, 8, 'colons'),
 | 
			
		||||
                   problem3=(6, 7, 'colons'),
 | 
			
		||||
                   problem4=(6, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '# yamllint disable-line rule:colons\n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(7, 7, 'colons'),
 | 
			
		||||
                   problem3=(7, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon  # yamllint disable-line rule:colons\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(6, 7, 'colons'),
 | 
			
		||||
                   problem3=(6, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable-line rule:colons\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(4, 8, 'colons'),
 | 
			
		||||
                   problem3=(7, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '- trailing spaces    \n'
 | 
			
		||||
                   '- bad   : colon\n'
 | 
			
		||||
                   '- [valid , YAML]\n'
 | 
			
		||||
                   '# yamllint disable-line rule:colons rule:trailing-spaces\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n'
 | 
			
		||||
                   '- [valid , YAML]\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(4, 8, 'colons'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_directive_with_rules_and_dos_lines(self):
 | 
			
		||||
        conf = self.conf + 'new-lines: {type: dos}\n'
 | 
			
		||||
        self.check('---\r\n'
 | 
			
		||||
                   '- [valid , YAML]\r\n'
 | 
			
		||||
                   '# yamllint disable rule:trailing-spaces\r\n'
 | 
			
		||||
                   '- trailing spaces    \r\n'
 | 
			
		||||
                   '- bad   : colon\r\n'
 | 
			
		||||
                   '- [valid , YAML]\r\n'
 | 
			
		||||
                   '# yamllint enable rule:trailing-spaces\r\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \r\n'
 | 
			
		||||
                   '- [valid , YAML]\r\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(5, 8, 'colons'),
 | 
			
		||||
                   problem2=(8, 7, 'colons'),
 | 
			
		||||
                   problem3=(8, 26, 'trailing-spaces'))
 | 
			
		||||
        self.check('---\r\n'
 | 
			
		||||
                   '- [valid , YAML]\r\n'
 | 
			
		||||
                   '- trailing spaces    \r\n'
 | 
			
		||||
                   '- bad   : colon\r\n'
 | 
			
		||||
                   '- [valid , YAML]\r\n'
 | 
			
		||||
                   '# yamllint disable-line rule:colons\r\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \r\n'
 | 
			
		||||
                   '- [valid , YAML]\r\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(3, 18, 'trailing-spaces'),
 | 
			
		||||
                   problem2=(4, 8, 'colons'),
 | 
			
		||||
                   problem3=(7, 26, 'trailing-spaces'))
 | 
			
		||||
 | 
			
		||||
    def test_directive_on_last_line(self):
 | 
			
		||||
        conf = 'new-line-at-end-of-file: {}'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'no new line',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem=(2, 12, 'new-line-at-end-of-file'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '# yamllint disable\n'
 | 
			
		||||
                   'no new line',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   'no new line  # yamllint disable',
 | 
			
		||||
                   conf)
 | 
			
		||||
 | 
			
		||||
    def test_indented_directive(self):
 | 
			
		||||
        conf = 'brackets: {min-spaces-inside: 0, max-spaces-inside: 0}'
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- a: 1\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   '    c: [    x]\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem=(4, 12, 'brackets'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- a: 1\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   '    # yamllint disable-line rule:brackets\n'
 | 
			
		||||
                   '    c: [    x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
 | 
			
		||||
    def test_directive_on_itself(self):
 | 
			
		||||
        conf = ('comments: {min-spaces-from-content: 2}\n'
 | 
			
		||||
                'comments-indentation: {}\n')
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(2, 8, 'comments'),
 | 
			
		||||
                   problem2=(4, 2, 'comments-indentation'))
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '# yamllint disable\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- a: 1 # yamllint disable-line\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   '    # yamllint disable-line\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '- a: 1 # yamllint disable-line rule:comments\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   '    # yamllint disable-line rule:comments-indentation\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '# yamllint disable\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  # yamllint enable rule:comments-indentation\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem=(6, 2, 'comments-indentation'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_file_directive(self):
 | 
			
		||||
        conf = ('comments: {min-spaces-from-content: 2}\n'
 | 
			
		||||
                'comments-indentation: {}\n')
 | 
			
		||||
        self.check('# yamllint disable-file\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('#    yamllint disable-file\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('#yamllint disable-file\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('#yamllint disable-file    \n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '# yamllint disable-file\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(3, 8, 'comments'),
 | 
			
		||||
                   problem2=(5, 2, 'comments-indentation'))
 | 
			
		||||
        self.check('# yamllint disable-file: rules cannot be specified\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(3, 8, 'comments'),
 | 
			
		||||
                   problem2=(5, 2, 'comments-indentation'))
 | 
			
		||||
        self.check('AAAA yamllint disable-file\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- a: 1 # comment too close\n'
 | 
			
		||||
                   '  b:\n'
 | 
			
		||||
                   ' # wrong indentation\n'
 | 
			
		||||
                   '    c: [x]\n',
 | 
			
		||||
                   conf,
 | 
			
		||||
                   problem1=(1, 1, 'document-start'),
 | 
			
		||||
                   problem2=(3, 8, 'comments'),
 | 
			
		||||
                   problem3=(5, 2, 'comments-indentation'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_file_directive_not_at_first_position(self):
 | 
			
		||||
        self.check('# yamllint disable-file\n'
 | 
			
		||||
                   '---\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n',
 | 
			
		||||
                   self.conf)
 | 
			
		||||
        self.check('---\n'
 | 
			
		||||
                   '# yamllint disable-file\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem1=(3, 7, 'colons'),
 | 
			
		||||
                   problem2=(3, 26, 'trailing-spaces'))
 | 
			
		||||
 | 
			
		||||
    def test_disable_file_directive_with_syntax_error(self):
 | 
			
		||||
        self.check('# This file is not valid YAML (it is a Jinja template)\n'
 | 
			
		||||
                   '{% if extra_info %}\n'
 | 
			
		||||
                   'key1: value1\n'
 | 
			
		||||
                   '{% endif %}\n'
 | 
			
		||||
                   'key2: value2\n',
 | 
			
		||||
                   self.conf,
 | 
			
		||||
                   problem=(2, 2, 'syntax'))
 | 
			
		||||
        self.check('# yamllint disable-file\n'
 | 
			
		||||
                   '# This file is not valid YAML (it is a Jinja template)\n'
 | 
			
		||||
                   '{% if extra_info %}\n'
 | 
			
		||||
                   'key1: value1\n'
 | 
			
		||||
                   '{% endif %}\n'
 | 
			
		||||
                   'key2: value2\n',
 | 
			
		||||
                   self.conf)
 | 
			
		||||
 | 
			
		||||
    def test_disable_file_directive_with_dos_lines(self):
 | 
			
		||||
        self.check('# yamllint disable-file\r\n'
 | 
			
		||||
                   '---\r\n'
 | 
			
		||||
                   '- bad  : colon and spaces   \r\n',
 | 
			
		||||
                   self.conf)
 | 
			
		||||
        self.check('# yamllint disable-file\r\n'
 | 
			
		||||
                   '# This file is not valid YAML (it is a Jinja template)\r\n'
 | 
			
		||||
                   '{% if extra_info %}\r\n'
 | 
			
		||||
                   'key1: value1\r\n'
 | 
			
		||||
                   '{% endif %}\r\n'
 | 
			
		||||
                   'key2: value2\r\n',
 | 
			
		||||
                   self.conf)
 | 
			
		||||
@ -0,0 +1,50 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -euf
 | 
			
		||||
 | 
			
		||||
DIR=$(dirname "$(readlink -f $0)")
 | 
			
		||||
 | 
			
		||||
fix_one_problem_in_file() {
 | 
			
		||||
  local filename=$1
 | 
			
		||||
  local error
 | 
			
		||||
  error=$(yamllint -f parsable "$filename" | grep 'wrong indentation: expected' \
 | 
			
		||||
    | head -n 1)
 | 
			
		||||
  if [ -z "$error" ]; then
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
  local line=$(echo $error | cut -d: -f2)
 | 
			
		||||
  local expected=$(echo $error | cut -d: -f5 | sed 's/.* expected //;s/ but found.*//')
 | 
			
		||||
  local found=$(echo $error | cut -d: -f5 | sed 's/.*but found //;s/(inde.*//')
 | 
			
		||||
  "$DIR/yaml-remove-indentation" "$filename" $line $expected $found
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
reformat_yaml() {
 | 
			
		||||
  local in=$1
 | 
			
		||||
  local out=$2
 | 
			
		||||
  python -c 'import sys, yaml; yaml.dump(yaml.load(sys.stdin), sys.stdout)' <"$in" >"$out"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fix_one_file() {
 | 
			
		||||
  local filename=$1
 | 
			
		||||
  local backup=$(mktemp originalXXXXX)
 | 
			
		||||
  cp "$filename" "$backup"
 | 
			
		||||
  echo "FIXING    $file"
 | 
			
		||||
  while fix_one_problem_in_file "$filename"; do continue; done
 | 
			
		||||
  echo "CHECKING  $file"
 | 
			
		||||
  local tmp_old=$(mktemp oldXXXXX)
 | 
			
		||||
  local tmp_new=$(mktemp newXXXXX)
 | 
			
		||||
  reformat_yaml "$backup" "$tmp_old"
 | 
			
		||||
  reformat_yaml "$filename" "$tmp_new"
 | 
			
		||||
  if ! diff -q "$tmp_old" "$tmp_new" &>/dev/null; then
 | 
			
		||||
    echo "error: after reformating, the file contents is detected different."
 | 
			
		||||
    echo "diff $backup $filename"
 | 
			
		||||
    echo "diff $tmp_old $tmp_new"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  rm "$backup" "$tmp_old" "$tmp_new"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
for file in "$@"; do
 | 
			
		||||
  fix_one_file "$file"
 | 
			
		||||
done
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
file = sys.argv[1]
 | 
			
		||||
line = int(sys.argv[2]) - 1
 | 
			
		||||
indent_expected = int(sys.argv[3])
 | 
			
		||||
indent_found = int(sys.argv[4])
 | 
			
		||||
 | 
			
		||||
with open(file) as f:
 | 
			
		||||
    lines = f.readlines()
 | 
			
		||||
 | 
			
		||||
    before = lines[:line]
 | 
			
		||||
 | 
			
		||||
    is_a_list = lines[line].strip()[0] == '-'
 | 
			
		||||
 | 
			
		||||
    i = line
 | 
			
		||||
    while (i < len(lines) and
 | 
			
		||||
           (lines[i].strip() == '' or
 | 
			
		||||
            (not is_a_list and lines[i].startswith(indent_found * ' ')) or
 | 
			
		||||
            (is_a_list and (lines[i].startswith(indent_found * ' ' + '-') or
 | 
			
		||||
                            lines[i].startswith(indent_found * ' ' + ' '))))):
 | 
			
		||||
        i += 1
 | 
			
		||||
 | 
			
		||||
    contents = lines[line:i]
 | 
			
		||||
    after = lines[i:]
 | 
			
		||||
 | 
			
		||||
    new_contents = []
 | 
			
		||||
    for line in contents:
 | 
			
		||||
        if line.strip() != '':
 | 
			
		||||
            line = (indent_expected * ' ') + line[indent_found:]
 | 
			
		||||
        new_contents.append(line)
 | 
			
		||||
 | 
			
		||||
with open(file, 'w') as f:
 | 
			
		||||
    f.write(''.join(before))
 | 
			
		||||
    f.write(''.join(new_contents))
 | 
			
		||||
    f.write(''.join(after))
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
from yamllint.cli import run
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    run()
 | 
			
		||||
@ -1,174 +0,0 @@
 | 
			
		||||
# Copyright (C) 2023 Adrien Vergé
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to report duplicated anchors and aliases referencing undeclared
 | 
			
		||||
anchors.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Options
 | 
			
		||||
 | 
			
		||||
* Set ``forbid-undeclared-aliases`` to ``true`` to avoid aliases that reference
 | 
			
		||||
  an anchor that hasn't been declared (either not declared at all, or declared
 | 
			
		||||
  later in the document).
 | 
			
		||||
* Set ``forbid-duplicated-anchors`` to ``true`` to avoid duplications of a same
 | 
			
		||||
  anchor.
 | 
			
		||||
* Set ``forbid-unused-anchors`` to ``true`` to avoid anchors being declared but
 | 
			
		||||
  not used anywhere in the YAML document via alias.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Default values (when enabled)
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 rules:
 | 
			
		||||
   anchors:
 | 
			
		||||
     forbid-undeclared-aliases: true
 | 
			
		||||
     forbid-duplicated-anchors: false
 | 
			
		||||
     forbid-unused-anchors: false
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``anchors: {forbid-undeclared-aliases: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor
 | 
			
		||||
      foo: bar
 | 
			
		||||
    - *anchor
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor
 | 
			
		||||
      foo: bar
 | 
			
		||||
    - *unknown
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor
 | 
			
		||||
      foo: bar
 | 
			
		||||
    - <<: *unknown
 | 
			
		||||
      extra: value
 | 
			
		||||
 | 
			
		||||
#. With ``anchors: {forbid-duplicated-anchors: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor1 Foo Bar
 | 
			
		||||
    - &anchor2 [item 1, item 2]
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor Foo Bar
 | 
			
		||||
    - &anchor [item 1, item 2]
 | 
			
		||||
 | 
			
		||||
#. With ``anchors: {forbid-unused-anchors: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor
 | 
			
		||||
      foo: bar
 | 
			
		||||
    - *anchor
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    ---
 | 
			
		||||
    - &anchor
 | 
			
		||||
      foo: bar
 | 
			
		||||
    - items:
 | 
			
		||||
      - item1
 | 
			
		||||
      - item2
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ID = 'anchors'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
CONF = {'forbid-undeclared-aliases': bool,
 | 
			
		||||
        'forbid-duplicated-anchors': bool,
 | 
			
		||||
        'forbid-unused-anchors': bool}
 | 
			
		||||
DEFAULT = {'forbid-undeclared-aliases': True,
 | 
			
		||||
           'forbid-duplicated-anchors': False,
 | 
			
		||||
           'forbid-unused-anchors': False}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
    if (conf['forbid-undeclared-aliases'] or
 | 
			
		||||
            conf['forbid-duplicated-anchors'] or
 | 
			
		||||
            conf['forbid-unused-anchors']):
 | 
			
		||||
        if isinstance(token, (
 | 
			
		||||
                yaml.StreamStartToken,
 | 
			
		||||
                yaml.DocumentStartToken,
 | 
			
		||||
                yaml.DocumentEndToken)):
 | 
			
		||||
            context['anchors'] = {}
 | 
			
		||||
 | 
			
		||||
    if (conf['forbid-undeclared-aliases'] and
 | 
			
		||||
            isinstance(token, yaml.AliasToken) and
 | 
			
		||||
            token.value not in context['anchors']):
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1, token.start_mark.column + 1,
 | 
			
		||||
            f'found undeclared alias "{token.value}"')
 | 
			
		||||
 | 
			
		||||
    if (conf['forbid-duplicated-anchors'] and
 | 
			
		||||
            isinstance(token, yaml.AnchorToken) and
 | 
			
		||||
            token.value in context['anchors']):
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1, token.start_mark.column + 1,
 | 
			
		||||
            f'found duplicated anchor "{token.value}"')
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-unused-anchors']:
 | 
			
		||||
        # Unused anchors can only be detected at the end of Document.
 | 
			
		||||
        # End of document can be either
 | 
			
		||||
        #   - end of stream
 | 
			
		||||
        #   - end of document sign '...'
 | 
			
		||||
        #   - start of a new document sign '---'
 | 
			
		||||
        # If next token indicates end of document,
 | 
			
		||||
        # check if the anchors have been used or not.
 | 
			
		||||
        # If they haven't been used, report problem on those anchors.
 | 
			
		||||
        if isinstance(next, (yaml.StreamEndToken,
 | 
			
		||||
                             yaml.DocumentStartToken,
 | 
			
		||||
                             yaml.DocumentEndToken)):
 | 
			
		||||
            for anchor, info in context['anchors'].items():
 | 
			
		||||
                if not info['used']:
 | 
			
		||||
                    yield LintProblem(info['line'] + 1,
 | 
			
		||||
                                      info['column'] + 1,
 | 
			
		||||
                                      f'found unused anchor "{anchor}"')
 | 
			
		||||
        elif isinstance(token, yaml.AliasToken):
 | 
			
		||||
            context['anchors'].get(token.value, {})['used'] = True
 | 
			
		||||
 | 
			
		||||
    if (conf['forbid-undeclared-aliases'] or
 | 
			
		||||
            conf['forbid-duplicated-anchors'] or
 | 
			
		||||
            conf['forbid-unused-anchors']):
 | 
			
		||||
        if isinstance(token, yaml.AnchorToken):
 | 
			
		||||
            context['anchors'][token.value] = {
 | 
			
		||||
                'line': token.start_mark.line,
 | 
			
		||||
                'column': token.start_mark.column,
 | 
			
		||||
                'used': False
 | 
			
		||||
            }
 | 
			
		||||
@ -1,104 +0,0 @@
 | 
			
		||||
# Copyright (C) 2017 Greg Dubicki
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to prevent nodes with empty content, that implicitly result in
 | 
			
		||||
``null`` values.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Options
 | 
			
		||||
 | 
			
		||||
* Use ``forbid-in-block-mappings`` to prevent empty values in block mappings.
 | 
			
		||||
* Use ``forbid-in-flow-mappings`` to prevent empty values in flow mappings.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Default values (when enabled)
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 rules:
 | 
			
		||||
   empty-values:
 | 
			
		||||
     forbid-in-block-mappings: true
 | 
			
		||||
     forbid-in-flow-mappings: true
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``empty-values: {forbid-in-block-mappings: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    some-mapping:
 | 
			
		||||
      sub-element: correctly indented
 | 
			
		||||
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    explicitly-null: null
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    some-mapping:
 | 
			
		||||
    sub-element: incorrectly indented
 | 
			
		||||
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    implicitly-null:
 | 
			
		||||
 | 
			
		||||
#. With ``empty-values: {forbid-in-flow-mappings: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    {prop: null}
 | 
			
		||||
    {a: 1, b: 2, c: 3}
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    {prop: }
 | 
			
		||||
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    {a: 1, b:, c: 3}
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ID = 'empty-values'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
CONF = {'forbid-in-block-mappings': bool,
 | 
			
		||||
        'forbid-in-flow-mappings': bool}
 | 
			
		||||
DEFAULT = {'forbid-in-block-mappings': True,
 | 
			
		||||
           'forbid-in-flow-mappings': True}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-in-block-mappings']:
 | 
			
		||||
        if isinstance(token, yaml.ValueToken) and isinstance(next, (
 | 
			
		||||
                yaml.KeyToken, yaml.BlockEndToken)):
 | 
			
		||||
            yield LintProblem(token.start_mark.line + 1,
 | 
			
		||||
                              token.end_mark.column + 1,
 | 
			
		||||
                              'empty value in block mapping')
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-in-flow-mappings']:
 | 
			
		||||
        if isinstance(token, yaml.ValueToken) and isinstance(next, (
 | 
			
		||||
                yaml.FlowEntryToken, yaml.FlowMappingEndToken)):
 | 
			
		||||
            yield LintProblem(token.start_mark.line + 1,
 | 
			
		||||
                              token.end_mark.column + 1,
 | 
			
		||||
                              'empty value in flow mapping')
 | 
			
		||||
@ -1,158 +0,0 @@
 | 
			
		||||
# Copyright (C) 2022 the yamllint contributors
 | 
			
		||||
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to limit the permitted values for floating-point numbers.
 | 
			
		||||
YAML permits three classes of float expressions: approximation to real numbers,
 | 
			
		||||
positive and negative infinity and "not a number".
 | 
			
		||||
 | 
			
		||||
.. rubric:: Options
 | 
			
		||||
 | 
			
		||||
* Use ``require-numeral-before-decimal`` to require floats to start
 | 
			
		||||
  with a numeral (ex ``0.0`` instead of ``.0``).
 | 
			
		||||
* Use ``forbid-scientific-notation`` to forbid scientific notation.
 | 
			
		||||
* Use ``forbid-nan`` to forbid NaN (not a number) values.
 | 
			
		||||
* Use ``forbid-inf`` to forbid infinite values.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Default values (when enabled)
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
    rules:
 | 
			
		||||
      float-values:
 | 
			
		||||
        forbid-inf: false
 | 
			
		||||
        forbid-nan: false
 | 
			
		||||
        forbid-scientific-notation: false
 | 
			
		||||
        require-numeral-before-decimal: false
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``float-values: {require-numeral-before-decimal: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    anemometer:
 | 
			
		||||
      angle: 0.0
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    anemometer:
 | 
			
		||||
      angle: .0
 | 
			
		||||
 | 
			
		||||
#. With ``float-values: {forbid-scientific-notation: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    anemometer:
 | 
			
		||||
      angle: 0.00001
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    anemometer:
 | 
			
		||||
      angle: 10e-6
 | 
			
		||||
 | 
			
		||||
#. With ``float-values: {forbid-nan: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    anemometer:
 | 
			
		||||
      angle: .NaN
 | 
			
		||||
 | 
			
		||||
 #. With ``float-values: {forbid-inf: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    anemometer:
 | 
			
		||||
      angle: .inf
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ID = 'float-values'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
CONF = {
 | 
			
		||||
    'require-numeral-before-decimal': bool,
 | 
			
		||||
    'forbid-scientific-notation': bool,
 | 
			
		||||
    'forbid-nan': bool,
 | 
			
		||||
    'forbid-inf': bool,
 | 
			
		||||
}
 | 
			
		||||
DEFAULT = {
 | 
			
		||||
    'require-numeral-before-decimal': False,
 | 
			
		||||
    'forbid-scientific-notation': False,
 | 
			
		||||
    'forbid-nan': False,
 | 
			
		||||
    'forbid-inf': False,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IS_NUMERAL_BEFORE_DECIMAL_PATTERN = (
 | 
			
		||||
    re.compile('[-+]?(\\.[0-9]+)([eE][-+]?[0-9]+)?$')
 | 
			
		||||
)
 | 
			
		||||
IS_SCIENTIFIC_NOTATION_PATTERN = re.compile(
 | 
			
		||||
    '[-+]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)$'
 | 
			
		||||
)
 | 
			
		||||
IS_INF_PATTERN = re.compile('[-+]?(\\.inf|\\.Inf|\\.INF)$')
 | 
			
		||||
IS_NAN_PATTERN = re.compile('(\\.nan|\\.NaN|\\.NAN)$')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
    if prev and isinstance(prev, yaml.tokens.TagToken):
 | 
			
		||||
        return
 | 
			
		||||
    if not isinstance(token, yaml.tokens.ScalarToken):
 | 
			
		||||
        return
 | 
			
		||||
    if token.style:
 | 
			
		||||
        return
 | 
			
		||||
    val = token.value
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-nan'] and IS_NAN_PATTERN.match(val):
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1,
 | 
			
		||||
            token.start_mark.column + 1,
 | 
			
		||||
            f'forbidden not a number value "{token.value}"',
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-inf'] and IS_INF_PATTERN.match(val):
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1,
 | 
			
		||||
            token.start_mark.column + 1,
 | 
			
		||||
            f'forbidden infinite value "{token.value}"',
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    if conf[
 | 
			
		||||
        'forbid-scientific-notation'
 | 
			
		||||
    ] and IS_SCIENTIFIC_NOTATION_PATTERN.match(val):
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1,
 | 
			
		||||
            token.start_mark.column + 1,
 | 
			
		||||
            f'forbidden scientific notation "{token.value}"',
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    if conf[
 | 
			
		||||
        'require-numeral-before-decimal'
 | 
			
		||||
    ] and IS_NUMERAL_BEFORE_DECIMAL_PATTERN.match(val):
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1,
 | 
			
		||||
            token.start_mark.column + 1,
 | 
			
		||||
            f'forbidden decimal missing 0 prefix "{token.value}"',
 | 
			
		||||
        )
 | 
			
		||||
@ -1,127 +0,0 @@
 | 
			
		||||
# Copyright (C) 2017 Johannes F. Knauf
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to enforce alphabetical ordering of keys in mappings. The sorting
 | 
			
		||||
order uses the Unicode code point number as a default. As a result, the
 | 
			
		||||
ordering is case-sensitive and not accent-friendly (see examples below).
 | 
			
		||||
This can be changed by setting the global ``locale`` option.  This allows one
 | 
			
		||||
to sort case and accents properly.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``key-ordering: {}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - key 1: v
 | 
			
		||||
      key 2: val
 | 
			
		||||
      key 3: value
 | 
			
		||||
    - {a: 1, b: 2, c: 3}
 | 
			
		||||
    - T-shirt: 1
 | 
			
		||||
      T-shirts: 2
 | 
			
		||||
      t-shirt: 3
 | 
			
		||||
      t-shirts: 4
 | 
			
		||||
    - hair: true
 | 
			
		||||
      hais: true
 | 
			
		||||
      haïr: true
 | 
			
		||||
      haïssable: true
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - key 2: v
 | 
			
		||||
      key 1: val
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - {b: 1, a: 2}
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - T-shirt: 1
 | 
			
		||||
      t-shirt: 2
 | 
			
		||||
      T-shirts: 3
 | 
			
		||||
      t-shirts: 4
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - haïr: true
 | 
			
		||||
      hais: true
 | 
			
		||||
 | 
			
		||||
#. With global option ``locale: "en_US.UTF-8"`` and rule ``key-ordering: {}``
 | 
			
		||||
 | 
			
		||||
   as opposed to before, the following code snippet would now **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - t-shirt: 1
 | 
			
		||||
      T-shirt: 2
 | 
			
		||||
      t-shirts: 3
 | 
			
		||||
      T-shirts: 4
 | 
			
		||||
    - hair: true
 | 
			
		||||
      haïr: true
 | 
			
		||||
      hais: true
 | 
			
		||||
      haïssable: true
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from locale import strcoll
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ID = 'key-ordering'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
 | 
			
		||||
MAP, SEQ = range(2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Parent:
 | 
			
		||||
    def __init__(self, type):
 | 
			
		||||
        self.type = type
 | 
			
		||||
        self.keys = []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
    if 'stack' not in context:
 | 
			
		||||
        context['stack'] = []
 | 
			
		||||
 | 
			
		||||
    if isinstance(token, (yaml.BlockMappingStartToken,
 | 
			
		||||
                          yaml.FlowMappingStartToken)):
 | 
			
		||||
        context['stack'].append(Parent(MAP))
 | 
			
		||||
    elif isinstance(token, (yaml.BlockSequenceStartToken,
 | 
			
		||||
                            yaml.FlowSequenceStartToken)):
 | 
			
		||||
        context['stack'].append(Parent(SEQ))
 | 
			
		||||
    elif isinstance(token, (yaml.BlockEndToken,
 | 
			
		||||
                            yaml.FlowMappingEndToken,
 | 
			
		||||
                            yaml.FlowSequenceEndToken)):
 | 
			
		||||
        context['stack'].pop()
 | 
			
		||||
    elif (isinstance(token, yaml.KeyToken) and
 | 
			
		||||
          isinstance(next, yaml.ScalarToken)):
 | 
			
		||||
        # This check is done because KeyTokens can be found inside flow
 | 
			
		||||
        # sequences... strange, but allowed.
 | 
			
		||||
        if len(context['stack']) > 0 and context['stack'][-1].type == MAP:
 | 
			
		||||
            if any(strcoll(next.value, key) < 0
 | 
			
		||||
                   for key in context['stack'][-1].keys):
 | 
			
		||||
                yield LintProblem(
 | 
			
		||||
                    next.start_mark.line + 1, next.start_mark.column + 1,
 | 
			
		||||
                    'wrong ordering of key "%s" in mapping' % next.value)
 | 
			
		||||
            else:
 | 
			
		||||
                context['stack'][-1].keys.append(next.value)
 | 
			
		||||
@ -1,114 +0,0 @@
 | 
			
		||||
# Copyright (C) 2017 ScienJus
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to prevent values with octal numbers. In YAML, numbers that
 | 
			
		||||
start with ``0`` are interpreted as octal, but this is not always wanted.
 | 
			
		||||
For instance ``010`` is the city code of Beijing, and should not be
 | 
			
		||||
converted to ``8``.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Options
 | 
			
		||||
 | 
			
		||||
* Use ``forbid-implicit-octal`` to prevent numbers starting with ``0``.
 | 
			
		||||
* Use ``forbid-explicit-octal`` to prevent numbers starting with ``0o``.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Default values (when enabled)
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 rules:
 | 
			
		||||
   octal-values:
 | 
			
		||||
     forbid-implicit-octal: true
 | 
			
		||||
     forbid-explicit-octal: true
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``octal-values: {forbid-implicit-octal: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    user:
 | 
			
		||||
      city-code: '010'
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    user:
 | 
			
		||||
      city-code: 010,021
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    user:
 | 
			
		||||
      city-code: 010
 | 
			
		||||
 | 
			
		||||
#. With ``octal-values: {forbid-explicit-octal: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    user:
 | 
			
		||||
      city-code: '0o10'
 | 
			
		||||
 | 
			
		||||
   the following code snippets would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    user:
 | 
			
		||||
      city-code: 0o10
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ID = 'octal-values'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
CONF = {'forbid-implicit-octal': bool,
 | 
			
		||||
        'forbid-explicit-octal': bool}
 | 
			
		||||
DEFAULT = {'forbid-implicit-octal': True,
 | 
			
		||||
           'forbid-explicit-octal': True}
 | 
			
		||||
 | 
			
		||||
IS_OCTAL_NUMBER_PATTERN = re.compile(r'^[0-7]+$')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
    if prev and isinstance(prev, yaml.tokens.TagToken):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-implicit-octal']:
 | 
			
		||||
        if isinstance(token, yaml.tokens.ScalarToken):
 | 
			
		||||
            if not token.style:
 | 
			
		||||
                val = token.value
 | 
			
		||||
                if (val.isdigit() and len(val) > 1 and val[0] == '0' and
 | 
			
		||||
                        IS_OCTAL_NUMBER_PATTERN.match(val[1:])):
 | 
			
		||||
                    yield LintProblem(
 | 
			
		||||
                        token.start_mark.line + 1, token.end_mark.column + 1,
 | 
			
		||||
                        'forbidden implicit octal value "%s"' %
 | 
			
		||||
                        token.value)
 | 
			
		||||
 | 
			
		||||
    if conf['forbid-explicit-octal']:
 | 
			
		||||
        if isinstance(token, yaml.tokens.ScalarToken):
 | 
			
		||||
            if not token.style:
 | 
			
		||||
                val = token.value
 | 
			
		||||
                if (len(val) > 2 and val[:2] == '0o' and
 | 
			
		||||
                        IS_OCTAL_NUMBER_PATTERN.match(val[2:])):
 | 
			
		||||
                    yield LintProblem(
 | 
			
		||||
                        token.start_mark.line + 1, token.end_mark.column + 1,
 | 
			
		||||
                        'forbidden explicit octal value "%s"' %
 | 
			
		||||
                        token.value)
 | 
			
		||||
@ -1,289 +0,0 @@
 | 
			
		||||
# Copyright (C) 2018 ClearScore
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to forbid any string values that are not quoted, or to prevent
 | 
			
		||||
quoted strings without needing it. You can also enforce the type of the quote
 | 
			
		||||
used.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Options
 | 
			
		||||
 | 
			
		||||
* ``quote-type`` defines allowed quotes: ``single``, ``double`` or ``any``
 | 
			
		||||
  (default).
 | 
			
		||||
* ``required`` defines whether using quotes in string values is required
 | 
			
		||||
  (``true``, default) or not (``false``), or only allowed when really needed
 | 
			
		||||
  (``only-when-needed``).
 | 
			
		||||
* ``extra-required`` is a list of PCRE regexes to force string values to be
 | 
			
		||||
  quoted, if they match any regex. This option can only be used with
 | 
			
		||||
  ``required: false`` and  ``required: only-when-needed``.
 | 
			
		||||
* ``extra-allowed`` is a list of PCRE regexes to allow quoted string values,
 | 
			
		||||
  even if ``required: only-when-needed`` is set.
 | 
			
		||||
* ``allow-quoted-quotes`` allows (``true``) using disallowed quotes for strings
 | 
			
		||||
  with allowed quotes inside. Default ``false``.
 | 
			
		||||
 | 
			
		||||
**Note**: Multi-line strings (with ``|`` or ``>``) will not be checked.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Default values (when enabled)
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 rules:
 | 
			
		||||
   quoted-strings:
 | 
			
		||||
     quote-type: any
 | 
			
		||||
     required: true
 | 
			
		||||
     extra-required: []
 | 
			
		||||
     extra-allowed: []
 | 
			
		||||
     allow-quoted-quotes: false
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``quoted-strings: {quote-type: any, required: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: "bar"
 | 
			
		||||
    bar: 'foo'
 | 
			
		||||
    number: 123
 | 
			
		||||
    boolean: true
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: bar
 | 
			
		||||
 | 
			
		||||
#. With ``quoted-strings: {quote-type: single, required: only-when-needed}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: bar
 | 
			
		||||
    bar: foo
 | 
			
		||||
    not_number: '123'
 | 
			
		||||
    not_boolean: 'true'
 | 
			
		||||
    not_comment: '# comment'
 | 
			
		||||
    not_list: '[1, 2, 3]'
 | 
			
		||||
    not_map: '{a: 1, b: 2}'
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: 'bar'
 | 
			
		||||
 | 
			
		||||
#. With ``quoted-strings: {required: false, extra-required: [^http://,
 | 
			
		||||
   ^ftp://]}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - localhost
 | 
			
		||||
    - "localhost"
 | 
			
		||||
    - "http://localhost"
 | 
			
		||||
    - "ftp://localhost"
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - http://localhost
 | 
			
		||||
    - ftp://localhost
 | 
			
		||||
 | 
			
		||||
#. With ``quoted-strings: {required: only-when-needed, extra-allowed:
 | 
			
		||||
   [^http://, ^ftp://], extra-required: [QUOTED]}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - localhost
 | 
			
		||||
    - "http://localhost"
 | 
			
		||||
    - "ftp://localhost"
 | 
			
		||||
    - "this is a string that needs to be QUOTED"
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - "localhost"
 | 
			
		||||
    - this is a string that needs to be QUOTED
 | 
			
		||||
 | 
			
		||||
#. With ``quoted-strings: {quote-type: double, allow-quoted-quotes: false}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: "bar\\"baz"
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: 'bar"baz'
 | 
			
		||||
 | 
			
		||||
#. With ``quoted-strings: {quote-type: double, allow-quoted-quotes: true}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    foo: 'bar"baz'
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
ID = 'quoted-strings'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
CONF = {'quote-type': ('any', 'single', 'double'),
 | 
			
		||||
        'required': (True, False, 'only-when-needed'),
 | 
			
		||||
        'extra-required': [str],
 | 
			
		||||
        'extra-allowed': [str],
 | 
			
		||||
        'allow-quoted-quotes': bool}
 | 
			
		||||
DEFAULT = {'quote-type': 'any',
 | 
			
		||||
           'required': True,
 | 
			
		||||
           'extra-required': [],
 | 
			
		||||
           'extra-allowed': [],
 | 
			
		||||
           'allow-quoted-quotes': False}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def VALIDATE(conf):
 | 
			
		||||
    if conf['required'] is True and len(conf['extra-allowed']) > 0:
 | 
			
		||||
        return 'cannot use both "required: true" and "extra-allowed"'
 | 
			
		||||
    if conf['required'] is True and len(conf['extra-required']) > 0:
 | 
			
		||||
        return 'cannot use both "required: true" and "extra-required"'
 | 
			
		||||
    if conf['required'] is False and len(conf['extra-allowed']) > 0:
 | 
			
		||||
        return 'cannot use both "required: false" and "extra-allowed"'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str'
 | 
			
		||||
 | 
			
		||||
# https://stackoverflow.com/a/36514274
 | 
			
		||||
yaml.resolver.Resolver.add_implicit_resolver(
 | 
			
		||||
    'tag:yaml.org,2002:int',
 | 
			
		||||
    re.compile(r'''^(?:[-+]?0b[0-1_]+
 | 
			
		||||
               |[-+]?0o?[0-7_]+
 | 
			
		||||
               |[-+]?0[0-7_]+
 | 
			
		||||
               |[-+]?(?:0|[1-9][0-9_]*)
 | 
			
		||||
               |[-+]?0x[0-9a-fA-F_]+
 | 
			
		||||
               |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X),
 | 
			
		||||
    list('-+0123456789'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _quote_match(quote_type, token_style):
 | 
			
		||||
    return ((quote_type == 'any') or
 | 
			
		||||
            (quote_type == 'single' and token_style == "'") or
 | 
			
		||||
            (quote_type == 'double' and token_style == '"'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _quotes_are_needed(string):
 | 
			
		||||
    loader = yaml.BaseLoader('key: ' + string)
 | 
			
		||||
    # Remove the 5 first tokens corresponding to 'key: ' (StreamStartToken,
 | 
			
		||||
    # BlockMappingStartToken, KeyToken, ScalarToken(value=key), ValueToken)
 | 
			
		||||
    for _ in range(5):
 | 
			
		||||
        loader.get_token()
 | 
			
		||||
    try:
 | 
			
		||||
        a, b = loader.get_token(), loader.get_token()
 | 
			
		||||
        if (isinstance(a, yaml.ScalarToken) and a.style is None and
 | 
			
		||||
                isinstance(b, yaml.BlockEndToken) and a.value == string):
 | 
			
		||||
            return False
 | 
			
		||||
        return True
 | 
			
		||||
    except yaml.scanner.ScannerError:
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _has_quoted_quotes(token):
 | 
			
		||||
    return ((not token.plain) and
 | 
			
		||||
            ((token.style == "'" and '"' in token.value) or
 | 
			
		||||
             (token.style == '"' and "'" in token.value)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
    if not (isinstance(token, yaml.tokens.ScalarToken) and
 | 
			
		||||
            isinstance(prev, (yaml.BlockEntryToken, yaml.FlowEntryToken,
 | 
			
		||||
                              yaml.FlowSequenceStartToken, yaml.TagToken,
 | 
			
		||||
                              yaml.ValueToken))):
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Ignore explicit types, e.g. !!str testtest or !!int 42
 | 
			
		||||
    if (prev and isinstance(prev, yaml.tokens.TagToken) and
 | 
			
		||||
            prev.value[0] == '!!'):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Ignore numbers, booleans, etc.
 | 
			
		||||
    resolver = yaml.resolver.Resolver()
 | 
			
		||||
    tag = resolver.resolve(yaml.nodes.ScalarNode, token.value, (True, False))
 | 
			
		||||
    if token.plain and tag != DEFAULT_SCALAR_TAG:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # Ignore multi-line strings
 | 
			
		||||
    if not token.plain and token.style in ("|", ">"):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    quote_type = conf['quote-type']
 | 
			
		||||
 | 
			
		||||
    msg = None
 | 
			
		||||
    if conf['required'] is True:
 | 
			
		||||
 | 
			
		||||
        # Quotes are mandatory and need to match config
 | 
			
		||||
        if (token.style is None or
 | 
			
		||||
            not (_quote_match(quote_type, token.style) or
 | 
			
		||||
                 (conf['allow-quoted-quotes'] and _has_quoted_quotes(token)))):
 | 
			
		||||
            msg = "string value is not quoted with %s quotes" % quote_type
 | 
			
		||||
 | 
			
		||||
    elif conf['required'] is False:
 | 
			
		||||
 | 
			
		||||
        # Quotes are not mandatory but when used need to match config
 | 
			
		||||
        if (token.style and
 | 
			
		||||
                not _quote_match(quote_type, token.style) and
 | 
			
		||||
                not (conf['allow-quoted-quotes'] and
 | 
			
		||||
                     _has_quoted_quotes(token))):
 | 
			
		||||
            msg = "string value is not quoted with %s quotes" % quote_type
 | 
			
		||||
 | 
			
		||||
        elif not token.style:
 | 
			
		||||
            is_extra_required = any(re.search(r, token.value)
 | 
			
		||||
                                    for r in conf['extra-required'])
 | 
			
		||||
            if is_extra_required:
 | 
			
		||||
                msg = "string value is not quoted"
 | 
			
		||||
 | 
			
		||||
    elif conf['required'] == 'only-when-needed':
 | 
			
		||||
 | 
			
		||||
        # Quotes are not strictly needed here
 | 
			
		||||
        if (token.style and tag == DEFAULT_SCALAR_TAG and token.value and
 | 
			
		||||
                not _quotes_are_needed(token.value)):
 | 
			
		||||
            is_extra_required = any(re.search(r, token.value)
 | 
			
		||||
                                    for r in conf['extra-required'])
 | 
			
		||||
            is_extra_allowed = any(re.search(r, token.value)
 | 
			
		||||
                                   for r in conf['extra-allowed'])
 | 
			
		||||
            if not (is_extra_required or is_extra_allowed):
 | 
			
		||||
                msg = "string value is redundantly quoted with %s quotes" % (
 | 
			
		||||
                    quote_type)
 | 
			
		||||
 | 
			
		||||
        # But when used need to match config
 | 
			
		||||
        elif (token.style and
 | 
			
		||||
              not _quote_match(quote_type, token.style) and
 | 
			
		||||
              not (conf['allow-quoted-quotes'] and _has_quoted_quotes(token))):
 | 
			
		||||
            msg = "string value is not quoted with %s quotes" % quote_type
 | 
			
		||||
 | 
			
		||||
        elif not token.style:
 | 
			
		||||
            is_extra_required = len(conf['extra-required']) and any(
 | 
			
		||||
                re.search(r, token.value) for r in conf['extra-required'])
 | 
			
		||||
            if is_extra_required:
 | 
			
		||||
                msg = "string value is not quoted"
 | 
			
		||||
 | 
			
		||||
    if msg is not None:
 | 
			
		||||
        yield LintProblem(
 | 
			
		||||
            token.start_mark.line + 1,
 | 
			
		||||
            token.start_mark.column + 1,
 | 
			
		||||
            msg)
 | 
			
		||||
@ -1,157 +0,0 @@
 | 
			
		||||
# Copyright (C) 2016 Peter Ericson
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Use this rule to forbid non-explicitly typed truthy values other than allowed
 | 
			
		||||
ones (by default: ``true`` and ``false``), for example ``YES`` or ``off``.
 | 
			
		||||
 | 
			
		||||
This can be useful to prevent surprises from YAML parsers transforming
 | 
			
		||||
``[yes, FALSE, Off]`` into ``[true, false, false]`` or
 | 
			
		||||
``{y: 1, yes: 2, on: 3, true: 4, True: 5}`` into ``{y: 1, true: 5}``.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Options
 | 
			
		||||
 | 
			
		||||
* ``allowed-values`` defines the list of truthy values which will be ignored
 | 
			
		||||
  during linting. The default is ``['true', 'false']``, but can be changed to
 | 
			
		||||
  any list containing: ``'TRUE'``, ``'True'``,  ``'true'``, ``'FALSE'``,
 | 
			
		||||
  ``'False'``, ``'false'``, ``'YES'``, ``'Yes'``, ``'yes'``, ``'NO'``,
 | 
			
		||||
  ``'No'``, ``'no'``, ``'ON'``, ``'On'``, ``'on'``, ``'OFF'``, ``'Off'``,
 | 
			
		||||
  ``'off'``.
 | 
			
		||||
* ``check-keys`` disables verification for keys in mappings. By default,
 | 
			
		||||
  ``truthy`` rule applies to both keys and values. Set this option to ``false``
 | 
			
		||||
  to prevent this.
 | 
			
		||||
 | 
			
		||||
.. rubric:: Default values (when enabled)
 | 
			
		||||
 | 
			
		||||
.. code-block:: yaml
 | 
			
		||||
 | 
			
		||||
 rules:
 | 
			
		||||
   truthy:
 | 
			
		||||
     allowed-values: ['true', 'false']
 | 
			
		||||
     check-keys: true
 | 
			
		||||
 | 
			
		||||
.. rubric:: Examples
 | 
			
		||||
 | 
			
		||||
#. With ``truthy: {}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    boolean: true
 | 
			
		||||
 | 
			
		||||
    object: {"True": 1, 1: "True"}
 | 
			
		||||
 | 
			
		||||
    "yes":  1
 | 
			
		||||
    "on":   2
 | 
			
		||||
    "True": 3
 | 
			
		||||
 | 
			
		||||
     explicit:
 | 
			
		||||
       string1: !!str True
 | 
			
		||||
       string2: !!str yes
 | 
			
		||||
       string3: !!str off
 | 
			
		||||
       encoded: !!binary |
 | 
			
		||||
                  True
 | 
			
		||||
                  OFF
 | 
			
		||||
                  pad==  # this decodes as 'N\xbb\x9e8Qii'
 | 
			
		||||
       boolean1: !!bool true
 | 
			
		||||
       boolean2: !!bool "false"
 | 
			
		||||
       boolean3: !!bool FALSE
 | 
			
		||||
       boolean4: !!bool True
 | 
			
		||||
       boolean5: !!bool off
 | 
			
		||||
       boolean6: !!bool NO
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    object: {True: 1, 1: True}
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    yes:  1
 | 
			
		||||
    on:   2
 | 
			
		||||
    True: 3
 | 
			
		||||
 | 
			
		||||
#. With ``truthy: {allowed-values: ["yes", "no"]}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - yes
 | 
			
		||||
    - no
 | 
			
		||||
    - "true"
 | 
			
		||||
    - 'false'
 | 
			
		||||
    - foo
 | 
			
		||||
    - bar
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    - true
 | 
			
		||||
    - false
 | 
			
		||||
    - on
 | 
			
		||||
    - off
 | 
			
		||||
 | 
			
		||||
#. With ``truthy: {check-keys: false}``
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **PASS**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    yes:  1
 | 
			
		||||
    on:   2
 | 
			
		||||
    true: 3
 | 
			
		||||
 | 
			
		||||
   the following code snippet would **FAIL**:
 | 
			
		||||
   ::
 | 
			
		||||
 | 
			
		||||
    yes:  Yes
 | 
			
		||||
    on:   On
 | 
			
		||||
    true: True
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from yamllint.linter import LintProblem
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TRUTHY = ['YES', 'Yes', 'yes',
 | 
			
		||||
          'NO', 'No', 'no',
 | 
			
		||||
          'TRUE', 'True', 'true',
 | 
			
		||||
          'FALSE', 'False', 'false',
 | 
			
		||||
          'ON', 'On', 'on',
 | 
			
		||||
          'OFF', 'Off', 'off']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ID = 'truthy'
 | 
			
		||||
TYPE = 'token'
 | 
			
		||||
CONF = {'allowed-values': list(TRUTHY), 'check-keys': bool}
 | 
			
		||||
DEFAULT = {'allowed-values': ['true', 'false'], 'check-keys': True}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check(conf, token, prev, next, nextnext, context):
 | 
			
		||||
    if prev and isinstance(prev, yaml.tokens.TagToken):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if (not conf['check-keys'] and isinstance(prev, yaml.tokens.KeyToken) and
 | 
			
		||||
            isinstance(token, yaml.tokens.ScalarToken)):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if isinstance(token, yaml.tokens.ScalarToken):
 | 
			
		||||
        if (token.value in (set(TRUTHY) - set(conf['allowed-values'])) and
 | 
			
		||||
                token.style is None):
 | 
			
		||||
            yield LintProblem(token.start_mark.line + 1,
 | 
			
		||||
                              token.start_mark.column + 1,
 | 
			
		||||
                              "truthy value should be one of [" +
 | 
			
		||||
                              ", ".join(sorted(conf['allowed-values'])) + "]")
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue