home · contact · privacy
For various boolean settings, treat absence of form POST as setting False.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 16 Aug 2024 01:35:34 +0000 (03:35 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 16 Aug 2024 01:35:34 +0000 (03:35 +0200)
plomtask/http.py
tests/conditions.py
tests/misc.py
tests/processes.py
tests/todos.py
tests/utils.py

index bb6e4edb9702248442da467ba3b7800e824eff1b..e224ea019011fda8916612d5765a322ef86e7e5c 100644 (file)
@@ -82,12 +82,9 @@ class InputsParser:
             msg = f'cannot int form field value for key {key}: {val}'
             raise BadFormatException(msg) from e
 
-    def get_bool_or_none(self, key: str) -> bool | None:
-        """Return value to key if truish; if no value to key, None."""
-        val = self.get_str(key)
-        if val is None:
-            return None
-        return val in {'True', 'true', '1', 'on'}
+    def get_bool(self, key: str) -> bool:
+        """Return if value to key truish; return False if None/no value."""
+        return self.get_str(key) in {'True', 'true', '1', 'on'}
 
     def get_all_of_key_prefixed(self, key_prefix: str) -> dict[str, list[str]]:
         """Retrieve dict of strings at keys starting with key_prefix."""
@@ -655,11 +652,9 @@ class TaskHandler(BaseHTTPRequestHandler):
                              for id_ in self._form.get_all_int('make_empty')]}
         step_fillers_to = self._form.get_all_of_key_prefixed('step_filler_to_')
         to_update: dict[str, Any] = {
-            'comment': self._form.get_str_or_fail('comment', '')}
-        for k in ('is_done', 'calendarize'):
-            v = self._form.get_bool_or_none(k)
-            if v is not None:
-                to_update[k] = v
+            'comment': self._form.get_str_or_fail('comment', ''),
+            'is_done': self._form.get_bool('is_done'),
+            'calendarize': self._form.get_bool('calendarize')}
         cond_rels = [self._form.get_all_int(name) for name in
                      ['conditions', 'blockers', 'enables', 'disables']]
         effort_or_not = self._form.get_str('effort')
@@ -752,7 +747,7 @@ class TaskHandler(BaseHTTPRequestHandler):
                      '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.get_bool_or_none('calendarize')
+        calendarize = self._form.get_bool('calendarize')
         step_of = self._form.get_all_str('step_of')
         suppressions = self._form.get_all_int('suppresses')
         kept_steps = self._form.get_all_int('kept_steps')
@@ -766,8 +761,7 @@ class TaskHandler(BaseHTTPRequestHandler):
         #
         for k, v in versioned.items():
             getattr(process, k).set(v)
-        if calendarize is not None:
-            process.calendarize = calendarize
+        process.calendarize = calendarize
         process.save(self._conn)
         assert isinstance(process.id_, int)
         # set relations to Conditions and ProcessSteps / other Processes
@@ -807,10 +801,9 @@ class TaskHandler(BaseHTTPRequestHandler):
         """Update/insert Condition of ?id= and fields defined in postvars."""
         title = self._form.get_str_or_fail('title')
         description = self._form.get_str_or_fail('description')
-        is_active = self._form.get_bool_or_none('is_active')
+        is_active = self._form.get_bool('is_active')
+        condition.is_active = is_active
         #
-        if is_active is not None:
-            condition.is_active = is_active
         condition.title.set(title)
         condition.description.set(description)
         condition.save(self._conn)
index 3b6495980cc4fc5ab334bd98eee57e85bd1b8d75..c071e65a2765d4182b4573e7744d7123b5f6509a 100644 (file)
@@ -100,6 +100,10 @@ class TestsWithServer(TestCaseWithServer):
                                       'is_active': 1})
         self.check_json_get(url_single, exp_single)
         self.check_json_get(url_all, exp_all)
+        # test POST sans 'is_active' setting it negative
+        self.post_exp_cond(all_exps, {'title': 'bar', 'description': 'oof'})
+        self.check_json_get(url_single, exp_single)
+        self.check_json_get(url_all, exp_all)
         # test deletion POST's effect, both to return id=1 into empty single,
         # full /conditions into empty list
         self.post_exp_cond(all_exps, {'delete': ''}, redir_to_id=False)
index 3aa13140bc1cd2380098ea4bfe5d0fec1827b466..a6df2e56481bb41deebe4fd4182ca96ac41c07fe 100644 (file)
@@ -98,36 +98,23 @@ class TestsSansServer(TestCase):
         with self.assertRaises(BadFormatException):
             InputsParser({'foo': []}).get_float_or_fail('foo')
 
