Mercurial > p > roundup > code
changeset 6356:c26b9ce33ae3
issue2551123 - validate indexer_language in configuration.py
Was validated in backends/indexer_xapian.py which would throw
an error on access rather than on start.
Added validator function to CoreConfig class that runs after
config.ini is read. At this time we have access to the indexer setting
so can determine if xapian is actually going to be used.
Moved test into test/test_config.py and pulled validation code from
indexer_xapian.py and test/test_indexer.py.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Mon, 29 Mar 2021 22:47:54 -0400 |
| parents | ac5a6ffa377b |
| children | c985ed52ca2d |
| files | roundup/backends/indexer_xapian.py roundup/configuration.py test/test_config.py test/test_indexer.py |
| diffstat | 4 files changed, 88 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/roundup/backends/indexer_xapian.py Mon Mar 29 20:43:22 2021 -0400 +++ b/roundup/backends/indexer_xapian.py Mon Mar 29 22:47:54 2021 -0400 @@ -22,18 +22,6 @@ self.reindex = 0 self.transaction_active = False - # self.language defined in IndexerBase.__init__ - # validate it here - try: - xapian.Stem(self.language) - except xapian.InvalidArgumentError: - raise ValueError( - _("Invalid indexer_language %(lang)s for xapian indexer\n" - "Valid languages: %(valid)s") % { - "lang": self.language, - "valid": b2s(xapian.Stem.get_available_languages()) } - ) - def _get_database(self): index = os.path.join(self.db_path, 'text-index') for n in range(10):
--- a/roundup/configuration.py Mon Mar 29 20:43:22 2021 -0400 +++ b/roundup/configuration.py Mon Mar 29 22:47:54 2021 -0400 @@ -20,6 +20,7 @@ from roundup.anypy.strings import b2s import roundup.anypy.random_ as random_ import binascii +from roundup.i18n import _ from roundup.backends import list_backends @@ -1844,12 +1845,49 @@ logger.handlers = [hdlr] logger.setLevel(self["LOGGING_LEVEL"] or "ERROR") + def validator(self, options): + """ Validate options once all options are loaded. + + Used to validate settings when options are dependent + on each other. E.G. indexer_language can only be + validated if xapian indexer is used. + """ + if options['INDEXER']._value in ("", "xapian"): + try: + import xapian + except ImportError: + # indexer is probably '' and xapian isn't present + # so just return at end of method + pass + else: + try: + lang = options["INDEXER_LANGUAGE"]._value + xapian.Stem(lang) + except xapian.InvalidArgumentError: + import textwrap + lang_avail = b2s(xapian.Stem.get_available_languages()) + languages = textwrap.fill(_("Valid languages: ") + + lang_avail, 75, + subsequent_indent=" ") + raise ValueError( + _("Invalid indexer_language '%(lang)s' in config.ini for xapian indexer\n\n" + "%(valid)s") % { + "lang": lang, + "valid": languages + } + ) + def load(self, home_dir): """Load configuration from path designated by home_dir argument""" if os.path.isfile(os.path.join(home_dir, self.INI_FILE)): self.load_ini(home_dir) else: raise NoConfigError(home_dir) + + # validator does inter-setting validation checks. + # when there are dependencies between options. + self.validator(self.options) + self.init_logging() self.ext = UserConfig(os.path.join(home_dir, "extensions")) self.detectors = UserConfig(os.path.join(home_dir, "detectors"))
--- a/test/test_config.py Mon Mar 29 20:43:22 2021 -0400 +++ b/test/test_config.py Mon Mar 29 22:47:54 2021 -0400 @@ -284,3 +284,53 @@ self.dirname) + def testInvalidIndexer_language(self): + """ make sure we have a reasonable error message if + invalid language is specified """ + + # change the indexer_language value to an invalid value. + import fileinput + for line in fileinput.input(os.path.join(self.dirname, "config.ini"), + inplace=True): + if line.startswith("indexer_language = "): + print("indexer_language = NO_LANG") + continue + print(line[:-1]) # remove trailing \n + + config = configuration.CoreConfig() + + # Note this should raise OptionValueError, but + # the test fot this error occurs too late to have + # a valid option still available. So raise ValueError. + with self.assertRaises(ValueError) as cm: + config.load(self.dirname) + + print(cm.exception) + self.assertIn("ValueError", repr(cm.exception)) + # look for failing language + self.assertIn("NO_LANG", cm.exception.args[0]) + # look for supported language + self.assertIn("english", cm.exception.args[0]) + + def testLoadConfig(self): + """ run load to validate config """ + + config = configuration.CoreConfig() + + config.load(self.dirname) + + with self.assertRaises(configuration.InvalidOptionError) as cm: + c = config['indexer_language'] + print(cm.exception) + self.assertIn("indexer_language", repr(cm.exception)) + + self.assertEqual(config['HTML_VERSION'], 'html4') + self.assertEqual(config[('main', 'html_version')], 'html4') + + self.assertEqual(config['WEB_COOKIE_TAKES_PRECEDENCE'], 0) + self.assertEqual(config[('web','cookie_takes_precedence')], 0) + + + + +
--- a/test/test_indexer.py Mon Mar 29 20:43:22 2021 -0400 +++ b/test/test_indexer.py Mon Mar 29 22:47:54 2021 -0400 @@ -195,26 +195,6 @@ self.dex = Indexer(db) def tearDown(self): shutil.rmtree('test-index') - def test_invalid_language(self): - """ make sure we have a reasonable error message if - invalid language is specified """ - l = db.config[('main', 'indexer_language')] - db.config[('main', 'indexer_language')] = "NO_LANG" - from roundup.backends.indexer_xapian import Indexer - with self.assertRaises(ValueError) as cm: - Indexer(db) - # note if Indexer(db) doesn't return ValueError - # all Xapian tests after this point will fail. - # because a valid langage will not be set. - # reset the valid language. - db.config[('main', 'indexer_language')] = l - - print(cm) - self.assertIn("ValueError", repr(cm.exception)) - # look for failing language - self.assertIn("NO_LANG", cm.exception.args[0]) - # look for supported language - self.assertIn("english", cm.exception.args[0]) class RDBMSIndexerTest(object): def setUp(self):
