home · contact · privacy
Simplify InputParser code/usage.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 8 Aug 2024 03:40:51 +0000 (05:40 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 8 Aug 2024 03:40:51 +0000 (05:40 +0200)
plomtask/http.py
tests/conditions.py
tests/misc.py

index 2c8eecbe07bf2cb53284a41d885d47494656b2aa..25e377de6cbdef845a7323dbfc1ce6faaf2eac23 100644 (file)
@@ -36,82 +36,69 @@ class TaskServer(HTTPServer):
 class InputsParser:
     """Wrapper for validating and retrieving dict-like HTTP inputs."""
 
-    def __init__(self, dict_: dict[str, list[str]],
-                 strictness: bool = True) -> None:
+    def __init__(self, dict_: dict[str, list[str]]) -> None:
         self.inputs = dict_
-        self.strict = strictness  # return None on absence of key, or fail?
 
-    def get_str(self, key: str, default: str = '',
-                ignore_strict: bool = False) -> str:
-        """Retrieve single/first string value of key, or default."""
-        if key not in self.inputs.keys() or 0 == len(self.inputs[key]):
-            if self.strict and not ignore_strict:
-                raise NotFoundException(f'no value found for key {key}')
-            return default
-        return self.inputs[key][0]
+    def get_all_str(self, key: str) -> list[str]:
+        """Retrieve list of string values at key (empty if no key)."""
+        if key not in self.inputs.keys():
+            return []
+        return self.inputs[key]
 
-    def get_first_strings_starting(self, prefix: str) -> dict[str, str]:
-        """Retrieve dict of (first) strings at key starting with prefix."""
-        ret = {}
-        for key in [k for k in self.inputs.keys() if k.startswith(prefix)]:
-            ret[key] = self.inputs[key][0]
-        return ret
+    def get_all_int(self, key: str) -> list[int]:
+        """Retrieve list of int values at key."""
+        all_str = self.get_all_str(key)
+        try:
+            return [int(s) for s in all_str if len(s) > 0]
+        except ValueError as e:
+            msg = f'cannot int a form field value for key {key} in: {all_str}'
+            raise BadFormatException(msg) from e
 
-    def get_int(self, key: str) -> int:
-        """Retrieve single/first value of key as int, error if empty."""
-        val = self.get_int_or_none(key)
-        if val is None:
-            raise BadFormatException(f'unexpected empty value for: {key}')
-        return val
+    def get_str(self, key: str, default: str | None = None) -> str | None:
+        """Retrieve single/first string value of key, or default."""
+        vals = self.get_all_str(key)
+        if vals:
+            return vals[0]
+        return default
+
+    def get_str_or_fail(self, key: str, default: str | None = None) -> str:
+        """Retrieve first string value of key, if none: fail or default."""
+        vals = self.get_all_str(key)
+        if not vals:
+            if default is not None:
+                return default
+            raise BadFormatException(f'no value found for key: {key}')
+        return vals[0]
 
     def get_int_or_none(self, key: str) -> int | None:
         """Retrieve single/first value of key as int, return None if empty."""
-        val = self.get_str(key, ignore_strict=True)
+        val = self.get_str_or_fail(key, '')
         if val == '':
             return None
         try:
             return int(val)
-        except ValueError as e:
+        except (ValueError, TypeError) as e:
             msg = f'cannot int form field value for key {key}: {val}'
             raise BadFormatException(msg) from e
 
-    def get_float(self, key: str) -> float:
-        """Retrieve float value of key from self.postvars."""
-        val = self.get_str(key)
-        try:
-            return float(val)
-        except ValueError as e:
-            msg = f'cannot float form field value for key {key}: {val}'
-            raise BadFormatException(msg) from e
-
-    def get_float_or_none(self, key: str) -> float | None:
-        """Retrieve float value of key from self.postvars, None if empty."""
-        val = self.get_str(key)
-        if '' == val:
-            return None
-        try:
-            return float(val)
-        except ValueError as e:
-            msg = f'cannot float form field value for key {key}: {val}'
-            raise BadFormatException(msg) from e
-
     def get_bool(self, key: str) -> bool:
-        """Return if key occurs and maps to a boolean Truth."""
-        return bool(self.get_all_str(key))
+        """Return if key occurs _and_ its value maps to a boolean Truth."""
+        return self.get_str(key) not in {None, 'False'}
 
-    def get_all_str(self, key: str) -> list[str]:
-        """Retrieve list of string values at key."""
-        if key not in self.inputs.keys():
-            return []
-        return self.inputs[key]
+    def get_firsts_of_key_prefixed(self, prefix: str) -> dict[str, str]:
+        """Retrieve dict of (first) strings at key starting with prefix."""
+        ret = {}
+        for key in [k for k in self.inputs.keys() if k.startswith(prefix)]:
+            ret[key] = self.inputs[key][0]
+        return ret
 
-    def get_all_int(self, key: str) -> list[int]:
-        """Retrieve list of int values at key."""
-        all_str = self.get_all_str(key)
+    def get_float_or_fail(self, key: str) -> float:
+        """Retrieve float value of key from self.postvars, fail if none."""
+        val = self.get_str_or_fail(key)
         try:
-            return [int(s) for s in all_str if len(s) > 0]
+            return float(val)
         except ValueError as e:
-            msg = f'cannot int a form field value for key {key} in: {all_str}'
+            msg = f'cannot float form field value for key {key}: {val}'
             raise BadFormatException(msg) from e
 
     def get_all_floats_or_nones(self, key: str) -> list[float | None]:
@@ -135,7 +122,7 @@ class TaskHandler(BaseHTTPRequestHandler):
     server: TaskServer
     conn: DatabaseConnection
     _site: str
-    _form_data: InputsParser
+    _form: InputsParser
     _params: InputsParser
 
     def _send_page(
@@ -253,8 +240,10 @@ class TaskHandler(BaseHTTPRequestHandler):
                     self.conn = DatabaseConnection(self.server.db)
                     parsed_url = urlparse(self.path)
                     self._site = path_split(parsed_url.path)[1]
-                    params = parse_qs(parsed_url.query, strict_parsing=True)
-                    self._params = InputsParser(params, False)
+                    params = parse_qs(parsed_url.query,
+                                      keep_blank_values=True,
+                                      strict_parsing=True)
+                    self._params = InputsParser(params)
                     handler_name = f'do_{http_method}_{self._site}'
                     if hasattr(self, handler_name):
                         handler = getattr(self, handler_name)
@@ -294,8 +283,8 @@ class TaskHandler(BaseHTTPRequestHandler):
         """Handle POST with handler, prepare redirection to result."""
         length = int(self.headers['content-length'])
         postvars = parse_qs(self.rfile.read(length).decode(),
-                            keep_blank_values=True, strict_parsing=True)
-        self._form_data = InputsParser(postvars)
+                            keep_blank_values=True)
+        self._form = InputsParser(postvars)
         redir_target = handler()
         self.conn.commit()
         return redir_target
@@ -332,8 +321,9 @@ class TaskHandler(BaseHTTPRequestHandler):
         same, the only difference being the HTML template they are rendered to,
         which .do_GET selects from their method name.
         """
-        start, end = self._params.get_str('start'), self._params.get_str('end')
-        end = end if end else date_in_n_days(366)
+        start = self._params.get_str_or_fail('start', '')
+        end = self._params.get_str_or_fail('end', '')
+        end = end if end != '' else date_in_n_days(366)
         days, start, end = Day.by_date_range_with_limits(self.conn,
                                                          (start, end), 'id')
         days = Day.with_filled_gaps(days, start, end)
@@ -350,9 +340,9 @@ class TaskHandler(BaseHTTPRequestHandler):
 
     def do_GET_day(self) -> dict[str, object]:
         """Show single Day of ?date=."""
-        date = self._params.get_str('date', date_in_n_days(0))
+        date = self._params.get_str_or_fail('date', date_in_n_days(0))
         day = Day.by_id_or_create(self.conn, date)
-        make_type = self._params.get_str('make_type')
+        make_type = self._params.get_str_or_fail('make_type', '')
         conditions_present = []
         enablers_for = {}
         disablers_for = {}
@@ -451,11 +441,11 @@ class TaskHandler(BaseHTTPRequestHandler):
 
     def do_GET_todos(self) -> dict[str, object]:
         """Show Todos from ?start= to ?end=, of ?process=, ?comment= pattern"""
-        sort_by = self._params.get_str('sort_by')
-        start = self._params.get_str('start')
-        end = self._params.get_str('end')
+        sort_by = self._params.get_str_or_fail('sort_by', '')
+        start = self._params.get_str_or_fail('start', '')
+        end = self._params.get_str_or_fail('end', '')
         process_id = self._params.get_int_or_none('process_id')
-        comment_pattern = self._params.get_str('comment_pattern')
+        comment_pattern = self._params.get_str_or_fail('comment_pattern', '')
         todos = []
         ret = Todo.by_date_range_with_limits(self.conn, (start, end))
         todos_by_date_range, start, end = ret
@@ -469,8 +459,8 @@ class TaskHandler(BaseHTTPRequestHandler):
 
     def do_GET_conditions(self) -> dict[str, object]:
         """Show all Conditions."""
-        pattern = self._params.get_str('pattern')
-        sort_by = self._params.get_str('sort_by')
+        pattern = self._params.get_str_or_fail('pattern', '')
+        sort_by = self._params.get_str_or_fail('sort_by', '')
         conditions = Condition.matching(self.conn, pattern)
         sort_by = Condition.sort_by(conditions, sort_by)
         return {'conditions': conditions,
@@ -542,8 +532,8 @@ class TaskHandler(BaseHTTPRequestHandler):
 
     def do_GET_processes(self) -> dict[str, object]:
         """Show all Processes."""
-        pattern = self._params.get_str('pattern')
-        sort_by = self._params.get_str('sort_by')
+        pattern = self._params.get_str_or_fail('pattern', '')
+        sort_by = self._params.get_str_or_fail('sort_by', '')
         processes = Process.matching(self.conn, pattern)
         sort_by = Process.sort_by(processes, sort_by)
         return {'processes': processes, 'sort_by': sort_by, 'pattern': pattern}
@@ -560,7 +550,7 @@ class TaskHandler(BaseHTTPRequestHandler):
                 # (because pylint here fails to detect the use of wrapper as a
                 # method to self with respective access privileges)
                 id_ = self._params.get_int_or_none('id')
-                for _ in self._form_data.get_all_str('delete'):
+                for _ in self._form.get_all_str('delete'):
                     if id_ is None:
                         msg = 'trying to delete non-saved ' +\
                                 f'{target_class.__name__}'
@@ -581,7 +571,7 @@ class TaskHandler(BaseHTTPRequestHandler):
         id_ = self._params.get_int_or_none('id')
         item = cls.by_id(self.conn, id_)
         attr = getattr(item, attr_name)
-        for k, v in self._form_data.get_first_strings_starting('at:').items():
+        for k, v in self._form.get_firsts_of_key_prefixed('at:').items():
             old = k[3:]
             if old[19:] != v:
                 attr.reset_timestamp(old, f'{v}.0')
@@ -591,17 +581,14 @@ class TaskHandler(BaseHTTPRequestHandler):
     def do_POST_day(self) -> str:
         """Update or insert Day of date and Todos mapped to it."""
         # pylint: disable=too-many-locals
-        try:
-            date = self._params.get_str('date')
-            day_comment = self._form_data.get_str('day_comment')
-            make_type = self._form_data.get_str('make_type')
-        except NotFoundException as e:
-            raise BadFormatException from e
-        old_todos = self._form_data.get_all_int('todo_id')
-        new_todos_by_process = self._form_data.get_all_int('new_todo')
-        comments = self._form_data.get_all_str('comment')
-        efforts = self._form_data.get_all_floats_or_nones('effort')
-        done_todos = self._form_data.get_all_int('done')
+        date = self._params.get_str_or_fail('date')
+        day_comment = self._form.get_str_or_fail('day_comment')
+        make_type = self._form.get_str_or_fail('make_type')
+        old_todos = self._form.get_all_int('todo_id')
+        new_todos_by_process = self._form.get_all_int('new_todo')
+        comments = self._form.get_all_str('comment')
+        efforts = self._form.get_all_floats_or_nones('effort')
+        done_todos = self._form.get_all_int('done')
         for _ in [id_ for id_ in done_todos if id_ not in old_todos]:
             raise BadFormatException('"done" field refers to unknown Todo')
         is_done = [t_id in done_todos for t_id in old_todos]
@@ -635,20 +622,26 @@ class TaskHandler(BaseHTTPRequestHandler):
         """Update Todo and its children."""
         # pylint: disable=too-many-locals
         # pylint: disable=too-many-branches
-        adopted_child_ids = self._form_data.get_all_int('adopt')
-        to_make = {'full': self._form_data.get_all_int('make_full'),
-                   'empty': self._form_data.get_all_int('make_empty')}
-        step_fillers = self._form_data.get_all_str('step_filler')
-        to_update = {
-            'is_done': self._form_data.get_bool('done'),
-            'calendarize': self._form_data.get_bool('calendarize'),
-            'comment': self._form_data.get_str('comment', ignore_strict=True)}
-        cond_rels = [self._form_data.get_all_int(name) for name in
+        adopted_child_ids = self._form.get_all_int('adopt')
+        to_make = {'full': self._form.get_all_int('make_full'),
+                   'empty': self._form.get_all_int('make_empty')}
+        step_fillers = self._form.get_all_str('step_filler')
+        to_update: dict[str, Any] = {
+            'is_done': self._form.get_bool('done'),
+            'calendarize': self._form.get_bool('calendarize'),
+            'comment': self._form.get_str_or_fail('comment', '')}
+        cond_rels = [self._form.get_all_int(name) for name in
                      ['conditions', 'blockers', 'enables', 'disables']]
-        try:
-            to_update['effort'] = self._form_data.get_float_or_none('effort')
-        except NotFoundException:
-            pass
+        effort_or_not = self._form.get_str('effort')
+        if effort_or_not is not None:
+            if effort_or_not == '':
+                to_update['effort'] = None
+            else:
+                try:
+                    to_update['effort'] = float(effort_or_not)
+                except ValueError as e:
+                    msg = 'cannot float form field value for key: effort'
+                    raise BadFormatException(msg) from e
         todo.set_condition_relations(self.conn, *cond_rels)
         for filler in [f for f in step_fillers if f != 'ignore']:
             target_id: int
@@ -707,23 +700,20 @@ class TaskHandler(BaseHTTPRequestHandler):
     def do_POST_process(self, process: Process) -> str:
         """Update or insert Process of ?id= and fields defined in postvars."""
         # pylint: disable=too-many-locals
-        try:
-            versioned = {'title': self._form_data.get_str('title'),
-                         'description': self._form_data.get_str('description'),
-                         'effort': self._form_data.get_float('effort')}
-        except NotFoundException as e:
-            raise BadFormatException from e
-        cond_rels = [self._form_data.get_all_int(s) for s
+        versioned = {'title': self._form.get_str_or_fail('title'),
+                     'description': self._form.get_str_or_fail('description'),
+                     'effort': self._form.get_float_or_fail('effort')}
+        cond_rels = [self._form.get_all_int(s) for s
                      in ['conditions', 'blockers', 'enables', 'disables']]
-        calendarize = self._form_data.get_bool('calendarize')
-        step_of = self._form_data.get_all_str('step_of')
-        suppresses = self._form_data.get_all_int('suppresses')
-        kept_steps = self._form_data.get_all_int('kept_steps')
-        new_top_steps = self._form_data.get_all_str('new_top_step')
+        calendarize = self._form.get_bool('calendarize')
+        step_of = self._form.get_all_str('step_of')
+        suppresses = self._form.get_all_int('suppresses')
+        kept_steps = self._form.get_all_int('kept_steps')
+        new_top_steps = self._form.get_all_str('new_top_step')
         new_steps_to = {}
         for step_id in kept_steps:
             name = f'new_step_to_{step_id}'
-            new_steps_to[step_id] = self._form_data.get_all_int(name)
+            new_steps_to[step_id] = self._form.get_all_int(name)
         for k, v in versioned.items():
             getattr(process, k).set(v)
         process.set_condition_relations(self.conn, *cond_rels)
@@ -785,12 +775,9 @@ class TaskHandler(BaseHTTPRequestHandler):
     @_delete_or_post(Condition, '/conditions')
     def do_POST_condition(self, condition: Condition) -> str:
         """Update/insert Condition of ?id= and fields defined in postvars."""
-        try:
-            title = self._form_data.get_str('title')
-            description = self._form_data.get_str('description')
-        except NotFoundException as e:
-            raise BadFormatException(e) from e
-        condition.is_active = self._form_data.get_bool('is_active')
+        title = self._form.get_str_or_fail('title')
+        description = self._form.get_str_or_fail('description')
+        condition.is_active = self._form.get_bool('is_active')
         condition.title.set(title)
         condition.description.set(description)
         condition.save(self.conn)
index 333267f5edbf123a70f22385178d90d5d6ea5678..cc208fb40510a502b29865389aa6c689613294dc 100644 (file)
@@ -79,7 +79,6 @@ class TestsWithServer(TestCaseWithServer):
         url = '/condition'
         self.check_post({}, url, 400)
         self.check_post({'title': ''}, url, 400)
-        self.check_post({'title': '', 'description': ''}, url, 400)
         self.check_post({'title': '', 'is_active': False}, url, 400)
         self.check_post({'description': '', 'is_active': False}, url, 400)
         # check valid POST payload on bad paths
index ce5f87a4234f1ded58d26676ffc62ccda8c583f1..8ac82f59f70482815a30401b42f19e89191b2416 100644 (file)
 from unittest import TestCase
 from tests.utils import TestCaseWithServer
 from plomtask.http import InputsParser
-from plomtask.exceptions import BadFormatException, NotFoundException
+from plomtask.exceptions import BadFormatException
 
 
 class TestsSansServer(TestCase):
     """Tests that do not require DB setup or a server."""
 
+    def test_InputsParser_get_str_or_fail(self) -> None:
+        """Test InputsParser.get_str."""
+        parser = InputsParser({})
+        with self.assertRaises(BadFormatException):
+            parser.get_str_or_fail('foo')
+        self.assertEqual('bar', parser.get_str_or_fail('foo', 'bar'))
+        parser = InputsParser({'foo': []})
+        with self.assertRaises(BadFormatException):
+            parser.get_str_or_fail('foo')
+        self.assertEqual('bar', parser.get_str_or_fail('foo', 'bar'))
+        parser = InputsParser({'foo': ['baz']})
+        self.assertEqual('baz', parser.get_str_or_fail('foo', 'bar'))
+        parser = InputsParser({'foo': ['baz', 'quux']})
+        self.assertEqual('baz', parser.get_str_or_fail('foo', 'bar'))
+
     def test_InputsParser_get_str(self) -> None:
-        """Test InputsParser.get_str on strict and non-strictk."""
-        parser = InputsParser({}, False)
-        self.assertEqual('', parser.get_str('foo'))
+        """Test InputsParser.get_str."""
+        parser = InputsParser({})
+        self.assertEqual(None, parser.get_str('foo'))
         self.assertEqual('bar', parser.get_str('foo', 'bar'))
-        parser.strict = True
-        with self.assertRaises(NotFoundException):
-            parser.get_str('foo')
-        with self.assertRaises(NotFoundException):
-            parser.get_str('foo', 'bar')
-        parser = InputsParser({'foo': []}, False)
+        parser = InputsParser({'foo': []})
+        self.assertEqual(None, parser.get_str('foo'))
         self.assertEqual('bar', parser.get_str('foo', 'bar'))
-        with self.assertRaises(NotFoundException):
-            InputsParser({'foo': []}, True).get_str('foo', 'bar')
-        for strictness in (False, True):
-            parser = InputsParser({'foo': ['baz']}, strictness)
-            self.assertEqual('baz', parser.get_str('foo', 'bar'))
-            parser = InputsParser({'foo': ['baz', 'quux']}, strictness)
-            self.assertEqual('baz', parser.get_str('foo', 'bar'))
-
-    def test_InputsParser_get_first_strings_starting(self) -> None:
-        """Test InputsParser.get_first_strings_starting [non-]strict."""
-        for strictness in (False, True):
-            parser = InputsParser({}, strictness)
-            self.assertEqual({},
-                             parser.get_first_strings_starting(''))
-            parser = InputsParser({}, strictness)
-            self.assertEqual({},
-                             parser.get_first_strings_starting('foo'))
-            parser = InputsParser({'foo': ['bar']}, strictness)
-            self.assertEqual({'foo': 'bar'},
-                             parser.get_first_strings_starting(''))
-            parser = InputsParser({'x': ['y']}, strictness)
-            self.assertEqual({'x': 'y'},
-                             parser.get_first_strings_starting('x'))
-            parser = InputsParser({'xx': ['y']}, strictness)
-            self.assertEqual({'xx': 'y'},
-                             parser.get_first_strings_starting('x'))
-            parser = InputsParser({'xx': ['y']}, strictness)
-            self.assertEqual({},
-                             parser.get_first_strings_starting('xxx'))
-            d = {'xxx': ['x'], 'xxy': ['y'], 'xyy': ['z']}
-            parser = InputsParser(d, strictness)
-            self.assertEqual({'xxx': 'x', 'xxy': 'y'},
-                             parser.get_first_strings_starting('xx'))
-            d = {'xxx': ['x', 'y', 'z'], 'xxy': ['y', 'z']}
-            parser = InputsParser(d, strictness)
-            self.assertEqual({'xxx': 'x', 'xxy': 'y'},
-                             parser.get_first_strings_starting('xx'))
+        parser = InputsParser({'foo': ['baz']})
+        self.assertEqual('baz', parser.get_str('foo', 'bar'))
+        parser = InputsParser({'foo': ['baz', 'quux']})
+        self.assertEqual('baz', parser.get_str('foo', 'bar'))
 
-    def test_InputsParser_get_int(self) -> None:
-        """Test InputsParser.get_int on strict and non-strict."""
-        for strictness in (False, True):
-            with self.assertRaises(BadFormatException):
-                InputsParser({}, strictness).get_int('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': []}, strictness).get_int('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['']}, strictness).get_int('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['bar']}, strictness).get_int('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['0.1']}).get_int('foo')
-            parser = InputsParser({'foo': ['0']}, strictness)
-            self.assertEqual(0, parser.get_int('foo'))
-            parser = InputsParser({'foo': ['17', '23']}, strictness)
-            self.assertEqual(17, parser.get_int('foo'))
+    def test_InputsParser_get_firsts_of_key_prefixed(self) -> None:
+        """Test InputsParser.get_firsts_of_key_prefixed."""
+        parser = InputsParser({})
+        self.assertEqual({},
+                         parser.get_firsts_of_key_prefixed(''))
+        self.assertEqual({},
+                         parser.get_firsts_of_key_prefixed('foo'))
+        parser = InputsParser({'foo': ['bar']})
+        self.assertEqual({'foo': 'bar'},
+                         parser.get_firsts_of_key_prefixed(''))
+        parser = InputsParser({'x': ['y']})
+        self.assertEqual({'x': 'y'},
+                         parser.get_firsts_of_key_prefixed('x'))
+        parser = InputsParser({'xx': ['y']})
+        self.assertEqual({'xx': 'y'},
+                         parser.get_firsts_of_key_prefixed('x'))
+        parser = InputsParser({'xx': ['y']})
+        self.assertEqual({},
+                         parser.get_firsts_of_key_prefixed('xxx'))
+        parser = InputsParser({'xxx': ['x'], 'xxy': ['y'], 'xyy': ['z']})
+        self.assertEqual({'xxx': 'x', 'xxy': 'y'},
+                         parser.get_firsts_of_key_prefixed('xx'))
+        parser = InputsParser({'xxx': ['x', 'y', 'z'], 'xxy': ['y', 'z']})
+        self.assertEqual({'xxx': 'x', 'xxy': 'y'},
+                         parser.get_firsts_of_key_prefixed('xx'))
 
     def test_InputsParser_get_int_or_none(self) -> None:
-        """Test InputsParser.get_int_or_none on strict and non-strict."""
-        for strictness in (False, True):
-            parser = InputsParser({}, strictness)
-            self.assertEqual(None, parser.get_int_or_none('foo'))
-            parser = InputsParser({'foo': []}, strictness)
-            self.assertEqual(None, parser.get_int_or_none('foo'))
-            parser = InputsParser({'foo': ['']}, strictness)
-            self.assertEqual(None, parser.get_int_or_none('foo'))
-            parser = InputsParser({'foo': ['0']}, strictness)
-            self.assertEqual(0, parser.get_int_or_none('foo'))
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['None']},
-                             strictness).get_int_or_none('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['0.1']},
-                             strictness).get_int_or_none('foo')
-            parser = InputsParser({'foo': ['23']}, strictness)
-            self.assertEqual(23, parser.get_int_or_none('foo'))
-
-    def test_InputsParser_get_float(self) -> None:
-        """Test InputsParser.get_float on strict and non-strict."""
-        for strictness in (False, True):
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['']}, strictness).get_float('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['bar']}, strictness).get_float('foo')
-            parser = InputsParser({'foo': ['0']}, strictness)
-            self.assertEqual(0, parser.get_float('foo'))
-            parser = InputsParser({'foo': ['0.1']}, strictness)
-            self.assertEqual(0.1, parser.get_float('foo'))
-            parser = InputsParser({'foo': ['1.23', '456']}, strictness)
-            self.assertEqual(1.23, parser.get_float('foo'))
-        if strictness:
-            with self.assertRaises(NotFoundException):
-                InputsParser({}, strictness).get_float('foo')
-            with self.assertRaises(NotFoundException):
-                InputsParser({'foo': []}, strictness).get_float('foo')
-        else:
-            with self.assertRaises(BadFormatException):
-                InputsParser({}, strictness).get_float('foo')
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': []}, strictness).get_float('foo')
+        """Test InputsParser.get_int_or_none."""
+        parser = InputsParser({})
+        self.assertEqual(None, parser.get_int_or_none('foo'))
+        parser = InputsParser({'foo': []})
+        self.assertEqual(None, parser.get_int_or_none('foo'))
+        parser = InputsParser({'foo': ['']})
+        self.assertEqual(None, parser.get_int_or_none('foo'))
+        parser = InputsParser({'foo': ['0']})
+        self.assertEqual(0, parser.get_int_or_none('foo'))
+        with self.assertRaises(BadFormatException):
+            InputsParser({'foo': ['None']}).get_int_or_none('foo')
+        with self.assertRaises(BadFormatException):
+            InputsParser({'foo': ['0.1']}).get_int_or_none('foo')
+        parser = InputsParser({'foo': ['23']})
+        self.assertEqual(23, parser.get_int_or_none('foo'))
 
-    def test_InputsParser_get_float_or_none(self) -> None:
-        """Test InputsParser.get_float_or_none on strict and non-strict."""
-        for strictness in (False, True):
-            with self.assertRaises(BadFormatException):
-                InputsParser({'foo': ['bar']}, strictness).\
-                        get_float_or_none('foo')
-            parser = InputsParser({'foo': ['']}, strictness)
-            self.assertEqual(None, parser.get_float_or_none('foo'))
-            parser = InputsParser({'foo': ['0']}, strictness)
-            self.assertEqual(0, parser.get_float_or_none('foo'))
-            parser = InputsParser({'foo': ['0.1']}, strictness)
-            self.assertEqual(0.1, parser.get_float_or_none('foo'))
-            parser = InputsParser({'foo': ['1.23', '456']}, strictness)
-            self.assertEqual(1.23, parser.get_float_or_none('foo'))
-        if strictness:
-            with self.assertRaises(NotFoundException):
-                InputsParser({}, strictness).get_float_or_none('foo')
-            with self.assertRaises(NotFoundException):
-                InputsParser({'foo': []}, strictness).get_float_or_none('foo')
-        else:
-            parser = InputsParser({}, strictness)
-            self.assertEqual(None, parser.get_float_or_none('foo'))
-            parser = InputsParser({'foo': []}, strictness)
-            self.assertEqual(None, parser.get_float_or_none('foo'))
+    def test_InputsParser_get_float_or_fail(self) -> None:
+        """Test InputsParser.get_float_or_fail."""
+        with self.assertRaises(BadFormatException):
+            InputsParser({}).get_float_or_fail('foo')
+        with self.assertRaises(BadFormatException):
+            InputsParser({'foo': ['']}).get_float_or_fail('foo')
+        with self.assertRaises(BadFormatException):
+            InputsParser({'foo': ['bar']}).get_float_or_fail('foo')
+        parser = InputsParser({'foo': ['0']})
+        self.assertEqual(0, parser.get_float_or_fail('foo'))
+        parser = InputsParser({'foo': ['0.1']})
+        self.assertEqual(0.1, parser.get_float_or_fail('foo'))
+        parser = InputsParser({'foo': ['1.23', '456']})
+        self.assertEqual(1.23, parser.get_float_or_fail('foo'))
+        with self.assertRaises(BadFormatException):
+            InputsParser({}).get_float_or_fail('foo')
+        with self.assertRaises(BadFormatException):
+            InputsParser({'foo': []}).get_float_or_fail('foo')
 
     def test_InputsParser_get_bool(self) -> None:
-        """Test InputsParser.get_all_str on strict and non-strict."""
-        for strictness in (False, True):
-            parser = InputsParser({}, strictness)
-            self.assertEqual(False, parser.get_bool('foo'))
-            parser = InputsParser({'val': ['true']}, strictness)
-            self.assertEqual(False, parser.get_bool('foo'))
-            parser = InputsParser({'val': ['True']}, strictness)
-            self.assertEqual(False, parser.get_bool('foo'))
-            parser = InputsParser({'val': ['1']}, strictness)
-            self.assertEqual(False, parser.get_bool('foo'))
-            parser = InputsParser({'val': ['foo']}, strictness)
-            self.assertEqual(False, parser.get_bool('foo'))
-            parser = InputsParser({'foo': []}, strictness)
-            self.assertEqual(False, parser.get_bool('foo'))
-            parser = InputsParser({'foo': ['None']}, strictness)
-            self.assertEqual(True, parser.get_bool('foo'))
-            parser = InputsParser({'foo': ['0']}, strictness)
-            self.assertEqual(True, parser.get_bool('foo'))
-            parser = InputsParser({'foo': ['']}, strictness)
-            self.assertEqual(True, parser.get_bool('foo'))
-            parser = InputsParser({'foo': ['bar']}, strictness)
-            self.assertEqual(True, parser.get_bool('foo'))
-            parser = InputsParser({'foo': ['bar', 'baz']}, strictness)
-            self.assertEqual(True, parser.get_bool('foo'))
-            parser = InputsParser({'foo': ['False']}, strictness)
-            self.assertEqual(True, parser.get_bool('foo'))
+        """Test InputsParser.get_all_str."""
+        parser = InputsParser({})
+        self.assertEqual(False, parser.get_bool('foo'))
+        parser = InputsParser({'val': ['true']})
+        self.assertEqual(False, parser.get_bool('foo'))
+        parser = InputsParser({'val': ['True']})
+        self.assertEqual(False, parser.get_bool('foo'))
+        parser = InputsParser({'val': ['1']})
+        self.assertEqual(False, parser.get_bool('foo'))
+        parser = InputsParser({'val': ['foo']})
+        self.assertEqual(False, parser.get_bool('foo'))
+        parser = InputsParser({'foo': []})
+        self.assertEqual(False, parser.get_bool('foo'))
+        parser = InputsParser({'foo': ['None']})
+        self.assertEqual(True, parser.get_bool('foo'))
+        parser = InputsParser({'foo': ['0']})
+        self.assertEqual(True, parser.get_bool('foo'))
+        parser = InputsParser({'foo': ['']})
+        self.assertEqual(True, parser.get_bool('foo'))
+        parser = InputsParser({'foo': ['bar']})
+        self.assertEqual(True, parser.get_bool('foo'))
+        parser = InputsParser({'foo': ['bar', 'baz']})
+        self.assertEqual(True, parser.get_bool('foo'))
+        parser = InputsParser({'foo': ['False']})
+        self.assertEqual(False, parser.get_bool('foo'))
 
     def test_InputsParser_get_all_str(self) -> None:
-        """Test InputsParser.get_all_str on strict and non-strict."""
-        for strictness in (False, True):
-            parser = InputsParser({}, strictness)
-            self.assertEqual([], parser.get_all_str('foo'))
-            parser = InputsParser({'foo': []}, strictness)
-            self.assertEqual([], parser.get_all_str('foo'))
-            parser = InputsParser({'foo': ['bar']}, strictness)
-            self.assertEqual(['bar'], parser.get_all_str('foo'))
-            parser = InputsParser({'foo': ['bar', 'baz']}, strictness)
-            self.assertEqual(['bar', 'baz'], parser.get_all_str('foo'))
+        """Test InputsParser.get_all_str."""
+        parser = InputsParser({})
+        self.assertEqual([], parser.get_all_str('foo'))
+        parser = InputsParser({'foo': []})
+        self.assertEqual([], parser.get_all_str('foo'))
+        parser = InputsParser({'foo': ['bar']})
+        self.assertEqual(['bar'], parser.get_all_str('foo'))
+        parser = InputsParser({'foo': ['bar', 'baz']})
+        self.assertEqual(['bar', 'baz'], parser.get_all_str('foo'))
 
     def test_InputsParser_strict_get_all_int(self) -> None:
-        """Test InputsParser.get_all_int on strict and non-strict."""
-        for strictness in (False, True):
-            parser = InputsParser({}, strictness)
-            self.assertEqual([], parser.get_all_int('foo'))
-            parser = InputsParser({'foo': []}, strictness)
-            self.assertEqual([], parser.get_all_int('foo'))
-            parser = InputsParser({'foo': ['']}, strictness)
-            self.assertEqual([], parser.get_all_int('foo'))
-            parser = InputsParser({'foo': ['0']}, strictness)
-            self.assertEqual([0], parser.get_all_int('foo'))
-            parser = InputsParser({'foo': ['0', '17']}, strictness)
-            self.assertEqual([0, 17], parser.get_all_int('foo'))
-            parser = InputsParser({'foo': ['0.1', '17']}, strictness)
-            with self.assertRaises(BadFormatException):
-                parser.get_all_int('foo')
-            parser = InputsParser({'foo': ['None', '17']}, strictness)
-            with self.assertRaises(BadFormatException):
-                parser.get_all_int('foo')
+        """Test InputsParser.get_all_int."""
+        parser = InputsParser({})
+        self.assertEqual([], parser.get_all_int('foo'))
+        parser = InputsParser({'foo': []})
+        self.assertEqual([], parser.get_all_int('foo'))
+        parser = InputsParser({'foo': ['']})
+        self.assertEqual([], parser.get_all_int('foo'))
+        parser = InputsParser({'foo': ['0']})
+        self.assertEqual([0], parser.get_all_int('foo'))
+        parser = InputsParser({'foo': ['0', '17']})
+        self.assertEqual([0, 17], parser.get_all_int('foo'))
+        parser = InputsParser({'foo': ['0.1', '17']})
+        with self.assertRaises(BadFormatException):
+            parser.get_all_int('foo')
+        parser = InputsParser({'foo': ['None', '17']})
+        with self.assertRaises(BadFormatException):
+            parser.get_all_int('foo')
 
 
 class TestsWithServer(TestCaseWithServer):