Report error when multi-valued setting has one value
authorKarl O. Pinc <kop@karlpinc.com>
Sun, 6 Dec 2020 20:57:33 +0000 (14:57 -0600)
committerKarl O. Pinc <kop@karlpinc.com>
Sun, 6 Dec 2020 21:27:18 +0000 (15:27 -0600)
src/pgwui_server/exceptions.py
src/pgwui_server/pgwui_server.py
tests/test_pgwui_server.py

index d312dd1a89792265ef8e509ec81e6798aa7972bc..5ab339d5b2012bb9ff66c7fc0d2192e00bd4db9f 100644 (file)
@@ -42,6 +42,19 @@ class AutoconfigureConflict(ServerInfo):
             'Autoconfigure is True and there is a pyramid.include setting')
 
 
+class MissingEqualError(ServerError):
+    def __init__(self, line):
+        super().__init__(
+            'Expecting text containing an equals (=) sign, but '
+            f'instead got ({line})')
+
+
+class BadValueError(ServerError):
+    def __init__(self, setting, ex):
+        super().__init__(
+            f'Bad setting value supplied to ({setting}): {ex}')
+
+
 class BadSettingsAbort(ServerError):
     def __init__(self):
         super().__init__('Aborting due to bad setting(s)')
index b950206cb2130ffeafe0349c746166c99387d2ca..46615f39e49bda5afef77f6c3bb45c17532914b3 100644 (file)
@@ -83,7 +83,10 @@ def parse_multiline_assignments(lines, result):
             stripped = line.lstrip()
             if stripped != '':
                 # Multiple values on different lines means a list
-                key, val = result[-1]
+                try:
+                    key, val = result[-1]
+                except IndexError:
+                    raise server_ex.MissingEqualError(stripped)
                 if not isinstance(val, list):
                     val = [val]
                 val.append(stripped)
@@ -102,12 +105,15 @@ def parse_assignments(lines):
     return result
 
 
-def dot_to_multiline_setting(settings, key, pgwui_key):
+def dot_to_multiline_setting(errors, settings, key, pgwui_key):
     '''Put a multi-line setting into its own dict,
     adding to what's already there
     '''
     multi_setting = settings['pgwui'].setdefault(pgwui_key, dict())
-    multi_setting.update(dict(parse_assignments(settings[key])))
+    try:
+        multi_setting.update(dict(parse_assignments(settings[key])))
+    except server_ex.MissingEqualError as ex:
+        errors.append(server_ex.BadValueError(f'pgwui:{pgwui_key}', ex))
     del settings[key]
 
 
@@ -115,7 +121,7 @@ def component_setting_into_dict(
         errors, component_checkers, key, settings, component):
     '''Put a component's settings in its own dict and validate them
     '''
-    comp_settings = dot_to_multiline_setting(settings, key, component)
+    comp_settings = dot_to_multiline_setting(errors, settings, key, component)
     if component in component_checkers:
         errors.extend(
             component_checkers[component](comp_settings))
@@ -135,7 +141,7 @@ def setting_into_dict(
             if new_key in SETTINGS:
                 dot_to_dict(settings, key, new_key)
             elif new_key in MULTI_SETTINGS:
-                dot_to_multiline_setting(settings, key, new_key)
+                dot_to_multiline_setting(errors, settings, key, new_key)
             else:
                 errors.append(common_ex.UnknownSettingKeyError(key))
 
index ac449215c7f493ddcd7815acace7c543f0405bcd..7cd136b080817b6ddf8cb6ca544e0774b3b84485 100644 (file)
@@ -33,6 +33,7 @@ from pgwui_testing import testing
 
 import pgwui_server.checkset
 import pgwui_server.pgwui_server as pgwui_server
+import pgwui_server.exceptions as server_ex
 
 
 # Mark all tests with "unittest"
@@ -79,6 +80,7 @@ mock_add_routes = testing.make_mock_fixture(
 def test_dot_to_multiline_setting_new(mock_parse_assignments):
     '''Adds a new dict and puts the settings in it
     '''
+    errors = []
     comp_settings = {'foo': 'foo', 'bar': 'bar'}
     component = 'pgwui_component'
     key = 'pgwui.' + component
@@ -88,14 +90,16 @@ def test_dot_to_multiline_setting_new(mock_parse_assignments):
 
     mock_parse_assignments.return_value = comp_settings
     pgwui_server.dot_to_multiline_setting(
-        settings, key, component)
+        errors, settings, key, component)
 
     assert settings == expected
+    assert errors == []
 
 
 def test_dot_to_multiline_setting_old(mock_parse_assignments):
     '''Extends an existing dict in the settings
     '''
+    errors = []
     comp_settings = {'foo': 'foo', 'bar': 'bar'}
     component = 'pgwui_component'
     key = 'pgwui.' + component
@@ -106,9 +110,27 @@ def test_dot_to_multiline_setting_old(mock_parse_assignments):
 
     mock_parse_assignments.return_value = comp_settings
     pgwui_server.dot_to_multiline_setting(
-        settings, key, component)
+        errors, settings, key, component)
 
     assert settings == expected
+    assert errors == []
+
+
+def test_dot_to_multiline_setting_bad(mock_parse_assignments):
+    '''When the value is bad we get the expected error
+    '''
+    errors = []
+    component = 'pgwui_component'
+    key = 'pgwui.' + component
+    settings = {'pgwui': {},
+                key: 'ignored'}
+
+    mock_parse_assignments.side_effect = server_ex.MissingEqualError('text')
+    pgwui_server.dot_to_multiline_setting(
+        errors, settings, key, component)
+
+    assert len(errors) == 1
+    assert isinstance(errors[0], server_ex.BadValueError)
 
 
 mock_dot_to_multiline_setting = testing.make_mock_fixture(
@@ -192,6 +214,13 @@ def test_parse_multiline_assignments_str():
                       ('key3', 'value3=withequals')]
 
 
+def test_parse_multiline_assignments_no_equal():
+    '''When the line contains no equal sign the right exception is raised
+    '''
+    with pytest.raises(server_ex.MissingEqualError):
+        pgwui_server.parse_multiline_assignments('noequal\n', [])
+
+
 mock_parse_multiline_assignments = testing.make_mock_fixture(
     pgwui_server, 'parse_multiline_assignments')