| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- # 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
- # pylint: disable=too-many-arguments, redefined-builtin, duplicate-code
- """Callback actions for various options."""
- from __future__ import annotations
- import abc
- import argparse
- import sys
- import warnings
- from collections.abc import Callable, Sequence
- from pathlib import Path
- from typing import TYPE_CHECKING, Any
- from pylint import exceptions, extensions, interfaces, utils
- if TYPE_CHECKING:
- from pylint.config.help_formatter import _HelpFormatter
- from pylint.lint import PyLinter
- from pylint.lint.run import Run
- class _CallbackAction(argparse.Action):
- """Custom callback action."""
- @abc.abstractmethod
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = None,
- ) -> None:
- raise NotImplementedError # pragma: no cover
- class _DoNothingAction(_CallbackAction):
- """Action that just passes.
- This action is used to allow pre-processing of certain options
- without erroring when they are then processed again by argparse.
- """
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = None,
- ) -> None:
- return None
- class _ExtendAction(argparse._AppendAction):
- """Action that adds the value to a pre-existing list.
- It is directly copied from the stdlib implementation which is only available
- on 3.8+.
- """
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = None,
- ) -> None:
- assert isinstance(values, (tuple, list))
- current = getattr(namespace, self.dest, [])
- assert isinstance(current, list)
- current.extend(values)
- setattr(namespace, self.dest, current)
- class _AccessRunObjectAction(_CallbackAction):
- """Action that has access to the Run object."""
- def __init__(
- self,
- option_strings: Sequence[str],
- dest: str,
- nargs: None = None,
- const: None = None,
- default: None = None,
- type: None = None,
- choices: None = None,
- required: bool = False,
- help: str = "",
- metavar: str = "",
- **kwargs: Run,
- ) -> None:
- self.run = kwargs["Run"]
- super().__init__(
- option_strings,
- dest,
- 0,
- const,
- default,
- type,
- choices,
- required,
- help,
- metavar,
- )
- @abc.abstractmethod
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = None,
- ) -> None:
- raise NotImplementedError # pragma: no cover
- class _MessageHelpAction(_CallbackAction):
- """Display the help message of a message."""
- def __init__(
- self,
- option_strings: Sequence[str],
- dest: str,
- nargs: None = None,
- const: None = None,
- default: None = None,
- type: None = None,
- choices: None = None,
- required: bool = False,
- help: str = "",
- metavar: str = "",
- **kwargs: Run,
- ) -> None:
- self.run = kwargs["Run"]
- super().__init__(
- option_strings,
- dest,
- "+",
- const,
- default,
- type,
- choices,
- required,
- help,
- metavar,
- )
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[str] | None,
- option_string: str | None = "--help-msg",
- ) -> None:
- assert isinstance(values, (list, tuple))
- values_to_print: list[str] = []
- for msg in values:
- assert isinstance(msg, str)
- values_to_print += utils._check_csv(msg)
- self.run.linter.msgs_store.help_message(values_to_print)
- sys.exit(0)
- class _ListMessagesAction(_AccessRunObjectAction):
- """Display all available messages."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--list-enabled",
- ) -> None:
- self.run.linter.msgs_store.list_messages()
- sys.exit(0)
- class _ListMessagesEnabledAction(_AccessRunObjectAction):
- """Display all enabled messages."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--list-msgs-enabled",
- ) -> None:
- self.run.linter.list_messages_enabled()
- sys.exit(0)
- class _ListCheckGroupsAction(_AccessRunObjectAction):
- """Display all the check groups that pylint knows about."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--list-groups",
- ) -> None:
- for check in self.run.linter.get_checker_names():
- print(check)
- sys.exit(0)
- class _ListConfidenceLevelsAction(_AccessRunObjectAction):
- """Display all the confidence levels that pylint knows about."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--list-conf-levels",
- ) -> None:
- for level in interfaces.CONFIDENCE_LEVELS:
- print(f"%-18s: {level}")
- sys.exit(0)
- class _ListExtensionsAction(_AccessRunObjectAction):
- """Display all extensions under pylint.extensions."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--list-extensions",
- ) -> None:
- for filename in Path(extensions.__file__).parent.iterdir():
- if filename.suffix == ".py" and not filename.stem.startswith("_"):
- extension_name, _, _ = filename.stem.partition(".")
- print(f"pylint.extensions.{extension_name}")
- sys.exit(0)
- class _FullDocumentationAction(_AccessRunObjectAction):
- """Display the full documentation."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--full-documentation",
- ) -> None:
- utils.print_full_documentation(self.run.linter)
- sys.exit(0)
- class _GenerateRCFileAction(_AccessRunObjectAction):
- """Generate a pylintrc file."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--generate-rcfile",
- ) -> None:
- # TODO: 2.x: Deprecate this after the auto-upgrade functionality of
- # pylint-config is sufficient.
- with warnings.catch_warnings():
- warnings.filterwarnings("ignore", category=DeprecationWarning)
- self.run.linter.generate_config(skipsections=("Commands",))
- sys.exit(0)
- class _GenerateConfigFileAction(_AccessRunObjectAction):
- """Generate a .toml format configuration file."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--generate-toml-config",
- ) -> None:
- print(self.run.linter._generate_config_file())
- sys.exit(0)
- class _ErrorsOnlyModeAction(_AccessRunObjectAction):
- """Turn on errors-only mode.
- Error mode:
- * disable all but error messages
- * disable the 'miscellaneous' checker which can be safely deactivated in
- debug
- * disable reports
- * do not save execution information
- """
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--errors-only",
- ) -> None:
- self.run.linter._error_mode = True
- class _LongHelpAction(_AccessRunObjectAction):
- """Display the long help message."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--long-help",
- ) -> None:
- formatter: _HelpFormatter = self.run.linter._arg_parser._get_formatter() # type: ignore[assignment]
- # Add extra info as epilog to the help message
- self.run.linter._arg_parser.epilog = formatter.get_long_description()
- print(self.run.linter.help())
- sys.exit(0)
- class _AccessLinterObjectAction(_CallbackAction):
- """Action that has access to the Linter object."""
- def __init__(
- self,
- option_strings: Sequence[str],
- dest: str,
- nargs: None = None,
- const: None = None,
- default: None = None,
- type: None = None,
- choices: None = None,
- required: bool = False,
- help: str = "",
- metavar: str = "",
- **kwargs: PyLinter,
- ) -> None:
- self.linter = kwargs["linter"]
- super().__init__(
- option_strings,
- dest,
- 1,
- const,
- default,
- type,
- choices,
- required,
- help,
- metavar,
- )
- @abc.abstractmethod
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = None,
- ) -> None:
- raise NotImplementedError # pragma: no cover
- class _XableAction(_AccessLinterObjectAction):
- """Callback action for enabling or disabling a message."""
- def _call(
- self,
- xabling_function: Callable[[str], None],
- values: str | Sequence[Any] | None,
- option_string: str | None,
- ) -> None:
- assert isinstance(values, (tuple, list))
- for msgid in utils._check_csv(values[0]):
- try:
- xabling_function(msgid)
- except (
- exceptions.DeletedMessageError,
- exceptions.MessageBecameExtensionError,
- ) as e:
- self.linter._stashed_messages[
- (self.linter.current_name, "useless-option-value")
- ].append((option_string, str(e)))
- except exceptions.UnknownMessageError:
- self.linter._stashed_messages[
- (self.linter.current_name, "unknown-option-value")
- ].append((option_string, msgid))
- @abc.abstractmethod
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--disable",
- ) -> None:
- raise NotImplementedError # pragma: no cover
- class _DisableAction(_XableAction):
- """Callback action for disabling a message."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--disable",
- ) -> None:
- self._call(self.linter.disable, values, option_string)
- class _EnableAction(_XableAction):
- """Callback action for enabling a message."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--enable",
- ) -> None:
- self._call(self.linter.enable, values, option_string)
- class _OutputFormatAction(_AccessLinterObjectAction):
- """Callback action for setting the output format."""
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = "--enable",
- ) -> None:
- assert isinstance(values, (tuple, list))
- assert isinstance(
- values[0], str
- ), "'output-format' should be a comma separated string of reporters"
- self.linter._load_reporters(values[0])
- class _AccessParserAction(_CallbackAction):
- """Action that has access to the ArgumentParser object."""
- def __init__(
- self,
- option_strings: Sequence[str],
- dest: str,
- nargs: None = None,
- const: None = None,
- default: None = None,
- type: None = None,
- choices: None = None,
- required: bool = False,
- help: str = "",
- metavar: str = "",
- **kwargs: argparse.ArgumentParser,
- ) -> None:
- self.parser = kwargs["parser"]
- super().__init__(
- option_strings,
- dest,
- 0,
- const,
- default,
- type,
- choices,
- required,
- help,
- metavar,
- )
- @abc.abstractmethod
- def __call__(
- self,
- parser: argparse.ArgumentParser,
- namespace: argparse.Namespace,
- values: str | Sequence[Any] | None,
- option_string: str | None = None,
- ) -> None:
- raise NotImplementedError # pragma: no cover
|