arguments_provider.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  2. # For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
  3. # Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt
  4. """Arguments provider class used to expose options."""
  5. from __future__ import annotations
  6. import argparse
  7. import optparse # pylint: disable=deprecated-module
  8. import warnings
  9. from collections.abc import Iterator
  10. from typing import Any
  11. from pylint.config.arguments_manager import _ArgumentsManager
  12. from pylint.typing import OptionDict, Options
  13. class UnsupportedAction(Exception):
  14. """Raised by set_option when it doesn't know what to do for an action."""
  15. def __init__(self, *args: object) -> None:
  16. # TODO: 3.0: Remove deprecated exception
  17. warnings.warn(
  18. "UnsupportedAction has been deprecated and will be removed in pylint 3.0",
  19. DeprecationWarning,
  20. stacklevel=2,
  21. )
  22. super().__init__(*args)
  23. class _ArgumentsProvider:
  24. """Base class for classes that provide arguments."""
  25. name: str
  26. """Name of the provider."""
  27. options: Options = ()
  28. """Options provided by this provider."""
  29. option_groups_descs: dict[str, str] = {}
  30. """Option groups of this provider and their descriptions."""
  31. def __init__(self, arguments_manager: _ArgumentsManager) -> None:
  32. self._arguments_manager = arguments_manager
  33. """The manager that will parse and register any options provided."""
  34. self._arguments_manager._register_options_provider(self)
  35. self._level = 0
  36. @property
  37. def level(self) -> int:
  38. # TODO: 3.0: Remove deprecated attribute
  39. warnings.warn(
  40. "The level attribute has been deprecated. It was used to display the checker in the help or not,"
  41. " and everything is displayed in the help now. It will be removed in pylint 3.0.",
  42. DeprecationWarning,
  43. stacklevel=2,
  44. )
  45. return self._level
  46. @level.setter
  47. def level(self, value: int) -> None:
  48. # TODO: 3.0: Remove deprecated attribute
  49. warnings.warn(
  50. "Setting the level attribute has been deprecated. It was used to display the checker "
  51. "in the help or not, and everything is displayed in the help now. It will be removed "
  52. "in pylint 3.0.",
  53. DeprecationWarning,
  54. stacklevel=2,
  55. )
  56. self._level = value
  57. @property
  58. def config(self) -> argparse.Namespace:
  59. # TODO: 3.0: Remove deprecated attribute
  60. warnings.warn(
  61. "The checker-specific config attribute has been deprecated. Please use "
  62. "'linter.config' to access the global configuration object.",
  63. DeprecationWarning,
  64. stacklevel=2,
  65. )
  66. return self._arguments_manager.config
  67. def load_defaults(self) -> None: # pragma: no cover
  68. """DEPRECATED: Initialize the provider using default values."""
  69. warnings.warn(
  70. "load_defaults has been deprecated. Option groups should be "
  71. "registered by initializing an ArgumentsProvider. "
  72. "This automatically registers the group on the ArgumentsManager.",
  73. DeprecationWarning,
  74. stacklevel=2,
  75. )
  76. for opt, optdict in self.options:
  77. action = optdict.get("action")
  78. if action != "callback":
  79. # callback action have no default
  80. if optdict is None:
  81. with warnings.catch_warnings():
  82. warnings.filterwarnings("ignore", category=DeprecationWarning)
  83. optdict = self.get_option_def(opt)
  84. default = optdict.get("default")
  85. self.set_option(opt, default, action, optdict)
  86. def option_attrname(
  87. self, opt: str, optdict: OptionDict | None = None
  88. ) -> str: # pragma: no cover
  89. """DEPRECATED: Get the config attribute corresponding to opt."""
  90. warnings.warn(
  91. "option_attrname has been deprecated. It will be removed "
  92. "in a future release.",
  93. DeprecationWarning,
  94. stacklevel=2,
  95. )
  96. if optdict is None:
  97. with warnings.catch_warnings():
  98. warnings.filterwarnings("ignore", category=DeprecationWarning)
  99. optdict = self.get_option_def(opt)
  100. return optdict.get("dest", opt.replace("-", "_")) # type: ignore[return-value]
  101. def option_value(self, opt: str) -> Any: # pragma: no cover
  102. """DEPRECATED: Get the current value for the given option."""
  103. warnings.warn(
  104. "option_value has been deprecated. It will be removed "
  105. "in a future release.",
  106. DeprecationWarning,
  107. stacklevel=2,
  108. )
  109. return getattr(self._arguments_manager.config, opt.replace("-", "_"), None)
  110. def set_option( # pragma: no cover
  111. self,
  112. optname: Any,
  113. value: Any,
  114. action: Any = None, # pylint: disable=unused-argument
  115. optdict: Any = None, # pylint: disable=unused-argument
  116. ) -> None:
  117. """DEPRECATED: Method called to set an option (registered in the options
  118. list).
  119. """
  120. # TODO: 3.0: Remove deprecated method.
  121. warnings.warn(
  122. "set_option has been deprecated. You can use _arguments_manager.set_option "
  123. "or linter.set_option to set options on the global configuration object.",
  124. DeprecationWarning,
  125. stacklevel=2,
  126. )
  127. self._arguments_manager.set_option(optname, value)
  128. def get_option_def(self, opt: str) -> OptionDict: # pragma: no cover
  129. """DEPRECATED: Return the dictionary defining an option given its name.
  130. :raises OptionError: If the option isn't found.
  131. """
  132. warnings.warn(
  133. "get_option_def has been deprecated. It will be removed "
  134. "in a future release.",
  135. DeprecationWarning,
  136. stacklevel=2,
  137. )
  138. assert self.options
  139. for option in self.options:
  140. if option[0] == opt:
  141. return option[1]
  142. raise optparse.OptionError(
  143. f"no such option {opt} in section {self.name!r}", opt # type: ignore[arg-type]
  144. )
  145. def options_by_section(
  146. self,
  147. ) -> Iterator[
  148. tuple[str, list[tuple[str, OptionDict, Any]]]
  149. | tuple[None, dict[str, list[tuple[str, OptionDict, Any]]]]
  150. ]: # pragma: no cover
  151. """DEPRECATED: Return an iterator on options grouped by section.
  152. (section, [list of (optname, optdict, optvalue)])
  153. """
  154. # TODO 3.0: Make this function private see
  155. # https://github.com/PyCQA/pylint/pull/6665#discussion_r880143229
  156. # It's only used in '_get_global_options_documentation'
  157. warnings.warn(
  158. "options_by_section has been deprecated. It will be removed "
  159. "in a future release.",
  160. DeprecationWarning,
  161. stacklevel=2,
  162. )
  163. sections: dict[str, list[tuple[str, OptionDict, Any]]] = {}
  164. for optname, optdict in self.options:
  165. with warnings.catch_warnings():
  166. warnings.filterwarnings("ignore", category=DeprecationWarning)
  167. sections.setdefault(optdict.get("group"), []).append( # type: ignore[arg-type]
  168. (optname, optdict, self.option_value(optname))
  169. )
  170. if None in sections:
  171. yield None, sections.pop(None) # type: ignore[call-overload]
  172. for section, options in sorted(sections.items()):
  173. yield section.upper(), options
  174. def options_and_values(
  175. self, options: Options | None = None
  176. ) -> Iterator[tuple[str, OptionDict, Any]]: # pragma: no cover
  177. """DEPRECATED."""
  178. warnings.warn(
  179. "options_and_values has been deprecated. It will be removed "
  180. "in a future release.",
  181. DeprecationWarning,
  182. stacklevel=2,
  183. )
  184. if options is None:
  185. options = self.options
  186. for optname, optdict in options:
  187. with warnings.catch_warnings():
  188. warnings.filterwarnings("ignore", category=DeprecationWarning)
  189. yield optname, optdict, self.option_value(optname)