blob: 3ffceda4cf7deb8794e678f20341728c4f71cf8f [file] [log] [blame]
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
# pylint: disable=missing-module-docstring, missing-function-docstring
from __future__ import annotations
import contextlib
import os
import pathlib
import shlex
import sys
from collections.abc import Sequence
from io import BufferedReader
from typing import Any, Protocol
from unittest.mock import MagicMock, mock_open, patch
import pytest
from pylint import run_pylint, run_pyreverse, run_symilar
from pylint.testutils import GenericTestReporter as Reporter
from pylint.testutils._run import _Run as Run
from pylint.testutils.utils import _test_cwd
class _RunCallable(Protocol): # pylint: disable=too-few-public-methods
def __call__(self, argv: Sequence[str] | None = None) -> None: ...
@pytest.mark.parametrize("runner", [run_pylint, run_pyreverse, run_symilar])
def test_runner(runner: _RunCallable, tmp_path: pathlib.Path) -> None:
filepath = os.path.abspath(__file__)
testargs = ["", filepath]
with _test_cwd(tmp_path):
with patch.object(sys, "argv", testargs):
with pytest.raises(SystemExit) as err:
runner()
assert err.value.code == 0
@pytest.mark.parametrize("runner", [run_pylint, run_pyreverse, run_symilar])
def test_runner_with_arguments(runner: _RunCallable, tmp_path: pathlib.Path) -> None:
"""Check the runners with arguments as parameter instead of sys.argv."""
filepath = os.path.abspath(__file__)
testargs = [filepath]
with _test_cwd(tmp_path):
with pytest.raises(SystemExit) as err:
runner(testargs)
assert err.value.code == 0
def test_pylint_argument_deduplication(
tmp_path: pathlib.Path, tests_directory: pathlib.Path
) -> None:
"""Check that the Pylint runner does not over-report on duplicate
arguments.
See https://github.com/pylint-dev/pylint/issues/6242 and
https://github.com/pylint-dev/pylint/issues/4053
"""
filepath = str(tests_directory / "functional/t/too/too_many_branches.py")
testargs = shlex.split("--report n --score n --max-branches 13")
testargs.extend([filepath] * 4)
exit_stack = contextlib.ExitStack()
exit_stack.enter_context(_test_cwd(tmp_path))
exit_stack.enter_context(patch.object(sys, "argv", testargs))
err = exit_stack.enter_context(pytest.raises(SystemExit))
with exit_stack:
run_pylint(testargs)
assert err.value.code == 0
def test_pylint_run_jobs_equal_zero_dont_crash_with_cpu_fraction(
tmp_path: pathlib.Path,
) -> None:
"""Check that the pylint runner does not crash if `pylint.lint.run._query_cpu`
determines only a fraction of a CPU core to be available.
"""
builtin_open = open
def _mock_open(*args: Any, **kwargs: Any) -> BufferedReader:
if args[0] == "/sys/fs/cgroup/cpu/cpu.cfs_quota_us":
return mock_open(read_data=b"-1")(*args, **kwargs) # type: ignore[no-any-return]
if args[0] == "/sys/fs/cgroup/cpu/cpu.shares":
return mock_open(read_data=b"2")(*args, **kwargs) # type: ignore[no-any-return]
return builtin_open(*args, **kwargs) # type: ignore[no-any-return]
pathlib_path = pathlib.Path
def _mock_path(*args: str, **kwargs: Any) -> pathlib.Path:
if args[0] == "/sys/fs/cgroup/cpu/cpu.shares":
return MagicMock(is_file=lambda: True)
return pathlib_path(*args, **kwargs)
filepath = os.path.abspath(__file__)
testargs = [filepath, "--jobs=0"]
with _test_cwd(tmp_path):
with pytest.raises(SystemExit) as err:
with patch("builtins.open", _mock_open):
with patch("pylint.lint.run.Path", _mock_path):
Run(testargs, reporter=Reporter())
assert err.value.code == 0