Windows/macOS tests

pull/581/head
Serguei E. Leontiev 2 years ago
parent 7f2c071545
commit 7561cebdd0

@ -33,16 +33,21 @@ jobs:
test: test:
name: Tests name: Tests
runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: ['macos', 'ubuntu', 'windows']
python-version: python-version:
- '3.7' - '3.7'
- '3.8' - '3.8'
- '3.9' - '3.9'
- '3.10' - '3.10'
- '3.11' - '3.11'
runs-on: ${{ matrix.os }}-latest
defaults:
run:
shell: bash -e {0}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@ -50,12 +55,20 @@ jobs:
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- run: pip install .
- name: Append GitHub Actions system path - name: Append GitHub Actions system path
if: ${{ matrix.os == 'ubuntu' }}
run: echo "$HOME/.local/bin" >> $GITHUB_PATH run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- run: pip install coverage - run: pip install coverage
- run: pip install . if: ${{ matrix.os == 'ubuntu' }}
# https://github.com/AndreMiras/coveralls-python-action/issues/18 # https://github.com/AndreMiras/coveralls-python-action/issues/18
- run: echo -e "[run]\nrelative_files = True" > .coveragerc - run: echo -e "[run]\nrelative_files = True" > .coveragerc
if: ${{ matrix.os == 'ubuntu' }}
- run: coverage run -m unittest discover - run: coverage run -m unittest discover
if: ${{ matrix.os == 'ubuntu' }}
- name: Coveralls - name: Coveralls
if: ${{ matrix.os == 'ubuntu' }}
uses: AndreMiras/coveralls-python-action@develop uses: AndreMiras/coveralls-python-action@develop
- name: Unittests only
if: ${{ matrix.os != 'ubuntu' }}
run: python -m unittest

@ -65,9 +65,12 @@ def build_temp_workspace(files):
if type(content) is list: if type(content) is list:
os.mkdir(path) os.mkdir(path)
else: else:
mode = 'wb' if isinstance(content, bytes) else 'w' if isinstance(content, bytes):
with open(path, mode) as f: with open(path, 'wb') as f:
f.write(content) f.write(content)
else:
with open(path, 'w', newline='') as f:
f.write(content)
return tempdir return tempdir
@ -84,3 +87,18 @@ def temp_workspace(files):
finally: finally:
os.chdir(backup_wd) os.chdir(backup_wd)
shutil.rmtree(wd) shutil.rmtree(wd)
@contextlib.contextmanager
def CompatNamedTemporaryFile(*args, **kwargs):
try:
assert 'delete' not in kwargs, "not applicable"
f = tempfile.NamedTemporaryFile(*args, **kwargs, delete=False)
yield f
finally:
f.close()
os.unlink(f.name)
def rsep(s: str) -> str:
return s.replace('/', os.sep)

@ -116,6 +116,8 @@ class KeyOrderingTestCase(RuleTestCase):
self.addCleanup(locale.setlocale, locale.LC_ALL, (None, None)) self.addCleanup(locale.setlocale, locale.LC_ALL, (None, None))
try: try:
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
if not locale.strcoll('t', 'T') < 0: # pragma: no cover
self.skipTest("Not 't' < 'T' for locale en_US.UTF-8")
except locale.Error: # pragma: no cover except locale.Error: # pragma: no cover
self.skipTest('locale en_US.UTF-8 not available') self.skipTest('locale en_US.UTF-8 not available')
conf = ('key-ordering: enable') conf = ('key-ordering: enable')