-    def test_InputsParser_get_bool_or_none(self) -> None:
-        """Test InputsParser.get_all_str."""
-        parser = InputsParser({})
-        self.assertEqual(None, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'val': ['foo']})
-        self.assertEqual(None, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'val': ['True']})
-        self.assertEqual(None, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': []})
-        self.assertEqual(None, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['None']})
-        self.assertEqual(False, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['0']})
-        self.assertEqual(False, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['']})
-        self.assertEqual(False, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['bar']})
-        self.assertEqual(False, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['bar', 'baz']})
-        self.assertEqual(False, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['False']})
-        self.assertEqual(False, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['true']})
-        self.assertEqual(True, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['True']})
-        self.assertEqual(True, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['1']})
-        self.assertEqual(True, parser.get_bool_or_none('foo'))
-        parser = InputsParser({'foo': ['on']})
-        self.assertEqual(True, parser.get_bool_or_none('foo'))
+    def test_InputsParser_get_bool(self) -> None:
+        """Test InputsParser.get_bool."""
+        self.assertEqual(0, InputsParser({}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'val': ['foo']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'val': ['True']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': []}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': ['None']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': ['0']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': ['']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': ['bar']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': ['bar',
+                                                  'baz']}).get_bool('foo'))
+        self.assertEqual(0, InputsParser({'foo': ['False']}).get_bool('foo'))
+        self.assertEqual(1, InputsParser({'foo': ['true']}).get_bool('foo'))
+        self.assertEqual(1, InputsParser({'foo': ['True']}).get_bool('foo'))
+        self.assertEqual(1, InputsParser({'foo': ['1']}).get_bool('foo'))
+        self.assertEqual(1, InputsParser({'foo': ['on']}).get_bool('foo'))
 
     def test_InputsParser_get_all_str(self) -> None:
         """Test InputsParser.get_all_str."""
index 0c2c1a935a2009abad2d2d460295bc360a5458ec..0fa352db3787593c5ab80bbab72f501e50008c3e 100644 (file)
@@ -324,6 +324,11 @@ class TestsWithServer(TestCaseWithServer):
         valid_post = {'title': 'foo', 'description': 'oof', 'effort': 2.3}
         self.post_exp_process([exp], valid_post, 1)
         self.check_json_get('/process?id=1', exp)
+        # check boolean 'calendarize'
+        self.post_exp_process([exp], valid_post | {'calendarize': True}, 1)
+        self.check_json_get('/process?id=1', exp)
+        self.post_exp_process([exp], valid_post, 1)
+        self.check_json_get('/process?id=1', exp)
         # check n_todos field
         self.post_exp_day([], {'new_todo': ['1']}, '2024-01-01')
         self.post_exp_day([], {'new_todo': ['1']}, '2024-01-02')
