diff options
author | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2021-12-23 23:02:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-23 23:02:34 +0100 |
commit | b4bf5168621f0a4bf7cca795862e2b5c139fc8cb (patch) | |
tree | 9103f50e667e2cdac1cc140938a48b3d8b6c3c04 | |
parent | 1a122dd7c4ace87574440bb78fc9b4ddcbd123d1 (diff) | |
download | pylint-git-b4bf5168621f0a4bf7cca795862e2b5c139fc8cb.tar.gz |
Create ``_config_initialization`` util and use in functional tests (#5591)
-rw-r--r-- | pylint/config/config_initialization.py | 75 | ||||
-rw-r--r-- | pylint/lint/run.py | 42 | ||||
-rw-r--r-- | pylint/testutils/lint_module_test.py | 15 | ||||
-rw-r--r-- | tests/testutils/data/init_hook.py | 3 | ||||
-rw-r--r-- | tests/testutils/data/init_hook.rc | 3 | ||||
-rw-r--r-- | tests/testutils/test_functional_testutils.py | 21 |
6 files changed, 111 insertions, 48 deletions
diff --git a/pylint/config/config_initialization.py b/pylint/config/config_initialization.py new file mode 100644 index 000000000..46031bae3 --- /dev/null +++ b/pylint/config/config_initialization.py @@ -0,0 +1,75 @@ +# 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 + +import sys +from typing import TYPE_CHECKING, List, Optional, Union + +from pylint import reporters +from pylint.utils import utils + +if TYPE_CHECKING: + from pylint.lint import PyLinter + + +def _config_initialization( + linter: "PyLinter", + args_list: List[str], + reporter: Union[reporters.BaseReporter, reporters.MultiReporter, None] = None, + config_file: Optional[str] = None, + verbose_mode: Optional[bool] = None, +) -> List[str]: + """Parse all available options, read config files and command line arguments and + set options accordingly. + """ + + # Read the config file. The parser is stored on linter.cfgfile_parser + try: + linter.read_config_file(config_file=config_file, verbose=verbose_mode) + except OSError as ex: + print(ex, file=sys.stderr) + sys.exit(32) + config_parser = linter.cfgfile_parser + + # Run init hook, if present, before loading plugins + if config_parser.has_option("MASTER", "init-hook"): + exec( # pylint: disable=exec-used + utils._unquote(config_parser.get("MASTER", "init-hook")) + ) + + # Load plugins if specified in the config file + if config_parser.has_option("MASTER", "load-plugins"): + plugins = utils._splitstrip(config_parser.get("MASTER", "load-plugins")) + linter.load_plugin_modules(plugins) + + # Now we can load file config, plugins (which can + # provide options) have been registered + linter.load_config_file() + + if reporter: + # If a custom reporter is provided as argument, it may be overridden + # by file parameters, so re-set it here, but before command line + # parsing, so it's still overridable by command line option + linter.set_reporter(reporter) + + # Load command line arguments + try: + args_list = linter.load_command_line_configuration(args_list) + except SystemExit as exc: + if exc.code == 2: # bad options + exc.code = 32 + raise + + # args_list should now only be a list of files/directories to lint. All options have + # been removed from the list + if not args_list: + print(linter.help()) + sys.exit(32) + + # We have loaded configuration from config file and command line. Now, we can + # load plugin specific configuration. + linter.load_plugin_configuration() + + # Now that plugins are loaded, get list of all fail_on messages, and enable them + linter.enable_fail_on_messages() + + return args_list diff --git a/pylint/lint/run.py b/pylint/lint/run.py index a349298c1..a7539cd6a 100644 --- a/pylint/lint/run.py +++ b/pylint/lint/run.py @@ -6,6 +6,7 @@ import sys import warnings from pylint import __pkginfo__, extensions, interfaces +from pylint.config.config_initialization import _config_initialization from pylint.constants import DEFAULT_PYLINT_HOME, OLD_DEFAULT_PYLINT_HOME, full_version from pylint.lint.pylinter import PyLinter from pylint.lint.utils import ArgumentPreprocessingError, preprocess_options @@ -327,40 +328,8 @@ to search for configuration file. # read configuration linter.disable("I") linter.enable("c-extension-no-member") - try: - linter.read_config_file(verbose=self.verbose) - except OSError as ex: - print(ex, file=sys.stderr) - sys.exit(32) - config_parser = linter.cfgfile_parser - # run init hook, if present, before loading plugins - if config_parser.has_option("MASTER", "init-hook"): - cb_init_hook( - "init-hook", utils._unquote(config_parser.get("MASTER", "init-hook")) - ) - # is there some additional plugins in the file configuration, in - if config_parser.has_option("MASTER", "load-plugins"): - plugins = utils._splitstrip(config_parser.get("MASTER", "load-plugins")) - linter.load_plugin_modules(plugins) - # now we can load file config and command line, plugins (which can - # provide options) have been registered - linter.load_config_file() - - if reporter: - # If a custom reporter is provided as argument, it may be overridden - # by file parameters, so re-set it here, but before command line - # parsing, so it's still overridable by command line option - linter.set_reporter(reporter) - try: - args = linter.load_command_line_configuration(args) - except SystemExit as exc: - if exc.code == 2: # bad options - exc.code = 32 - raise - if not args: - print(linter.help()) - sys.exit(32) + args = _config_initialization(linter, args, reporter, verbose_mode=self.verbose) if linter.config.jobs < 0: print( @@ -378,13 +347,6 @@ to search for configuration file. elif linter.config.jobs == 0: linter.config.jobs = _cpu_count() - # We have loaded configuration from config file and command line. Now, we can - # load plugin specific configuration. - linter.load_plugin_configuration() - - # Now that plugins are loaded, get list of all fail_on messages, and enable them - linter.enable_fail_on_messages() - if self._output: try: with open(self._output, "w", encoding="utf-8") as output: diff --git a/pylint/testutils/lint_module_test.py b/pylint/testutils/lint_module_test.py index b7e1ffc67..e89f82ace 100644 --- a/pylint/testutils/lint_module_test.py +++ b/pylint/testutils/lint_module_test.py @@ -14,6 +14,7 @@ import pytest from _pytest.config import Config from pylint import checkers +from pylint.config.config_initialization import _config_initialization from pylint.lint import PyLinter from pylint.message.message import Message from pylint.testutils.constants import _EXPECTED_RE, _OPERATORS, UPDATE_OPTION @@ -24,7 +25,6 @@ from pylint.testutils.functional.test_file import ( # need to import from funct ) from pylint.testutils.output_line import OutputLine from pylint.testutils.reporter_for_tests import FunctionalTestReporter -from pylint.utils import utils MessageCounter = CounterType[Tuple[int, str]] @@ -44,15 +44,14 @@ class LintModuleTest: self._linter.disable("locally-disabled") self._linter.disable("useless-suppression") try: - self._linter.read_config_file(test_file.option_file) - if self._linter.cfgfile_parser.has_option("MASTER", "load-plugins"): - plugins = utils._splitstrip( - self._linter.cfgfile_parser.get("MASTER", "load-plugins") - ) - self._linter.load_plugin_modules(plugins) - self._linter.load_config_file() + _config_initialization( + self._linter, + [test_file.source], + config_file=test_file.option_file, + ) except NoFileError: pass + self._test_file = test_file self._config = config self._check_end_position = ( diff --git a/tests/testutils/data/init_hook.py b/tests/testutils/data/init_hook.py new file mode 100644 index 000000000..f16492d3a --- /dev/null +++ b/tests/testutils/data/init_hook.py @@ -0,0 +1,3 @@ +"""This file should never be tested as the init-hook in the configuration +file prevents the test runner from getting here. +""" diff --git a/tests/testutils/data/init_hook.rc b/tests/testutils/data/init_hook.rc new file mode 100644 index 000000000..b0efa254b --- /dev/null +++ b/tests/testutils/data/init_hook.rc @@ -0,0 +1,3 @@ +[MASTER] + +init-hook=raise RuntimeError diff --git a/tests/testutils/test_functional_testutils.py b/tests/testutils/test_functional_testutils.py new file mode 100644 index 000000000..c1e852e15 --- /dev/null +++ b/tests/testutils/test_functional_testutils.py @@ -0,0 +1,21 @@ +# 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 + +"""Tests for the functional test framework.""" + +from pathlib import Path + +import pytest + +from pylint import testutils +from pylint.testutils.functional import FunctionalTestFile + +HERE = Path(__file__).parent +DATA_DIRECTORY = HERE / "data" + + +def test_parsing_of_pylintrc_init_hook() -> None: + """Test that we correctly parse an init-hook in a settings file.""" + with pytest.raises(RuntimeError): + test_file = FunctionalTestFile(str(DATA_DIRECTORY), "init_hook.py") + testutils.LintModuleTest(test_file) |