summaryrefslogtreecommitdiff
path: root/pylint/config/arguments_provider.py
blob: f5aac2f1dc48f68c7d931f1dac3b150281cd0e93 (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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# 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

"""Arguments provider class used to expose options."""

from __future__ import annotations

import argparse
import optparse  # pylint: disable=deprecated-module
import warnings
from collections.abc import Iterator
from typing import Any

from pylint.config.arguments_manager import _ArgumentsManager
from pylint.typing import OptionDict, Options


class UnsupportedAction(Exception):
    """Raised by set_option when it doesn't know what to do for an action."""

    def __init__(self, *args: object) -> None:
        # TODO: 3.0: Remove deprecated exception
        warnings.warn(
            "UnsupportedAction has been deprecated and will be removed in pylint 3.0",
            DeprecationWarning,
            stacklevel=2,
        )
        super().__init__(*args)


class _ArgumentsProvider:
    """Base class for classes that provide arguments."""

    name: str
    """Name of the provider."""

    options: Options = ()
    """Options provided by this provider."""

    option_groups_descs: dict[str, str] = {}
    """Option groups of this provider and their descriptions."""

    def __init__(self, arguments_manager: _ArgumentsManager) -> None:
        self._arguments_manager = arguments_manager
        """The manager that will parse and register any options provided."""

        self._arguments_manager._register_options_provider(self)

        self._level = 0

    @property
    def level(self) -> int:
        # TODO: 3.0: Remove deprecated attribute
        warnings.warn(
            "The level attribute has been deprecated. It was used to display the checker in the help or not,"
            " and everything is displayed in the help now. It will be removed in pylint 3.0.",
            DeprecationWarning,
            stacklevel=2,
        )
        return self._level

    @level.setter
    def level(self, value: int) -> None:
        # TODO: 3.0: Remove deprecated attribute
        warnings.warn(
            "Setting the level attribute has been deprecated. It was used to display the checker "
            "in the help or not, and everything is displayed in the help now. It will be removed "
            "in pylint 3.0.",
            DeprecationWarning,
            stacklevel=2,
        )
        self._level = value

    @property
    def config(self) -> argparse.Namespace:
        # TODO: 3.0: Remove deprecated attribute
        warnings.warn(
            "The checker-specific config attribute has been deprecated. Please use "
            "'linter.config' to access the global configuration object.",
            DeprecationWarning,
            stacklevel=2,
        )
        return self._arguments_manager.config

    def load_defaults(self) -> None:  # pragma: no cover
        """DEPRECATED: Initialize the provider using default values."""
        warnings.warn(
            "load_defaults has been deprecated. Option groups should be "
            "registered by initializing an ArgumentsProvider. "
            "This automatically registers the group on the ArgumentsManager.",
            DeprecationWarning,
            stacklevel=2,
        )
        for opt, optdict in self.options:
            action = optdict.get("action")
            if action != "callback":
                # callback action have no default
                if optdict is None:
                    with warnings.catch_warnings():
                        warnings.filterwarnings("ignore", category=DeprecationWarning)
                        optdict = self.get_option_def(opt)
                default = optdict.get("default")
                self.set_option(opt, default, action, optdict)

    def option_attrname(
        self, opt: str, optdict: OptionDict | None = None
    ) -> str:  # pragma: no cover
        """DEPRECATED: Get the config attribute corresponding to opt."""
        warnings.warn(
            "option_attrname has been deprecated. It will be removed "
            "in a future release.",
            DeprecationWarning,
            stacklevel=2,
        )
        if optdict is None:
            with warnings.catch_warnings():
                warnings.filterwarnings("ignore", category=DeprecationWarning)
                optdict = self.get_option_def(opt)
        return optdict.get("dest", opt.replace("-", "_"))  # type: ignore[return-value]

    def option_value(self, opt: str) -> Any:  # pragma: no cover
        """DEPRECATED: Get the current value for the given option."""
        warnings.warn(
            "option_value has been deprecated. It will be removed "
            "in a future release.",
            DeprecationWarning,
            stacklevel=2,
        )
        return getattr(self._arguments_manager.config, opt.replace("-", "_"), None)

    def set_option(  # pragma: no cover
        self,
        optname: Any,
        value: Any,
        action: Any = None,  # pylint: disable=unused-argument
        optdict: Any = None,  # pylint: disable=unused-argument
    ) -> None:
        """DEPRECATED: Method called to set an option (registered in the options
        list).
        """
        # TODO: 3.0: Remove deprecated method.
        warnings.warn(
            "set_option has been deprecated. You can use _arguments_manager.set_option "
            "or linter.set_option to set options on the global configuration object.",
            DeprecationWarning,
            stacklevel=2,
        )
        self._arguments_manager.set_option(optname, value)

    def get_option_def(self, opt: str) -> OptionDict:  # pragma: no cover
        """DEPRECATED: Return the dictionary defining an option given its name.

        :raises OptionError: If the option isn't found.
        """
        warnings.warn(
            "get_option_def has been deprecated. It will be removed "
            "in a future release.",
            DeprecationWarning,
            stacklevel=2,
        )
        assert self.options
        for option in self.options:
            if option[0] == opt:
                return option[1]
        raise optparse.OptionError(
            f"no such option {opt} in section {self.name!r}", opt  # type: ignore[arg-type]
        )

    def options_by_section(
        self,
    ) -> Iterator[
        tuple[str, list[tuple[str, OptionDict, Any]]]
        | tuple[None, dict[str, list[tuple[str, OptionDict, Any]]]]
    ]:  # pragma: no cover
        """DEPRECATED: Return an iterator on options grouped by section.

        (section, [list of (optname, optdict, optvalue)])
        """
        # TODO 3.0: Make this function private see
        # https://github.com/PyCQA/pylint/pull/6665#discussion_r880143229
        # It's only used in '_get_global_options_documentation'
        warnings.warn(
            "options_by_section has been deprecated. It will be removed "
            "in a future release.",
            DeprecationWarning,
            stacklevel=2,
        )
        sections: dict[str, list[tuple[str, OptionDict, Any]]] = {}
        for optname, optdict in self.options:
            with warnings.catch_warnings():
                warnings.filterwarnings("ignore", category=DeprecationWarning)
                sections.setdefault(optdict.get("group"), []).append(  # type: ignore[arg-type]
                    (optname, optdict, self.option_value(optname))
                )
        if None in sections:
            yield None, sections.pop(None)  # type: ignore[call-overload]
        for section, options in sorted(sections.items()):
            yield section.upper(), options

    def options_and_values(
        self, options: Options | None = None
    ) -> Iterator[tuple[str, OptionDict, Any]]:  # pragma: no cover
        """DEPRECATED."""
        warnings.warn(
            "options_and_values has been deprecated. It will be removed "
            "in a future release.",
            DeprecationWarning,
            stacklevel=2,
        )
        if options is None:
            options = self.options
        for optname, optdict in options:
            with warnings.catch_warnings():
                warnings.filterwarnings("ignore", category=DeprecationWarning)
                yield optname, optdict, self.option_value(optname)