summaryrefslogtreecommitdiff
path: root/tests/config/test_config.py
blob: 5eab597fd1879455045f8d9dda9a7d3ba97ae736 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt

from __future__ import annotations

import os
from pathlib import Path
from tempfile import TemporaryDirectory

import pytest
from pytest import CaptureFixture

from pylint.interfaces import CONFIDENCE_LEVEL_NAMES
from pylint.lint import Run as LintRun
from pylint.testutils import create_files
from pylint.testutils._run import _Run as Run
from pylint.testutils.configuration_test import run_using_a_configuration_file

HERE = Path(__file__).parent.absolute()
REGRTEST_DATA_DIR = HERE / ".." / "regrtest_data"
EMPTY_MODULE = REGRTEST_DATA_DIR / "empty.py"


def check_configuration_file_reader(
    runner: LintRun,
    expected_disabled: set[str] | None = None,
    expected_jobs: int = 10,
    expected_reports_truthey: bool = True,
) -> None:
    """Check that what we initialized the linter with what was expected."""
    if expected_disabled is None:
        # "logging-not-lazy" and "logging-format-interpolation"
        expected_disabled = {"W1201", "W1202"}
    for msgid in expected_disabled:
        assert not runner.linter.is_message_enabled(msgid)
    assert runner.linter.config.jobs == expected_jobs
    assert bool(runner.linter.config.reports) == expected_reports_truthey


def test_can_read_toml_env_variable(tmp_path: Path, file_to_lint_path: str) -> None:
    """We can read and open a properly formatted toml file."""
    config_file = tmp_path / "pyproject.toml"
    config_file.write_text(
        """
[tool.pylint."messages control"]
disable = "logging-not-lazy,logging-format-interpolation"
jobs = "10"
reports = "yes"
"""
    )
    env_var = "tmp_path_env"
    os.environ[env_var] = str(config_file)
    mock_exit, _, runner = run_using_a_configuration_file(
        f"${env_var}", file_to_lint_path
    )
    mock_exit.assert_called_once_with(0)
    check_configuration_file_reader(runner)


def test_unknown_message_id(capsys: CaptureFixture) -> None:
    """Check that we correctly raise a message on an unknown id."""
    Run([str(EMPTY_MODULE), "--disable=12345"], exit=False)
    output = capsys.readouterr()
    assert "Command line:1:0: W0012: Unknown option value for '--disable'" in output.out


def test_unknown_option_name(capsys: CaptureFixture) -> None:
    """Check that we correctly raise a message on an unknown option."""
    with pytest.raises(SystemExit):
        Run([str(EMPTY_MODULE), "--unknown-option=yes"], exit=False)
    output = capsys.readouterr()
    assert "usage: pylint" in output.err
    assert "Unrecognized option" in output.err


def test_unknown_short_option_name(capsys: CaptureFixture) -> None:
    """Check that we correctly raise a message on an unknown short option."""
    with pytest.raises(SystemExit):
        Run([str(EMPTY_MODULE), "-Q"], exit=False)
    output = capsys.readouterr()
    assert "usage: pylint" in output.err
    assert "Unrecognized option" in output.err


def test_unknown_confidence(capsys: CaptureFixture) -> None:
    """Check that we correctly error an unknown confidence value."""
    with pytest.raises(SystemExit):
        Run([str(EMPTY_MODULE), "--confidence=UNKNOWN_CONFIG"], exit=False)
    output = capsys.readouterr()
    assert "argument --confidence: UNKNOWN_CONFIG should be in" in output.err


def test_empty_confidence() -> None:
    """An empty confidence value indicates all errors should be emitted."""
    r = Run([str(EMPTY_MODULE), "--confidence="], exit=False)
    assert r.linter.config.confidence == CONFIDENCE_LEVEL_NAMES


def test_unknown_yes_no(capsys: CaptureFixture) -> None:
    """Check that we correctly error on an unknown yes/no value."""
    with pytest.raises(SystemExit):
        Run([str(EMPTY_MODULE), "--reports=maybe"], exit=False)
    output = capsys.readouterr()
    assert "Invalid yn value 'maybe', should be in " in output.err


def test_unknown_py_version(capsys: CaptureFixture) -> None:
    """Check that we correctly error on an unknown python-version."""
    with pytest.raises(SystemExit):
        Run([str(EMPTY_MODULE), "--py-version=the-newest"], exit=False)
    output = capsys.readouterr()
    assert "the-newest has an invalid format, should be a version string." in output.err


def test_regex_error(capsys: CaptureFixture) -> None:
    """Check that we correctly error when an an option is passed whose value is an invalid regular expression."""
    with pytest.raises(SystemExit):
        Run(
            [str(EMPTY_MODULE), r"--function-rgx=[\p{Han}a-z_][\p{Han}a-z0-9_]{2,30}$"],
            exit=False,
        )
    output = capsys.readouterr()

    assertString = (
        r"Error in provided regular expression: [\p{Han}a-z_][\p{Han}a-z0-9_]{2,30}$ "
        r"beginning at index 1: bad escape \p"
    )
    assert assertString in output.err


def test_csv_regex_error(capsys: CaptureFixture) -> None:
    """Check that we correctly error when an option is passed and one
    of its comma-separated regular expressions values is an invalid regular expression.
    """
    with pytest.raises(SystemExit):
        Run(
            [str(EMPTY_MODULE), r"--bad-names-rgx=(foo{1,3})"],
            exit=False,
        )
    output = capsys.readouterr()
    assert (
        r"Error in provided regular expression: (foo{1 beginning at index 0: missing ), unterminated subpattern"
        in output.err
    )


def test_short_verbose(capsys: CaptureFixture) -> None:
    """Check that we correctly handle the -v flag."""
    Run([str(EMPTY_MODULE), "-v"], exit=False)
    output = capsys.readouterr()
    assert "Using config file" in output.err


def test_argument_separator() -> None:
    """Check that we support using '--' to separate argument types.

    Reported in https://github.com/PyCQA/pylint/issues/7003.
    """
    runner = Run(["--", str(EMPTY_MODULE)], exit=False)
    assert not runner.linter.stats.by_msg


def test_clear_cache_post_run() -> None:
    modname = "changing.py"
    with TemporaryDirectory() as tmp_dir:
        create_files([modname], tmp_dir)
        module = tmp_dir + os.sep + modname
        # Run class does not produce the wanted failure
        # must use LintRun to get pylint.lint.Run
        run_before_edit = LintRun([module, "--clear-cache-post-run=y"], exit=False)
        with open(module, mode="a", encoding="utf-8") as f:
            f.write("undefined\n")
        run_after_edit = LintRun([module, "--clear-cache-post-run=y"], exit=False)

    assert not run_before_edit.linter.stats.by_msg
    assert run_after_edit.linter.stats.by_msg