"""Integration tests for the main entrypoint of flake8.""" import json import os import sys from unittest import mock import pytest from flake8 import utils from flake8.main import cli def _call_main(argv, retv=0): with pytest.raises(SystemExit) as excinfo: cli.main(argv) assert excinfo.value.code == retv def test_diff_option(tmpdir, capsys): """Ensure that `flake8 --diff` works.""" t_py_contents = """\ import os import sys # unused but not part of diff print('(to avoid trailing whitespace in test)') print('(to avoid trailing whitespace in test)') print(os.path.join('foo', 'bar')) y # part of the diff and an error """ diff = """\ diff --git a/t.py b/t.py index d64ac39..7d943de 100644 --- a/t.py +++ b/t.py @@ -4,3 +4,5 @@ import sys # unused but not part of diff print('(to avoid trailing whitespace in test)') print('(to avoid trailing whitespace in test)') print(os.path.join('foo', 'bar')) + +y # part of the diff and an error """ with mock.patch.object(utils, "stdin_get_value", return_value=diff): with tmpdir.as_cwd(): tmpdir.join("t.py").write(t_py_contents) _call_main(["--diff"], retv=1) out, err = capsys.readouterr() assert out == "t.py:8:1: F821 undefined name 'y'\n" assert err == "" def test_form_feed_line_split(tmpdir, capsys): """Test that form feed is treated the same for stdin.""" src = "x=1\n\f\ny=1\n" expected_out = """\ t.py:1:2: E225 missing whitespace around operator t.py:3:2: E225 missing whitespace around operator """ with tmpdir.as_cwd(): tmpdir.join("t.py").write(src) with mock.patch.object(utils, "stdin_get_value", return_value=src): _call_main(["-", "--stdin-display-name=t.py"], retv=1) out, err = capsys.readouterr() assert out == expected_out assert err == "" _call_main(["t.py"], retv=1) out, err = capsys.readouterr() assert out == expected_out assert err == "" def test_e101_indent_char_does_not_reset(tmpdir, capsys): """Ensure that E101 with an existing indent_char does not reset it.""" t_py_contents = """\ if True: print('space indented') s = '''\ \ttab indented ''' # noqa: E101 if True: print('space indented') """ with tmpdir.as_cwd(): tmpdir.join("t.py").write(t_py_contents) _call_main(["t.py"]) def test_statistics_option(tmpdir, capsys): """Ensure that `flake8 --statistics` works.""" with tmpdir.as_cwd(): tmpdir.join("t.py").write("import os\nimport sys\n") _call_main(["--statistics", "t.py"], retv=1) expected = """\ t.py:1:1: F401 'os' imported but unused t.py:2:1: F401 'sys' imported but unused 2 F401 'os' imported but unused """ out, err = capsys.readouterr() assert out == expected assert err == "" def test_show_source_option(tmpdir, capsys): """Ensure that --show-source and --no-show-source work.""" with tmpdir.as_cwd(): tmpdir.join("tox.ini").write("[flake8]\nshow_source = true\n") tmpdir.join("t.py").write("import os\n") _call_main(["t.py"], retv=1) expected = """\ t.py:1:1: F401 'os' imported but unused import os ^ """ out, err = capsys.readouterr() assert out == expected assert err == "" with tmpdir.as_cwd(): _call_main(["t.py", "--no-show-source"], retv=1) expected = """\ t.py:1:1: F401 'os' imported but unused """ out, err = capsys.readouterr() assert out == expected assert err == "" def test_extend_exclude(tmpdir, capsys): """Ensure that `flake8 --extend-exclude` works.""" for d in ["project", "vendor", "legacy", ".git", ".tox", ".hg"]: tmpdir.mkdir(d).join("t.py").write("import os\nimport sys\n") with tmpdir.as_cwd(): _call_main(["--extend-exclude=vendor,legacy/"], retv=1) out, err = capsys.readouterr() expected_out = """\ ./project/t.py:1:1: F401 'os' imported but unused ./project/t.py:2:1: F401 'sys' imported but unused """ assert out == expected_out.replace("/", os.sep) assert err == "" def test_malformed_per_file_ignores_error(tmpdir, capsys): """Test the error message for malformed `per-file-ignores`.""" setup_cfg = """\ [flake8] per-file-ignores = incorrect/* values/* """ expected = """\ There was a critical error during execution of Flake8: Expected `per-file-ignores` to be a mapping from file exclude patterns to ignore codes. Configured `per-file-ignores` setting: incorrect/* values/* """ # noqa: E501 with tmpdir.as_cwd(): tmpdir.join("setup.cfg").write(setup_cfg) _call_main(["."], retv=1) out, err = capsys.readouterr() assert out == expected def test_tokenization_error_but_not_syntax_error(tmpdir, capsys): """Test that flake8 does not crash on tokenization errors.""" with tmpdir.as_cwd(): # this is a crash in the tokenizer, but not in the ast tmpdir.join("t.py").write("b'foo' \\\n") _call_main(["t.py"], retv=1) if hasattr(sys, "pypy_version_info"): # pragma: no cover (pypy) expected = "t.py:2:1: E999 SyntaxError: end of file (EOF) in multi-line statement\n" # noqa: E501 elif sys.version_info < (3, 8): # pragma: no cover (