@ -14,21 +14,25 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from io import StringIO from io import StringIO
import fcntl
import locale import locale
import os import os
import pty
import shutil import shutil
import sys import sys
import tempfile import tempfile
import unittest import unittest
from tests.common import build_temp_workspace, temp_workspace from tests.common import (build_temp_workspace, temp_workspace,
CompatNamedTemporaryFile, rsep)
from yamllint import cli from yamllint import cli
from yamllint import config from yamllint import config
if not sys.platform.startswith('win'):
import pty
import fcntl
class RunContext: class RunContext:
"""Context manager for ``cli.run()`` to capture exit code and streams.""" """Context manager for ``cli.run()`` to capture exit code and streams."""
@ -127,9 +131,10 @@ class CommandLineTestCase(unittest.TestCase):
os.path.join(self.wd, 'dos.yml'), os.path.join(self.wd, 'dos.yml'),
os.path.join(self.wd, 'empty.yml'), os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 'en.yaml'), os.path.join(self.wd, 'en.yaml'),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd,
os.path.join(self.wd, 'sub/directory.yaml/empty.yml'), rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')),
os.path.join(self.wd, 'sub/ok.yaml'), os.path.join(self.wd, rsep('sub/directory.yaml/empty.yml')),
os.path.join(self.wd, rsep('sub/ok.yaml')),
os.path.join(self.wd, 'warn.yaml')], os.path.join(self.wd, 'warn.yaml')],
) )
@ -145,7 +150,8 @@ class CommandLineTestCase(unittest.TestCase):
self.assertEqual( self.assertEqual(
sorted(cli.find_files_recursively(items, conf)), sorted(cli.find_files_recursively(items, conf)),
[os.path.join(self.wd, 'empty.yml'), [os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')], os.path.join(self.wd,
rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'))],
) )
items = [os.path.join(self.wd, 'sub'), items = [os.path.join(self.wd, 'sub'),
@ -153,8 +159,8 @@ class CommandLineTestCase(unittest.TestCase):
self.assertEqual( self.assertEqual(
sorted(cli.find_files_recursively(items, conf)), sorted(cli.find_files_recursively(items, conf)),
[os.path.join(self.wd, '/etc/another/file'), [os.path.join(self.wd, '/etc/another/file'),
os.path.join(self.wd, 'sub/directory.yaml/empty.yml'), os.path.join(self.wd, rsep('sub/directory.yaml/empty.yml')),
os.path.join(self.wd, 'sub/ok.yaml')], os.path.join(self.wd, rsep('sub/ok.yaml'))],
) )
conf = config.YamlLintConfig('extends: default\n' conf = config.YamlLintConfig('extends: default\n'
@ -165,8 +171,9 @@ class CommandLineTestCase(unittest.TestCase):
[os.path.join(self.wd, 'a.yaml'), [os.path.join(self.wd, 'a.yaml'),
os.path.join(self.wd, 'c.yaml'), os.path.join(self.wd, 'c.yaml'),
os.path.join(self.wd, 'en.yaml'), os.path.join(self.wd, 'en.yaml'),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd,
os.path.join(self.wd, 'sub/ok.yaml'), rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')),
os.path.join(self.wd, rsep('sub/ok.yaml')),
os.path.join(self.wd, 'warn.yaml')] os.path.join(self.wd, 'warn.yaml')]
) )
@ -177,7 +184,7 @@ class CommandLineTestCase(unittest.TestCase):
sorted(cli.find_files_recursively([self.wd], conf)), sorted(cli.find_files_recursively([self.wd], conf)),
[os.path.join(self.wd, 'dos.yml'), [os.path.join(self.wd, 'dos.yml'),
os.path.join(self.wd, 'empty.yml'), os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 'sub/directory.yaml/empty.yml')] os.path.join(self.wd, rsep('sub/directory.yaml/empty.yml'))]
) )
conf = config.YamlLintConfig('extends: default\n' conf = config.YamlLintConfig('extends: default\n'
@ -199,11 +206,12 @@ class CommandLineTestCase(unittest.TestCase):
os.path.join(self.wd, 'empty.yml'), os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 'en.yaml'), os.path.join(self.wd, 'en.yaml'),
os.path.join(self.wd, 'no-yaml.json'), os.path.join(self.wd, 'no-yaml.json'),
os.path.join(self.wd, 'non-ascii/éçäγλνπ¥/utf-8'), os.path.join(self.wd, rsep('non-ascii/éçäγλνπ¥/utf-8')),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd,
os.path.join(self.wd, 'sub/directory.yaml/empty.yml'), rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')),
os.path.join(self.wd, 'sub/directory.yaml/not-yaml.txt'), os.path.join(self.wd, rsep('sub/directory.yaml/empty.yml')),
os.path.join(self.wd, 'sub/ok.yaml'), os.path.join(self.wd, rsep('sub/directory.yaml/not-yaml.txt')),
os.path.join(self.wd, rsep('sub/ok.yaml')),
os.path.join(self.wd, 'warn.yaml')] os.path.join(self.wd, 'warn.yaml')]
) )
@ -220,11 +228,12 @@ class CommandLineTestCase(unittest.TestCase):
os.path.join(self.wd, 'empty.yml'), os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 'en.yaml'), os.path.join(self.wd, 'en.yaml'),
os.path.join(self.wd, 'no-yaml.json'), os.path.join(self.wd, 'no-yaml.json'),
os.path.join(self.wd, 'non-ascii/éçäγλνπ¥/utf-8'), os.path.join(self.wd, rsep('non-ascii/éçäγλνπ¥/utf-8')),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd,
os.path.join(self.wd, 'sub/directory.yaml/empty.yml'), rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')),
os.path.join(self.wd, 'sub/directory.yaml/not-yaml.txt'), os.path.join(self.wd, rsep('sub/directory.yaml/empty.yml')),
os.path.join(self.wd, 'sub/ok.yaml'), os.path.join(self.wd, rsep('sub/directory.yaml/not-yaml.txt')),
os.path.join(self.wd, rsep('sub/ok.yaml')),
os.path.join(self.wd, 'warn.yaml')] os.path.join(self.wd, 'warn.yaml')]
) )
@ -234,7 +243,7 @@ class CommandLineTestCase(unittest.TestCase):
' - \'**/utf-8\'\n') ' - \'**/utf-8\'\n')
self.assertEqual( self.assertEqual(
sorted(cli.find_files_recursively([self.wd], conf)), sorted(cli.find_files_recursively([self.wd], conf)),
[os.path.join(self.wd, 'non-ascii/éçäγλνπ¥/utf-8')] [os.path.join(self.wd, rsep('non-ascii/éçäγλνπ¥/utf-8'))]
) )
def test_run_with_bad_arguments(self): def test_run_with_bad_arguments(self):
@ -306,6 +315,8 @@ class CommandLineTestCase(unittest.TestCase):
cli.run(('-c', f.name, os.path.join(self.wd, 'a.yaml'))) cli.run(('-c', f.name, os.path.join(self.wd, 'a.yaml')))
self.assertEqual(ctx.returncode, 1) self.assertEqual(ctx.returncode, 1)
@unittest.skipIf(sys.platform.startswith('win'),
'TODO Windows override HOME unimplemented')
@unittest.skipIf(os.environ.get('GITHUB_RUN_ID'), '$HOME not overridable') @unittest.skipIf(os.environ.get('GITHUB_RUN_ID'), '$HOME not overridable')
def test_run_with_user_global_config_file(self): def test_run_with_user_global_config_file(self):
home = os.path.join(self.wd, 'fake-home') home = os.path.join(self.wd, 'fake-home')
@ -346,7 +357,7 @@ class CommandLineTestCase(unittest.TestCase):
def test_run_with_user_yamllint_config_file_in_env(self): def test_run_with_user_yamllint_config_file_in_env(self):
self.addCleanup(os.environ.__delitem__, 'YAMLLINT_CONFIG_FILE') self.addCleanup(os.environ.__delitem__, 'YAMLLINT_CONFIG_FILE')
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
os.environ['YAMLLINT_CONFIG_FILE'] = f.name os.environ['YAMLLINT_CONFIG_FILE'] = f.name
f.write('rules: {trailing-spaces: disable}') f.write('rules: {trailing-spaces: disable}')
f.flush() f.flush()
@ -354,7 +365,7 @@ class CommandLineTestCase(unittest.TestCase):
cli.run((os.path.join(self.wd, 'a.yaml'), )) cli.run((os.path.join(self.wd, 'a.yaml'), ))
self.assertEqual(ctx.returncode, 0) self.assertEqual(ctx.returncode, 0)
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
os.environ['YAMLLINT_CONFIG_FILE'] = f.name os.environ['YAMLLINT_CONFIG_FILE'] = f.name
f.write('rules: {trailing-spaces: enable}') f.write('rules: {trailing-spaces: enable}')
f.flush() f.flush()
@ -368,6 +379,8 @@ class CommandLineTestCase(unittest.TestCase):
# as the first two runs don't use setlocale() # as the first two runs don't use setlocale()
try: try:
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
if not locale.strcoll('a', 'A') < 0: # pragma: no cover
self.skipTest("Not 'a' < 'A' for locale en_US.UTF-8")
except locale.Error: # pragma: no cover except locale.Error: # pragma: no cover
self.skipTest('locale en_US.UTF-8 not available') self.skipTest('locale en_US.UTF-8 not available')
locale.setlocale(locale.LC_ALL, (None, None)) locale.setlocale(locale.LC_ALL, (None, None))
@ -477,7 +490,7 @@ class CommandLineTestCase(unittest.TestCase):
self.assertEqual((ctx.returncode, ctx.stderr), (1, '')) self.assertEqual((ctx.returncode, ctx.stderr), (1, ''))
self.assertEqual(ctx.stdout, ( self.assertEqual(ctx.stdout, (
'%s:3:1: [error] duplication of key "key" in mapping ' '%s:3:1: [error] duplication of key "key" in mapping '
'(key-duplicates)\n') % path) '(key-duplicates)\n') % rsep(path))
def test_run_piped_output_nocolor(self): def test_run_piped_output_nocolor(self):
path = os.path.join(self.wd, 'a.yaml') path = os.path.join(self.wd, 'a.yaml')
@ -492,6 +505,8 @@ class CommandLineTestCase(unittest.TestCase):
'(new-line-at-end-of-file)\n' '(new-line-at-end-of-file)\n'
'\n' % path)) '\n' % path))
@unittest.skipIf(sys.platform.startswith('win'),
'Windows pseudo-TTY unimplemented')
def test_run_default_format_output_in_tty(self): def test_run_default_format_output_in_tty(self):
path = os.path.join(self.wd, 'a.yaml') path = os.path.join(self.wd, 'a.yaml')
@ -689,9 +704,10 @@ class CommandLineTestCase(unittest.TestCase):
os.path.join(self.wd, 'dos.yml'), os.path.join(self.wd, 'dos.yml'),
os.path.join(self.wd, 'empty.yml'), os.path.join(self.wd, 'empty.yml'),
os.path.join(self.wd, 'en.yaml'), os.path.join(self.wd, 'en.yaml'),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd,
os.path.join(self.wd, 'sub/directory.yaml/empty.yml'), rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')),
os.path.join(self.wd, 'sub/ok.yaml'), os.path.join(self.wd, rsep('sub/directory.yaml/empty.yml')),
os.path.join(self.wd, rsep('sub/ok.yaml')),
os.path.join(self.wd, 'warn.yaml')] os.path.join(self.wd, 'warn.yaml')]
) )
@ -705,9 +721,10 @@ class CommandLineTestCase(unittest.TestCase):
os.path.join(self.wd, 'c.yaml'), os.path.join(self.wd, 'c.yaml'),
os.path.join(self.wd, 'en.yaml'), os.path.join(self.wd, 'en.yaml'),
os.path.join(self.wd, 'no-yaml.json'), os.path.join(self.wd, 'no-yaml.json'),
os.path.join(self.wd, 's/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml'), os.path.join(self.wd,
os.path.join(self.wd, 'sub/directory.yaml/not-yaml.txt'), rsep('s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/file.yaml')),
os.path.join(self.wd, 'sub/ok.yaml'), os.path.join(self.wd, rsep('sub/directory.yaml/not-yaml.txt')),
os.path.join(self.wd, rsep('sub/ok.yaml')),
os.path.join(self.wd, 'warn.yaml')] os.path.join(self.wd, 'warn.yaml')]
) )
@ -724,9 +741,10 @@ class CommandLineConfigTestCase(unittest.TestCase):
with RunContext(self) as ctx: with RunContext(self) as ctx:
cli.run(('-f', 'parsable', '.')) cli.run(('-f', 'parsable', '.'))
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr), self.assertEqual(
(0, './a.yml:1:1: [warning] missing document ' (ctx.returncode, ctx.stdout, ctx.stderr),
'start "---" (document-start)\n', '')) (0, rsep('./a.yml:1:1: [warning] missing document '
'start "---" (document-start)\n'), ''))
with temp_workspace({**workspace, **{conf_file: conf}}): with temp_workspace({**workspace, **{conf_file: conf}}):
with RunContext(self) as ctx: with RunContext(self) as ctx:
@ -747,10 +765,11 @@ class CommandLineConfigTestCase(unittest.TestCase):
os.chdir('a/b/c/d/e/f') os.chdir('a/b/c/d/e/f')
cli.run(('-f', 'parsable', '.')) cli.run(('-f', 'parsable', '.'))
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr), self.assertEqual(
(0, './g/a.yml:1:1: [warning] missing ' (ctx.returncode, ctx.stdout, ctx.stderr),
'document start "---" (document-start)\n', (0, rsep('./g/a.yml:1:1: [warning] missing '
'')) 'document start "---" (document-start)\n'),
''))
with temp_workspace({**workspace, **{conf_file: conf}}): with temp_workspace({**workspace, **{conf_file: conf}}):
with RunContext(self) as ctx: with RunContext(self) as ctx:
@ -783,15 +802,17 @@ class CommandLineConfigTestCase(unittest.TestCase):
os.chdir('a/b/c') os.chdir('a/b/c')
cli.run(('-f', 'parsable', '.')) cli.run(('-f', 'parsable', '.'))
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr), self.assertEqual(
(0, './3spaces.yml:2:4: [warning] wrong indentation: ' (ctx.returncode, ctx.stdout, ctx.stderr),
'expected 4 but found 3 (indentation)\n', '')) (0, rsep('./3spaces.yml:2:4: [warning] wrong indentation: '
'expected 4 but found 3 (indentation)\n'), ''))
with temp_workspace({**workspace, **{'a/b/.yamllint.yml': conf3}}): with temp_workspace({**workspace, **{'a/b/.yamllint.yml': conf3}}):
with RunContext(self) as ctx: with RunContext(self) as ctx:
os.chdir('a/b/c') os.chdir('a/b/c')
cli.run(('-f', 'parsable', '.')) cli.run(('-f', 'parsable', '.'))
self.assertEqual((ctx.returncode, ctx.stdout, ctx.stderr), self.assertEqual(
(0, './4spaces.yml:2:5: [warning] wrong indentation: ' (ctx.returncode, ctx.stdout, ctx.stderr),
'expected 3 but found 4 (indentation)\n', '')) (0, rsep('./4spaces.yml:2:5: [warning] wrong indentation: '
'expected 3 but found 4 (indentation)\n'), ''))

