From e598da95fce7019c2acad0766abc32eff252946e Mon Sep 17 00:00:00 2001 From: Vincent Pelletier <vincent@nexedi.com> Date: Wed, 12 Jun 2019 14:24:28 +0900 Subject: [PATCH] CMFActivity: Ignore None dependencies. Simplifies activity spawning when dependencies are conditionally set: activate( after_tag=some_value if some_condition else None, ) instead of having to do a ** dance. All columns involved in dependency checking are declared NOT NULL, so providing "None" and expecting a dependency to happen was already not working. This change pushes this one step further by allowing activity auto-validation also happen on these activities. Also, simplify getOrderValidationText: avoid iterating on keys and then retrieving values, use a list-comprehension, simplify condition. Add a test for after_tag, also covering activity auto-validation. --- product/CMFActivity/Activity/Queue.py | 31 ++++++++++---------- product/CMFActivity/tests/testCMFActivity.py | 22 ++++++++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/product/CMFActivity/Activity/Queue.py b/product/CMFActivity/Activity/Queue.py index c5c14e9fdb..cf3079f71a 100644 --- a/product/CMFActivity/Activity/Queue.py +++ b/product/CMFActivity/Activity/Queue.py @@ -140,21 +140,22 @@ class Queue(object): def getOrderValidationText(self, message): # Return an identifier of validators related to ordering. - order_validation_item_list = [] - key_list = message.activity_kw.keys() - key_list.sort() - for key in key_list: - method_id = "_validate_" + key - if getattr(self, method_id, None) is not None: - order_validation_item_list.append((key, message.activity_kw[key])) - if len(order_validation_item_list) == 0: - # When no order validation argument is specified, skip the computation - # of the checksum for speed. Here, 'none' is used, because this never be - # identical to SHA1 hexdigest (which is always 40 characters), and 'none' - # is true in Python. This is important, because dtml-if assumes that an empty - # string is false, so we must use a non-empty string for this. - return 'none' - return sha1(repr(order_validation_item_list)).hexdigest() + order_validation_item_list = [ + (key, value) + for key, value in sorted( + message.activity_kw.iteritems(), key=lambda x: x[0], + ) + if value is not None and + getattr(self, "_validate_" + key, None) is not None + ] + if order_validation_item_list: + return sha1(repr(order_validation_item_list)).hexdigest() + # When no order validation argument is specified, skip the computation + # of the checksum for speed. Here, 'none' is used, because this never be + # identical to SHA1 hexdigest (which is always 40 characters), and 'none' + # is true in Python. This is important, because dtml-if assumes that an empty + # string is false, so we must use a non-empty string for this. + return 'none' def getMessageList(self, activity_tool, processing_node=None,**kw): return [] diff --git a/product/CMFActivity/tests/testCMFActivity.py b/product/CMFActivity/tests/testCMFActivity.py index b25cded52b..5b65a5dc6e 100644 --- a/product/CMFActivity/tests/testCMFActivity.py +++ b/product/CMFActivity/tests/testCMFActivity.py @@ -2603,6 +2603,28 @@ class TestCMFActivity(ERP5TypeTestCase, LogInterceptor): self.assertEqual(len(result), 1) self.deleteMessageList(activity, result) + def test_message_auto_validation(self): + """ + Test that messages without dependencies are directly spawned with + processing_node=0. + """ + organisation = self.portal.organisation_module.newContent(portal_type='Organisation') + self.tic() + activity_tool = self.getActivityTool() + organisation.activate(tag='1').getId() + organisation.activate(tag='2', after_tag=None).getId() + organisation.activate(tag='3', after_tag='foo').getId() + self.commit() + activity_tool.getMessageList() + self.assertItemsEqual( + [('1', 0), ('2', 0), ('3', -1)], + [ + (x.activity_kw['tag'], x.processing_node) + for x in self.getActivityTool().getMessageList() + ], + ) + self.tic() + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCMFActivity)) -- 2.30.9