index 6118ab774f4e8f5a0edd216bc7b80532bca7439b..ea61a3306eb1ccd893217d1e845a8f502035e1ac 100644 (file)
@@ -5,8 +5,7 @@ from tests.utils import (TestCaseSansDB, TestCaseWithDB, TestCaseWithServer,
 from plomtask.todos import Todo, TodoNode
 from plomtask.processes import Process, ProcessStep
 from plomtask.conditions import Condition
-from plomtask.exceptions import (NotFoundException, BadFormatException,
-                                 HandledException)
+from plomtask.exceptions import BadFormatException, HandledException
 
 
 class TestsWithDB(TestCaseWithDB, TestCaseSansDB):
@@ -31,26 +30,6 @@ class TestsWithDB(TestCaseWithDB, TestCaseSansDB):
         self.cond2.save(self.db_conn)
         self.default_init_kwargs['process'] = self.proc
 
-    def test_Todo_init(self) -> None:
-        """Test creation of Todo and what they default to."""
-        process = Process(None)
-        with self.assertRaises(NotFoundException):
-            Todo(None, process, False, self.date1)
-        process.save(self.db_conn)
-        assert isinstance(self.cond1.id_, int)
-        assert isinstance(self.cond2.id_, int)
-        process.set_condition_relations(self.db_conn,
-                                        [self.cond1.id_, self.cond2.id_], [],
-                                        [self.cond1.id_], [self.cond2.id_])
-        todo_no_id = Todo(None, process, False, self.date1)
-        self.assertEqual(todo_no_id.conditions, [self.cond1, self.cond2])
-        self.assertEqual(todo_no_id.enables, [self.cond1])
-        self.assertEqual(todo_no_id.disables, [self.cond2])
-        todo_yes_id = Todo(5, process, False, self.date1)
-        self.assertEqual(todo_yes_id.conditions, [])
-        self.assertEqual(todo_yes_id.enables, [])
-        self.assertEqual(todo_yes_id.disables, [])
-
     def test_Todo_by_date(self) -> None:
         """Test findability of Todos by date."""
         t1 = Todo(None, self.proc, False, self.date1)
@@ -66,21 +45,6 @@ class TestsWithDB(TestCaseWithDB, TestCaseSansDB):
         """Test .by_date_range_with_limits."""
         self.check_by_date_range_with_limits('day')
 
-    def test_Todo_on_conditions(self) -> None:
-        """Test effect of Todos on Conditions."""
-        assert isinstance(self.cond1.id_, int)
-        assert isinstance(self.cond2.id_, int)
-        todo = Todo(None, self.proc, False, self.date1)
-        todo.save(self.db_conn)
-        todo.set_condition_relations(self.db_conn, [], [],
-                                     [self.cond1.id_], [self.cond2.id_])
-        todo.is_done = True
-        self.assertEqual(self.cond1.is_active, True)
-        self.assertEqual(self.cond2.is_active, False)
-        todo.is_done = False
-        self.assertEqual(self.cond1.is_active, True)
-        self.assertEqual(self.cond2.is_active, False)
-
     def test_Todo_children(self) -> None:
         """Test Todo.children relations."""
         todo_1 = Todo(None, self.proc, False, self.date1)
@@ -308,9 +272,8 @@ class TestsWithServer(TestCaseWithServer):
                      'comment': 'foo', 'effort': 2.3}
         self._post_exp_todo(1, todo_post, exp)
         self.check_json_get('/todo?id=1', exp)
-        # test implicitly un-setting (only) comment by empty post
-        self.check_post({}, '/todo?id=1')
-        exp.lib_get('Todo', 1)['comment'] = ''
+        # test implicitly un-setting comment/calendarize/is_done by empty post
+        self._post_exp_todo(1, {}, exp)
         self.check_json_get('/todo?id=1', exp)
         # test effort post can be explicitly unset by "effort":"" post
         self.check_post({'effort': ''}, '/todo?id=1')
index e706ec0b242b4bfff9dbd09af92657b8279df4da..045194fb099785d897fcac0a556cc9a94dc993e3 100644 (file)
@@ -718,8 +718,8 @@ class Expected:
             return
         cond = self.lib_get('Condition', id_)
         if cond:
-            if 'is_active' in d:
-                cond['is_active'] = d['is_active']
+            cond['is_active'] = 'is_active' in d and\
+                    d['is_active'] in VALID_TRUES
             for category in ['title', 'description']:
                 history = cond['_versioned'][category]
                 if len(history) > 0:
@@ -766,7 +766,8 @@ class Expected:
 
     def set_todo_from_post(self, id_: int, d: dict[str, Any]) -> None:
         """Set Todo of id_ in library based on POST dict d."""
-        corrected_kwargs: dict[str, Any] = {'children': []}
+        corrected_kwargs: dict[str, Any] = {
+                'children': [], 'is_done': 0, 'calendarize': 0, 'comment': ''}
         for k, v in d.items():
             if k.startswith('step_filler_to_'):
                 continue
@@ -774,8 +775,8 @@ class Expected:
                 new_children = v if isinstance(v, list) else [v]
                 corrected_kwargs['children'] += new_children
                 continue
-            if k in {'is_done', 'calendarize'}:
-                v = v in VALID_TRUES
+            if k in {'is_done', 'calendarize'} and v in VALID_TRUES:
+                v = True
             corrected_kwargs[k] = v
         todo = self.lib_get('Todo', id_)
         if todo:
@@ -846,12 +847,13 @@ class Expected:
                                      d['title'], d['description'], d['effort'])
         ignore = {'title', 'description', 'effort', 'new_top_step', 'step_of',
                   'kept_steps'}
+        proc['calendarize'] = False
         for k, v in d.items():
             if k in ignore\
                     or k.startswith('step_') or k.startswith('new_step_to'):
                 continue
-            if k in {'calendarize'}:
-                v = v in VALID_TRUES
+            if k in {'calendarize'} and v in VALID_TRUES:
+                v = True
             elif k in {'suppressed_steps', 'explicit_steps', 'conditions',
                        'disables', 'enables', 'blockers'}:
                 if not isinstance(v, list):