options_provider_mixin.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. import optparse # pylint: disable=deprecated-module
  4. from typing import Any, Dict, Tuple
  5. from pylint.config.option import _validate
  6. class UnsupportedAction(Exception):
  7. """raised by set_option when it doesn't know what to do for an action"""
  8. class OptionsProviderMixIn:
  9. """Mixin to provide options to an OptionsManager"""
  10. # those attributes should be overridden
  11. priority = -1
  12. name = "default"
  13. options: Tuple[Tuple[str, Dict[str, Any]], ...] = ()
  14. level = 0
  15. def __init__(self):
  16. self.config = optparse.Values()
  17. self.load_defaults()
  18. def load_defaults(self):
  19. """initialize the provider using default values"""
  20. for opt, optdict in self.options:
  21. action = optdict.get("action")
  22. if action != "callback":
  23. # callback action have no default
  24. if optdict is None:
  25. optdict = self.get_option_def(opt)
  26. default = optdict.get("default")
  27. self.set_option(opt, default, action, optdict)
  28. def option_attrname(self, opt, optdict=None):
  29. """get the config attribute corresponding to opt"""
  30. if optdict is None:
  31. optdict = self.get_option_def(opt)
  32. return optdict.get("dest", opt.replace("-", "_"))
  33. def option_value(self, opt):
  34. """get the current value for the given option"""
  35. return getattr(self.config, self.option_attrname(opt), None)
  36. def set_option(self, optname, value, action=None, optdict=None):
  37. """method called to set an option (registered in the options list)"""
  38. if optdict is None:
  39. optdict = self.get_option_def(optname)
  40. if value is not None:
  41. value = _validate(value, optdict, optname)
  42. if action is None:
  43. action = optdict.get("action", "store")
  44. if action == "store":
  45. setattr(self.config, self.option_attrname(optname, optdict), value)
  46. elif action in {"store_true", "count"}:
  47. setattr(self.config, self.option_attrname(optname, optdict), 0)
  48. elif action == "store_false":
  49. setattr(self.config, self.option_attrname(optname, optdict), 1)
  50. elif action == "append":
  51. optname = self.option_attrname(optname, optdict)
  52. _list = getattr(self.config, optname, None)
  53. if _list is None:
  54. if isinstance(value, (list, tuple)):
  55. _list = value
  56. elif value is not None:
  57. _list = []
  58. _list.append(value)
  59. setattr(self.config, optname, _list)
  60. elif isinstance(_list, tuple):
  61. setattr(self.config, optname, _list + (value,))
  62. else:
  63. _list.append(value)
  64. elif action == "callback":
  65. optdict["callback"](None, optname, value, None)
  66. else:
  67. raise UnsupportedAction(action)
  68. def get_option_def(self, opt):
  69. """return the dictionary defining an option given its name"""
  70. assert self.options
  71. for option in self.options:
  72. if option[0] == opt:
  73. return option[1]
  74. raise optparse.OptionError(
  75. f"no such option {opt} in section {self.name!r}", opt
  76. )
  77. def options_by_section(self):
  78. """return an iterator on options grouped by section
  79. (section, [list of (optname, optdict, optvalue)])
  80. """
  81. sections = {}
  82. for optname, optdict in self.options:
  83. sections.setdefault(optdict.get("group"), []).append(
  84. (optname, optdict, self.option_value(optname))
  85. )
  86. if None in sections:
  87. yield None, sections.pop(None)
  88. for section, options in sorted(sections.items()):
  89. yield section.upper(), options
  90. def options_and_values(self, options=None):
  91. if options is None:
  92. options = self.options
  93. for optname, optdict in options:
  94. yield (optname, optdict, self.option_value(optname))