options_provider_mixin.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  2. # For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
  4. # type: ignore # Deprecated module.
  5. import optparse # pylint: disable=deprecated-module
  6. import warnings
  7. from pylint.config.callback_actions import _CallbackAction
  8. from pylint.config.option import _validate
  9. from pylint.typing import Options
  10. class UnsupportedAction(Exception):
  11. """Raised by set_option when it doesn't know what to do for an action."""
  12. class OptionsProviderMixIn:
  13. """Mixin to provide options to an OptionsManager."""
  14. # those attributes should be overridden
  15. name = "default"
  16. options: Options = ()
  17. level = 0
  18. def __init__(self):
  19. # TODO: 3.0: Remove deprecated class
  20. warnings.warn(
  21. "OptionsProviderMixIn has been deprecated and will be removed in pylint 3.0",
  22. DeprecationWarning,
  23. stacklevel=2,
  24. )
  25. self.config = optparse.Values()
  26. self.load_defaults()
  27. def load_defaults(self):
  28. """Initialize the provider using default values."""
  29. for opt, optdict in self.options:
  30. action = optdict.get("action")
  31. if action != "callback":
  32. # callback action have no default
  33. if optdict is None:
  34. optdict = self.get_option_def(opt)
  35. default = optdict.get("default")
  36. self.set_option(opt, default, action, optdict)
  37. def option_attrname(self, opt, optdict=None):
  38. """Get the config attribute corresponding to opt."""
  39. if optdict is None:
  40. optdict = self.get_option_def(opt)
  41. return optdict.get("dest", opt.replace("-", "_"))
  42. def option_value(self, opt):
  43. """Get the current value for the given option."""
  44. return getattr(self.config, self.option_attrname(opt), None)
  45. def set_option(self, optname, value, action=None, optdict=None):
  46. """Method called to set an option (registered in the options list)."""
  47. if optdict is None:
  48. optdict = self.get_option_def(optname)
  49. if value is not None:
  50. value = _validate(value, optdict, optname)
  51. if action is None:
  52. action = optdict.get("action", "store")
  53. if action == "store":
  54. setattr(self.config, self.option_attrname(optname, optdict), value)
  55. elif action in {"store_true", "count"}:
  56. setattr(self.config, self.option_attrname(optname, optdict), value)
  57. elif action == "store_false":
  58. setattr(self.config, self.option_attrname(optname, optdict), value)
  59. elif action == "append":
  60. optname = self.option_attrname(optname, optdict)
  61. _list = getattr(self.config, optname, None)
  62. if _list is None:
  63. if isinstance(value, (list, tuple)):
  64. _list = value
  65. elif value is not None:
  66. _list = [value]
  67. setattr(self.config, optname, _list)
  68. elif isinstance(_list, tuple):
  69. setattr(self.config, optname, _list + (value,))
  70. else:
  71. _list.append(value)
  72. elif (
  73. action == "callback"
  74. or (not isinstance(action, str))
  75. and issubclass(action, _CallbackAction)
  76. ):
  77. return
  78. else:
  79. raise UnsupportedAction(action)
  80. def get_option_def(self, opt):
  81. """Return the dictionary defining an option given its name."""
  82. assert self.options
  83. for option in self.options:
  84. if option[0] == opt:
  85. return option[1]
  86. raise optparse.OptionError(
  87. f"no such option {opt} in section {self.name!r}", opt
  88. )
  89. def options_by_section(self):
  90. """Return an iterator on options grouped by section.
  91. (section, [list of (optname, optdict, optvalue)])
  92. """
  93. sections = {}
  94. for optname, optdict in self.options:
  95. sections.setdefault(optdict.get("group"), []).append(
  96. (optname, optdict, self.option_value(optname))
  97. )
  98. if None in sections:
  99. yield None, sections.pop(None)
  100. for section, options in sorted(sections.items()):
  101. yield section.upper(), options
  102. def options_and_values(self, options=None):
  103. if options is None:
  104. options = self.options
  105. for optname, optdict in options:
  106. yield optname, optdict, self.option_value(optname)