@ -17,10 +17,9 @@ from io import StringIO
import os import os
import shutil import shutil
import sys import sys
import tempfile
import unittest import unittest
from tests.common import build_temp_workspace from tests.common import build_temp_workspace, CompatNamedTemporaryFile, rsep
from yamllint.config import YamlLintConfigError from yamllint.config import YamlLintConfigError
from yamllint import cli from yamllint import cli
@ -245,7 +244,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(len(new.enabled_rules(None)), 2) self.assertEqual(len(new.enabled_rules(None)), 2)
def test_extend_on_file(self): def test_extend_on_file(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('rules:\n' f.write('rules:\n'
' colons:\n' ' colons:\n'
' max-spaces-before: 0\n' ' max-spaces-before: 0\n'
@ -264,7 +263,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(len(c.enabled_rules(None)), 2) self.assertEqual(len(c.enabled_rules(None)), 2)
def test_extend_remove_rule(self): def test_extend_remove_rule(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('rules:\n' f.write('rules:\n'
' colons:\n' ' colons:\n'
' max-spaces-before: 0\n' ' max-spaces-before: 0\n'
@ -283,7 +282,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(len(c.enabled_rules(None)), 1) self.assertEqual(len(c.enabled_rules(None)), 1)
def test_extend_edit_rule(self): def test_extend_edit_rule(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('rules:\n' f.write('rules:\n'
' colons:\n' ' colons:\n'
' max-spaces-before: 0\n' ' max-spaces-before: 0\n'
@ -305,7 +304,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(len(c.enabled_rules(None)), 2) self.assertEqual(len(c.enabled_rules(None)), 2)
def test_extend_reenable_rule(self): def test_extend_reenable_rule(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('rules:\n' f.write('rules:\n'
' colons:\n' ' colons:\n'
' max-spaces-before: 0\n' ' max-spaces-before: 0\n'
@ -325,7 +324,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(len(c.enabled_rules(None)), 2) self.assertEqual(len(c.enabled_rules(None)), 2)
def test_extend_recursive_default_values(self): def test_extend_recursive_default_values(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('rules:\n' f.write('rules:\n'
' braces:\n' ' braces:\n'
' max-spaces-inside: 1248\n') ' max-spaces-inside: 1248\n')
@ -340,7 +339,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(c.rules['braces']['min-spaces-inside-empty'], 2357) self.assertEqual(c.rules['braces']['min-spaces-inside-empty'], 2357)
self.assertEqual(c.rules['braces']['max-spaces-inside-empty'], -1) self.assertEqual(c.rules['braces']['max-spaces-inside-empty'], -1)
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('rules:\n' f.write('rules:\n'
' colons:\n' ' colons:\n'
' max-spaces-before: 1337\n') ' max-spaces-before: 1337\n')
@ -352,8 +351,8 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(c.rules['colons']['max-spaces-before'], 1337) self.assertEqual(c.rules['colons']['max-spaces-before'], 1337)
self.assertEqual(c.rules['colons']['max-spaces-after'], 1) self.assertEqual(c.rules['colons']['max-spaces-after'], 1)
with tempfile.NamedTemporaryFile('w') as f1, \ with CompatNamedTemporaryFile('w') as f1, \
tempfile.NamedTemporaryFile('w') as f2: CompatNamedTemporaryFile('w') as f2:
f1.write('rules:\n' f1.write('rules:\n'
' colons:\n' ' colons:\n'
' max-spaces-before: 1337\n') ' max-spaces-before: 1337\n')
@ -370,7 +369,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(c.rules['colons']['max-spaces-after'], 1) self.assertEqual(c.rules['colons']['max-spaces-after'], 1)
def test_extended_ignore_str(self): def test_extended_ignore_str(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('ignore: |\n' f.write('ignore: |\n'
' *.template.yaml\n') ' *.template.yaml\n')
f.flush() f.flush()
@ -380,7 +379,7 @@ class ExtendedConfigTestCase(unittest.TestCase):
self.assertEqual(c.ignore.match_file('test.yaml'), False) self.assertEqual(c.ignore.match_file('test.yaml'), False)
def test_extended_ignore_list(self): def test_extended_ignore_list(self):
with tempfile.NamedTemporaryFile('w') as f: with CompatNamedTemporaryFile('w') as f:
f.write('ignore:\n' f.write('ignore:\n'
' - "*.template.yaml"\n') ' - "*.template.yaml"\n')
f.flush() f.flush()
@ -513,7 +512,7 @@ class IgnoreConfigTestCase(unittest.TestCase):
trailing = '[error] trailing spaces (trailing-spaces)' trailing = '[error] trailing spaces (trailing-spaces)'
hyphen = '[error] too many spaces after hyphen (hyphens)' hyphen = '[error] too many spaces after hyphen (hyphens)'
self.assertEqual(out, '\n'.join(( self.assertEqual(out, rsep('\n'.join((
'./bin/file.lint-me-anyway.yaml:3:3: ' + keydup, './bin/file.lint-me-anyway.yaml:3:3: ' + keydup,
'./bin/file.lint-me-anyway.yaml:4:17: ' + trailing, './bin/file.lint-me-anyway.yaml:4:17: ' + trailing,
'./bin/file.lint-me-anyway.yaml:5:5: ' + hyphen, './bin/file.lint-me-anyway.yaml:5:5: ' + hyphen,
@ -547,10 +546,10 @@ class IgnoreConfigTestCase(unittest.TestCase):
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen,
))) ))))
def test_run_with_ignore_str(self): def test_run_with_ignore_str(self):
with open(os.path.join(self.wd, '.yamllint'), 'w') as f: with open(os.path.join(self.wd, '.yamllint'), 'w', newline='') as f:
f.write('extends: default\n' f.write('extends: default\n'
'ignore: |\n' 'ignore: |\n'
' *.dont-lint-me.yaml\n' ' *.dont-lint-me.yaml\n'
@ -577,7 +576,7 @@ class IgnoreConfigTestCase(unittest.TestCase):
trailing = '[error] trailing spaces (trailing-spaces)' trailing = '[error] trailing spaces (trailing-spaces)'
hyphen = '[error] too many spaces after hyphen (hyphens)' hyphen = '[error] too many spaces after hyphen (hyphens)'
self.assertEqual(out, '\n'.join(( self.assertEqual(out, rsep('\n'.join((
'./.yamllint:1:1: ' + docstart, './.yamllint:1:1: ' + docstart,
'./bin/file.lint-me-anyway.yaml:3:3: ' + keydup, './bin/file.lint-me-anyway.yaml:3:3: ' + keydup,
'./bin/file.lint-me-anyway.yaml:4:17: ' + trailing, './bin/file.lint-me-anyway.yaml:4:17: ' + trailing,
@ -601,10 +600,10 @@ class IgnoreConfigTestCase(unittest.TestCase):
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen,
))) ))))
def test_run_with_ignore_list(self): def test_run_with_ignore_list(self):
with open(os.path.join(self.wd, '.yamllint'), 'w') as f: with open(os.path.join(self.wd, '.yamllint'), 'w', newline='') as f:
f.write('extends: default\n' f.write('extends: default\n'
'ignore:\n' 'ignore:\n'
' - "*.dont-lint-me.yaml"\n' ' - "*.dont-lint-me.yaml"\n'
@ -631,7 +630,7 @@ class IgnoreConfigTestCase(unittest.TestCase):
trailing = '[error] trailing spaces (trailing-spaces)' trailing = '[error] trailing spaces (trailing-spaces)'
hyphen = '[error] too many spaces after hyphen (hyphens)' hyphen = '[error] too many spaces after hyphen (hyphens)'
self.assertEqual(out, '\n'.join(( self.assertEqual(out, rsep('\n'.join((
'./.yamllint:1:1: ' + docstart, './.yamllint:1:1: ' + docstart,
'./bin/file.lint-me-anyway.yaml:3:3: ' + keydup, './bin/file.lint-me-anyway.yaml:3:3: ' + keydup,
'./bin/file.lint-me-anyway.yaml:4:17: ' + trailing, './bin/file.lint-me-anyway.yaml:4:17: ' + trailing,
@ -655,13 +654,13 @@ class IgnoreConfigTestCase(unittest.TestCase):
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen,
))) ))))
def test_run_with_ignore_from_file(self): def test_run_with_ignore_from_file(self):
with open(os.path.join(self.wd, '.yamllint'), 'w') as f: with open(os.path.join(self.wd, '.yamllint'), 'w', newline='') as f:
f.write('extends: default\n' f.write('extends: default\n'
'ignore-from-file: .gitignore\n') 'ignore-from-file: .gitignore\n')
with open(os.path.join(self.wd, '.gitignore'), 'w') as f: with open(os.path.join(self.wd, '.gitignore'), 'w', newline='') as f:
f.write('*.dont-lint-me.yaml\n' f.write('*.dont-lint-me.yaml\n'
'/bin/\n' '/bin/\n'
'!/bin/*.lint-me-anyway.yaml\n') '!/bin/*.lint-me-anyway.yaml\n')
@ -678,7 +677,7 @@ class IgnoreConfigTestCase(unittest.TestCase):
trailing = '[error] trailing spaces (trailing-spaces)' trailing = '[error] trailing spaces (trailing-spaces)'
hyphen = '[error] too many spaces after hyphen (hyphens)' hyphen = '[error] too many spaces after hyphen (hyphens)'
self.assertEqual(out, '\n'.join(( self.assertEqual(out, rsep('\n'.join((
'./.yamllint:1:1: ' + docstart, './.yamllint:1:1: ' + docstart,
'./bin/file.lint-me-anyway.yaml:3:3: ' + keydup, './bin/file.lint-me-anyway.yaml:3:3: ' + keydup,
'./bin/file.lint-me-anyway.yaml:4:17: ' + trailing, './bin/file.lint-me-anyway.yaml:4:17: ' + trailing,
@ -707,16 +706,16 @@ class IgnoreConfigTestCase(unittest.TestCase):
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen,
))) ))))
def test_run_with_ignored_from_file(self): def test_run_with_ignored_from_file(self):
with open(os.path.join(self.wd, '.yamllint'), 'w') as f: with open(os.path.join(self.wd, '.yamllint'), 'w', newline='') as f:
f.write('ignore-from-file: [.gitignore, .yamlignore]\n' f.write('ignore-from-file: [.gitignore, .yamlignore]\n'
'extends: default\n') 'extends: default\n')
with open(os.path.join(self.wd, '.gitignore'), 'w') as f: with open(os.path.join(self.wd, '.gitignore'), 'w', newline='') as f:
f.write('*.dont-lint-me.yaml\n' f.write('*.dont-lint-me.yaml\n'
'/bin/\n') '/bin/\n')
with open(os.path.join(self.wd, '.yamlignore'), 'w') as f: with open(os.path.join(self.wd, '.yamlignore'), 'w', newline='') as f:
f.write('!/bin/*.lint-me-anyway.yaml\n') f.write('!/bin/*.lint-me-anyway.yaml\n')
sys.stdout = StringIO() sys.stdout = StringIO()
@ -731,7 +730,7 @@ class IgnoreConfigTestCase(unittest.TestCase):
trailing = '[error] trailing spaces (trailing-spaces)' trailing = '[error] trailing spaces (trailing-spaces)'
hyphen = '[error] too many spaces after hyphen (hyphens)' hyphen = '[error] too many spaces after hyphen (hyphens)'
self.assertEqual(out, '\n'.join(( self.assertEqual(out, rsep('\n'.join((
'./.yamllint:1:1: ' + docstart, './.yamllint:1:1: ' + docstart,
'./bin/file.lint-me-anyway.yaml:3:3: ' + keydup, './bin/file.lint-me-anyway.yaml:3:3: ' + keydup,
'./bin/file.lint-me-anyway.yaml:4:17: ' + trailing, './bin/file.lint-me-anyway.yaml:4:17: ' + trailing,
@ -760,4 +759,4 @@ class IgnoreConfigTestCase(unittest.TestCase):
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:3:3: ' + keydup,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:4:17: ' + trailing,
'./s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen, './s/s/ign-trail/s/s/file2.lint-me-anyway.yaml:5:5: ' + hyphen,
))) ))))

@ -20,6 +20,8 @@ import tempfile
import sys import sys
import unittest import unittest
from tests.common import rsep
PYTHON = sys.executable or 'python' PYTHON = sys.executable or 'python'
@ -29,12 +31,13 @@ class ModuleTestCase(unittest.TestCase):
self.wd = tempfile.mkdtemp(prefix='yamllint-tests-') self.wd = tempfile.mkdtemp(prefix='yamllint-tests-')
# file with only one warning # file with only one warning
with open(os.path.join(self.wd, 'warn.yaml'), 'w') as f: with open(os.path.join(self.wd, 'warn.yaml'), 'w', newline='') as f:
f.write('key: value\n') f.write('key: value\n')
# file in dir # file in dir
os.mkdir(os.path.join(self.wd, 'sub')) os.mkdir(os.path.join(self.wd, 'sub'))
with open(os.path.join(self.wd, 'sub', 'nok.yaml'), 'w') as f: with open(os.path.join(self.wd, 'sub', 'nok.yaml'),
'w', newline='') as f:
f.write('---\n' f.write('---\n'
'list: [ 1, 1, 2, 3, 5, 8] \n') 'list: [ 1, 1, 2, 3, 5, 8] \n')
@ -44,41 +47,43 @@ class ModuleTestCase(unittest.TestCase):
def test_run_module_no_args(self): def test_run_module_no_args(self):
with self.assertRaises(subprocess.CalledProcessError) as ctx: with self.assertRaises(subprocess.CalledProcessError) as ctx:
subprocess.check_output([PYTHON, '-m', 'yamllint'], subprocess.check_output([PYTHON, '-m', 'yamllint'],
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT, text=True)
self.assertEqual(ctx.exception.returncode, 2) self.assertEqual(ctx.exception.returncode, 2)
self.assertRegex(ctx.exception.output.decode(), r'^usage: yamllint') self.assertRegex(ctx.exception.output, r'^usage: yamllint')
def test_run_module_on_bad_dir(self): def test_run_module_on_bad_dir(self):
with self.assertRaises(subprocess.CalledProcessError) as ctx: with self.assertRaises(subprocess.CalledProcessError) as ctx:
subprocess.check_output([PYTHON, '-m', 'yamllint', subprocess.check_output([PYTHON, '-m', 'yamllint',
'/does/not/exist'], '/does/not/exist'],
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT, text=True)
self.assertRegex(ctx.exception.output.decode(), self.assertRegex(ctx.exception.output,
r'No such file or directory') r'No such file or directory')
def test_run_module_on_file(self): def test_run_module_on_file(self):
out = subprocess.check_output( out = subprocess.check_output(
[PYTHON, '-m', 'yamllint', os.path.join(self.wd, 'warn.yaml')]) [PYTHON, '-m', 'yamllint', os.path.join(self.wd, 'warn.yaml')],
lines = out.decode().splitlines() text=True)
self.assertIn('/warn.yaml', lines[0]) lines = out.splitlines()
self.assertIn(rsep('/warn.yaml'), lines[0])
self.assertEqual('\n'.join(lines[1:]), self.assertEqual('\n'.join(lines[1:]),
' 1:1 warning missing document start "---"' ' 1:1 warning missing document start "---"'
' (document-start)\n') ' (document-start)\n')
def test_run_module_on_dir(self): def test_run_module_on_dir(self):
with self.assertRaises(subprocess.CalledProcessError) as ctx: with self.assertRaises(subprocess.CalledProcessError) as ctx:
subprocess.check_output([PYTHON, '-m', 'yamllint', self.wd]) subprocess.check_output([PYTHON, '-m', 'yamllint', self.wd],
text=True)
self.assertEqual(ctx.exception.returncode, 1) self.assertEqual(ctx.exception.returncode, 1)
files = ctx.exception.output.decode().split('\n\n') files = ctx.exception.output.split('\n\n')
self.assertIn( self.assertIn(
'/warn.yaml\n' rsep('/warn.yaml\n'
' 1:1 warning missing document start "---"' ' 1:1 warning missing document start "---"'
' (document-start)', ' (document-start)'),
files[0]) files[0])
self.assertIn( self.assertIn(
'/sub/nok.yaml\n' rsep('/sub/nok.yaml\n'
' 2:9 error too many spaces inside brackets' ' 2:9 error too many spaces inside brackets'
' (brackets)\n' ' (brackets)\n'
' 2:27 error trailing spaces (trailing-spaces)', ' 2:27 error trailing spaces (trailing-spaces)'),
files[1]) files[1])

Loading…
Cancel
Save