Mercurial > p > roundup > code
comparison roundup/configuration.py @ 6584:770503bd211e
Validate SecretOption and support validate method
Needed to validate SecretOption and verify that file is readable
and valid.
validator() now calls the validate method for each Option subclass.
To add post config load validation, just define a method
validate(self, options) for the Option subclass.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Thu, 06 Jan 2022 21:22:26 -0500 |
| parents | b1f1539c6a31 |
| children | 91ab3e0ffcd0 |
comparison
equal
deleted
inserted
replaced
| 6583:3759893f0686 | 6584:770503bd211e |
|---|---|
| 434 _val = value.lower() | 434 _val = value.lower() |
| 435 if _val in self.allowed: | 435 if _val in self.allowed: |
| 436 return _val | 436 return _val |
| 437 raise OptionValueError(self, value, self.class_description) | 437 raise OptionValueError(self, value, self.class_description) |
| 438 | 438 |
| 439 def validate(self, options): | |
| 440 | |
| 441 if self._value in ("", "xapian"): | |
| 442 try: | |
| 443 import xapian | |
| 444 except ImportError: | |
| 445 # indexer is probably '' and xapian isn't present | |
| 446 # so just return at end of method | |
| 447 pass | |
| 448 else: | |
| 449 try: | |
| 450 lang = options["INDEXER_LANGUAGE"]._value | |
| 451 xapian.Stem(lang) | |
| 452 except xapian.InvalidArgumentError: | |
| 453 import textwrap | |
| 454 lang_avail = b2s(xapian.Stem.get_available_languages()) | |
| 455 languages = textwrap.fill(_("Valid languages: ") + | |
| 456 lang_avail, 75, | |
| 457 subsequent_indent=" ") | |
| 458 raise OptionValueError(options["INDEXER_LANGUAGE"], | |
| 459 lang, languages) | |
| 460 | |
| 439 | 461 |
| 440 class MailAddressOption(Option): | 462 class MailAddressOption(Option): |
| 441 | 463 |
| 442 """Email address | 464 """Email address |
| 443 | 465 |
| 604 else: | 626 else: |
| 605 raise OptionValueError(self, _val, | 627 raise OptionValueError(self, _val, |
| 606 "Unable to read value for %s. Error opening " | 628 "Unable to read value for %s. Error opening " |
| 607 "%s: %s." % (self.name, e.filename, e.args[1])) | 629 "%s: %s." % (self.name, e.filename, e.args[1])) |
| 608 return self.str2value(_val) | 630 return self.str2value(_val) |
| 631 | |
| 632 def validate(self, options): | |
| 633 if self.name == 'MAIL_PASSWORD': | |
| 634 if options['MAIL_USERNAME']._value: | |
| 635 # MAIL_PASSWORD is an exception. It is mandatory only | |
| 636 # if MAIL_USERNAME is set. So check only if username | |
| 637 # is set. | |
| 638 try: | |
| 639 self.get() | |
| 640 except OptionUnsetError: | |
| 641 # provide error message with link to MAIL_USERNAME | |
| 642 raise OptionValueError(options["MAIL_PASSWORD"], | |
| 643 "not defined", | |
| 644 "Mail username is set, so this must be defined.") | |
| 645 else: | |
| 646 self.get() | |
| 609 | 647 |
| 610 | 648 |
| 611 class WebUrlOption(Option): | 649 class WebUrlOption(Option): |
| 612 """URL MUST start with http/https scheme and end with '/'""" | 650 """URL MUST start with http/https scheme and end with '/'""" |
| 613 | 651 |
| 1477 # mapping from option names and aliases to Option instances | 1515 # mapping from option names and aliases to Option instances |
| 1478 options = None | 1516 options = None |
| 1479 # actual name of the config file. set on load. | 1517 # actual name of the config file. set on load. |
| 1480 filepath = os.path.join(HOME, INI_FILE) | 1518 filepath = os.path.join(HOME, INI_FILE) |
| 1481 | 1519 |
| 1520 # List of option names that need additional validation after | |
| 1521 # all options are loaded. | |
| 1522 option_validators = [] | |
| 1523 | |
| 1482 def __init__(self, config_path=None, layout=None, settings=None): | 1524 def __init__(self, config_path=None, layout=None, settings=None): |
| 1483 """Initialize confing instance | 1525 """Initialize confing instance |
| 1484 | 1526 |
| 1485 Parameters: | 1527 Parameters: |
| 1486 config_path: | 1528 config_path: |
| 1549 # (section, name) key is used for writing .ini file | 1591 # (section, name) key is used for writing .ini file |
| 1550 self.options[(_section, _name)] = option | 1592 self.options[(_section, _name)] = option |
| 1551 # make the option known under all of its A.K.A.s | 1593 # make the option known under all of its A.K.A.s |
| 1552 for _name in option.aliases: | 1594 for _name in option.aliases: |
| 1553 self.options[_name] = option | 1595 self.options[_name] = option |
| 1596 | |
| 1597 if hasattr(option, 'validate'): | |
| 1598 self.option_validators.append(option.name) | |
| 1554 | 1599 |
| 1555 def update_option(self, name, klass, | 1600 def update_option(self, name, klass, |
| 1556 default=NODEFAULT, description=None): | 1601 default=NODEFAULT, description=None): |
| 1557 """Override behaviour of early created option. | 1602 """Override behaviour of early created option. |
| 1558 | 1603 |
| 1963 | 2008 |
| 1964 Used to validate settings when options are dependent | 2009 Used to validate settings when options are dependent |
| 1965 on each other. E.G. indexer_language can only be | 2010 on each other. E.G. indexer_language can only be |
| 1966 validated if xapian indexer is used. | 2011 validated if xapian indexer is used. |
| 1967 """ | 2012 """ |
| 1968 if options['INDEXER']._value in ("", "xapian"): | 2013 |
| 1969 try: | 2014 for option in self.option_validators: |
| 1970 import xapian | 2015 # validate() should throw an exception if there is an issue. |
| 1971 except ImportError: | 2016 options[option].validate(options) |
| 1972 # indexer is probably '' and xapian isn't present | |
| 1973 # so just return at end of method | |
| 1974 pass | |
| 1975 else: | |
| 1976 try: | |
| 1977 lang = options["INDEXER_LANGUAGE"]._value | |
| 1978 xapian.Stem(lang) | |
| 1979 except xapian.InvalidArgumentError: | |
| 1980 import textwrap | |
| 1981 lang_avail = b2s(xapian.Stem.get_available_languages()) | |
| 1982 languages = textwrap.fill(_("Valid languages: ") + | |
| 1983 lang_avail, 75, | |
| 1984 subsequent_indent=" ") | |
| 1985 raise OptionValueError(options["INDEXER_LANGUAGE"], | |
| 1986 lang, languages) | |
| 1987 | |
| 1988 if options['MAIL_USERNAME']._value != "": | |
| 1989 # require password to be set | |
| 1990 if options['MAIL_PASSWORD']._value is NODEFAULT: | |
| 1991 raise OptionValueError(options["MAIL_PASSWORD"], | |
| 1992 "not defined", | |
| 1993 "mail username is set, so this must be defined.") | |
| 1994 | 2017 |
| 1995 def load(self, home_dir): | 2018 def load(self, home_dir): |
| 1996 """Load configuration from path designated by home_dir argument""" | 2019 """Load configuration from path designated by home_dir argument""" |
| 1997 if os.path.isfile(os.path.join(home_dir, self.INI_FILE)): | 2020 if os.path.isfile(os.path.join(home_dir, self.INI_FILE)): |
| 1998 self.load_ini(home_dir) | 2021 self.load_ini(home_dir) |
