Skip to content

Commit 6563d39

Browse files
committed
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.
1 parent 16e3af4 commit 6563d39

File tree

4 files changed

+88
-32
lines changed

4 files changed

+88
-32
lines changed

roundup/backends/indexer_xapian.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,6 @@ def __init__(self, db):
2222
self.reindex = 0
2323
self.transaction_active = False
2424

25-
# self.language defined in IndexerBase.__init__
26-
# validate it here
27-
try:
28-
xapian.Stem(self.language)
29-
except xapian.InvalidArgumentError:
30-
raise ValueError(
31-
_("Invalid indexer_language %(lang)s for xapian indexer\n"
32-
"Valid languages: %(valid)s") % {
33-
"lang": self.language,
34-
"valid": b2s(xapian.Stem.get_available_languages()) }
35-
)
36-
3725
def _get_database(self):
3826
index = os.path.join(self.db_path, 'text-index')
3927
for n in range(10):

roundup/configuration.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from roundup.anypy.strings import b2s
2121
import roundup.anypy.random_ as random_
2222
import binascii
23+
from roundup.i18n import _
2324

2425
from roundup.backends import list_backends
2526

@@ -1844,12 +1845,49 @@ def init_logging(self):
18441845
logger.handlers = [hdlr]
18451846
logger.setLevel(self["LOGGING_LEVEL"] or "ERROR")
18461847

1848+
def validator(self, options):
1849+
""" Validate options once all options are loaded.
1850+
1851+
Used to validate settings when options are dependent
1852+
on each other. E.G. indexer_language can only be
1853+
validated if xapian indexer is used.
1854+
"""
1855+
if options['INDEXER']._value in ("", "xapian"):
1856+
try:
1857+
import xapian
1858+
except ImportError:
1859+
# indexer is probably '' and xapian isn't present
1860+
# so just return at end of method
1861+
pass
1862+
else:
1863+
try:
1864+
lang = options["INDEXER_LANGUAGE"]._value
1865+
xapian.Stem(lang)
1866+
except xapian.InvalidArgumentError:
1867+
import textwrap
1868+
lang_avail = b2s(xapian.Stem.get_available_languages())
1869+
languages = textwrap.fill(_("Valid languages: ") +
1870+
lang_avail, 75,
1871+
subsequent_indent=" ")
1872+
raise ValueError(
1873+
_("Invalid indexer_language '%(lang)s' in config.ini for xapian indexer\n\n"
1874+
"%(valid)s") % {
1875+
"lang": lang,
1876+
"valid": languages
1877+
}
1878+
)
1879+
18471880
def load(self, home_dir):
18481881
"""Load configuration from path designated by home_dir argument"""
18491882
if os.path.isfile(os.path.join(home_dir, self.INI_FILE)):
18501883
self.load_ini(home_dir)
18511884
else:
18521885
raise NoConfigError(home_dir)
1886+
1887+
# validator does inter-setting validation checks.
1888+
# when there are dependencies between options.
1889+
self.validator(self.options)
1890+
18531891
self.init_logging()
18541892
self.ext = UserConfig(os.path.join(home_dir, "extensions"))
18551893
self.detectors = UserConfig(os.path.join(home_dir, "detectors"))

test/test_config.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,53 @@ def testNoDBInConfig(self):
284284
self.dirname)
285285

286286

287+
def testInvalidIndexer_language(self):
288+
""" make sure we have a reasonable error message if
289+
invalid language is specified """
290+
291+
# change the indexer_language value to an invalid value.
292+
import fileinput
293+
for line in fileinput.input(os.path.join(self.dirname, "config.ini"),
294+
inplace=True):
295+
if line.startswith("indexer_language = "):
296+
print("indexer_language = NO_LANG")
297+
continue
298+
print(line[:-1]) # remove trailing \n
299+
300+
config = configuration.CoreConfig()
301+
302+
# Note this should raise OptionValueError, but
303+
# the test fot this error occurs too late to have
304+
# a valid option still available. So raise ValueError.
305+
with self.assertRaises(ValueError) as cm:
306+
config.load(self.dirname)
307+
308+
print(cm.exception)
309+
self.assertIn("ValueError", repr(cm.exception))
310+
# look for failing language
311+
self.assertIn("NO_LANG", cm.exception.args[0])
312+
# look for supported language
313+
self.assertIn("english", cm.exception.args[0])
314+
315+
def testLoadConfig(self):
316+
""" run load to validate config """
317+
318+
config = configuration.CoreConfig()
319+
320+
config.load(self.dirname)
321+
322+
with self.assertRaises(configuration.InvalidOptionError) as cm:
323+
c = config['indexer_language']
324+
print(cm.exception)
325+
self.assertIn("indexer_language", repr(cm.exception))
326+
327+
self.assertEqual(config['HTML_VERSION'], 'html4')
328+
self.assertEqual(config[('main', 'html_version')], 'html4')
329+
330+
self.assertEqual(config['WEB_COOKIE_TAKES_PRECEDENCE'], 0)
331+
self.assertEqual(config[('web','cookie_takes_precedence')], 0)
332+
333+
334+
335+
336+

test/test_indexer.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -195,26 +195,6 @@ def setUp(self):
195195
self.dex = Indexer(db)
196196
def tearDown(self):
197197
shutil.rmtree('test-index')
198-
def test_invalid_language(self):
199-
""" make sure we have a reasonable error message if
200-
invalid language is specified """
201-
l = db.config[('main', 'indexer_language')]
202-
db.config[('main', 'indexer_language')] = "NO_LANG"
203-
from roundup.backends.indexer_xapian import Indexer
204-
with self.assertRaises(ValueError) as cm:
205-
Indexer(db)
206-
# note if Indexer(db) doesn't return ValueError
207-
# all Xapian tests after this point will fail.
208-
# because a valid langage will not be set.
209-
# reset the valid language.
210-
db.config[('main', 'indexer_language')] = l
211-
212-
print(cm)
213-
self.assertIn("ValueError", repr(cm.exception))
214-
# look for failing language
215-
self.assertIn("NO_LANG", cm.exception.args[0])
216-
# look for supported language
217-
self.assertIn("english", cm.exception.args[0])
218198

219199
class RDBMSIndexerTest(object):
220200
def setUp(self):

0 commit comments

Comments
 (0)