From 9c62e1b0e5c30ed3fd7a49828749db195bc3e557 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 17 Jun 2024 23:15:48 +0200 Subject: [PATCH] Simplify JSON-ification of VersionedAttributes. --- plomtask/db.py | 5 ++++- plomtask/versioned_attributes.py | 6 ------ tests/conditions.py | 31 ++++++++++++++++++------------- tests/processes.py | 3 ++- tests/utils.py | 19 ++++++++++--------- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/plomtask/db.py b/plomtask/db.py index 1cecc16..054060e 100644 --- a/plomtask/db.py +++ b/plomtask/db.py @@ -275,6 +275,8 @@ class BaseModel(Generic[BaseModelId]): def as_dict(self) -> dict[str, object]: """Return self as (json.dumps-coompatible) dict.""" d: dict[str, object] = {'id': self.id_} + if len(self.to_save_versioned) > 0: + d['_versioned'] = {} for k in self.to_save: attr = getattr(self, k) if hasattr(attr, 'as_dict'): @@ -282,7 +284,8 @@ class BaseModel(Generic[BaseModelId]): d[k] = attr for k in self.to_save_versioned: attr = getattr(self, k) - d[k] = attr.as_dict + assert isinstance(d['_versioned'], dict) + d['_versioned'][k] = attr.history for r in self.to_save_relations: attr_name = r[2] d[attr_name] = [x.as_dict for x in getattr(self, attr_name)] diff --git a/plomtask/versioned_attributes.py b/plomtask/versioned_attributes.py index cc42bbc..cbd1c8e 100644 --- a/plomtask/versioned_attributes.py +++ b/plomtask/versioned_attributes.py @@ -25,12 +25,6 @@ class VersionedAttribute: history_tuples) return hash(hashable) - @property - def as_dict(self) -> dict[str, object]: - """Return self as (json.dumps-coompatible) dict.""" - d = {'parent_id': self.parent.id_, 'history': self.history} - return d - @property def _newest_timestamp(self) -> str: """Return most recent timestamp.""" diff --git a/tests/conditions.py b/tests/conditions.py index 53a75b8..5270812 100644 --- a/tests/conditions.py +++ b/tests/conditions.py @@ -74,16 +74,18 @@ class TestsWithServer(TestCaseWithServer): """Return JSON of Condition to expect.""" d = {'id': id_, 'is_active': is_active, - 'title': {'history': {}, 'parent_id': id_}, - 'description': {'history': {}, 'parent_id': id_}} + '_versioned': { + 'title': {}, + 'description': {} + } + } titles = titles if titles else [] descriptions = descriptions if descriptions else [] + assert isinstance(d['_versioned'], dict) for i, title in enumerate(titles): - assert isinstance(d['title'], dict) - d['title']['history'][f'[{i}]'] = title + d['_versioned']['title'][i] = title for i, description in enumerate(descriptions): - assert isinstance(d['description'], dict) - d['description']['history'][f'[{i}]'] = description + d['_versioned']['description'][i] = description return d @staticmethod @@ -100,9 +102,11 @@ class TestsWithServer(TestCaseWithServer): 'calendarize': False, 'suppressed_steps': [], 'explicit_steps': [], - 'title': {'history': {'[0]': title}, 'parent_id': id_}, - 'effort': {'history': {'[0]': 1.0}, 'parent_id': id_}, - 'description': {'history': {'[0]': ''}, 'parent_id': id_}, + '_versioned': { + 'title': {0: title}, + 'description': {0: ''}, + 'effort': {0: 1.0} + }, 'conditions': conditions if conditions else [], 'disables': disables if disables else [], 'enables': enables if enables else [], @@ -117,7 +121,7 @@ class TestsWithServer(TestCaseWithServer): post = {'title': 'foo', 'description': 'oof', 'is_active': False} self.check_post(post, '/condition', 302, '/condition?id=1') # … single /condition - cond = self.cond_as_dict(titles = ['foo'], descriptions = ['oof']) + cond = self.cond_as_dict(titles=['foo'], descriptions=['oof']) expected_single: dict[str, object] expected_single = {'is_new': False, 'enabled_processes': [], @@ -137,7 +141,8 @@ class TestsWithServer(TestCaseWithServer): # test effect of POST changing title and activeness post = {'title': 'bar', 'description': 'oof', 'is_active': True} self.check_post(post, '/condition?id=1', 302) - expected_single['condition']['title']['history']['[1]'] = 'bar' + assert isinstance(expected_single['condition'], dict) + expected_single['condition']['_versioned']['title'][1] = 'bar' expected_single['condition']['is_active'] = True self.check_json_get('/condition?id=1', expected_single) # test deletion POST's effect on … @@ -162,7 +167,7 @@ class TestsWithServer(TestCaseWithServer): proc_2_post = {'title': 'B', 'description': '', 'effort': 1.0, 'enables': [1], 'blocker': [1]} self.post_process(2, proc_2_post) - cond = self.cond_as_dict(titles = ['foo'], descriptions = ['oof']) + cond = self.cond_as_dict(titles=['foo'], descriptions=['oof']) proc_1 = self.proc_as_dict(conditions=[cond], disables=[cond]) proc_2 = self.proc_as_dict(2, 'B', blockers=[cond], enables=[cond]) expected_single = {'is_new': False, @@ -193,7 +198,7 @@ class TestsWithServer(TestCaseWithServer): self.check_post(post_2, '/condition', 302, '/condition?id=2') post_3 = {'title': 'baz', 'description': 'zab', 'is_active': True} self.check_post(post_3, '/condition', 302, '/condition?id=3') - cond_1 = self.cond_as_dict(titles = ['foo'], descriptions = ['oof']) + cond_1 = self.cond_as_dict(titles=['foo'], descriptions=['oof']) cond_2 = self.cond_as_dict(2, titles=['bar'], descriptions=['rab']) cond_3 = self.cond_as_dict(3, True, ['baz'], ['zab']) cons = [cond_2, cond_3, cond_1] diff --git a/tests/processes.py b/tests/processes.py index 34f6427..4d2252c 100644 --- a/tests/processes.py +++ b/tests/processes.py @@ -279,7 +279,8 @@ class TestsWithServer(TestCaseWithServer): form_data = {'title': 'foo', 'description': 'foo', 'effort': 1.0} self.post_process(2, form_data | {'condition': []}) self.check_post(form_data | {'condition': [1]}, '/process?id=', 404) - self.check_post({'title': 'foo', 'description': 'foo'}, + self.check_post({'title': 'foo', 'description': 'foo', + 'is_active': False}, '/condition', 302, '/condition?id=1') self.post_process(3, form_data | {'condition': [1]}) self.post_process(4, form_data | {'disables': [1]}) diff --git a/tests/utils.py b/tests/utils.py index 86d049d..d6c5b20 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -274,22 +274,23 @@ class TestCaseWithServer(TestCaseWithDB): """Compare JSON on GET path with expected. To simplify comparison of VersionedAttribute histories, transforms - keys under "history"-named dicts into bracketed integer strings - counting upwards in chronology. + timestamp keys of VersionedAttribute history keys into integers + counting chronologically forward from 0. """ def rewrite_history_keys_in(item: Any) -> Any: if isinstance(item, dict): - if 'history' in item.keys(): - vals = item['history'].values() - history = {} - for i, val in enumerate(vals): - history[f'[{i}]'] = val - item['history'] = history + if '_versioned' in item.keys(): + for k in item['_versioned']: + vals = item['_versioned'][k].values() + history = {} + for i, val in enumerate(vals): + history[i] = val + item['_versioned'][k] = history for k in list(item.keys()): rewrite_history_keys_in(item[k]) elif isinstance(item, list): item[:] = [rewrite_history_keys_in(i) for i in item] - return item + return item self.conn.request('GET', path) response = self.conn.getresponse() self.assertEqual(response.status, 200) -- 2.30.2