From e4cb0458b47e140aefacde5c4729043087362781 Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida <leonardo@nexedi.com> Date: Tue, 19 Jul 2011 18:29:23 +0200 Subject: [PATCH] temp object must not skip interaction on real one Only prevent transition from running if it has actually run. If its guard prevents it from running, consider it still runnable in this transaction. This change doesn't help to skip the interaction on the real object if it's not forbidden on the temp one. --- product/ERP5/tests/testInteractionWorkflow.py | 69 +++++++++++++++++++ product/ERP5Type/Base.py | 15 ++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/product/ERP5/tests/testInteractionWorkflow.py b/product/ERP5/tests/testInteractionWorkflow.py index d4edd8a8c8..9e07b9e266 100644 --- a/product/ERP5/tests/testInteractionWorkflow.py +++ b/product/ERP5/tests/testInteractionWorkflow.py @@ -560,6 +560,75 @@ context.setTitle('Bar') self.tic() self.assertEquals(organisation.getTitle(), 'Bar') + def test_18_no_temp_object(self, quiet=0, run=run_all_test): + if not run: return + if not quiet: + self.logMessage('Skips Temp Objects') + self.createInteractionWorkflow() + self.interaction.setProperties( + 'editObject', + temporary_document_disallowed=False, + method_id='_setGroup.*', + after_script_name=('afterEdit',)) + params = 'sci, **kw' + body = """\ +context = sci['object'] +context.setTitle('Bar') +""" + self.script.ZPythonScript_edit(params, body) + self.createData() + organisation = self.organisation + temp = organisation.asContext() + temp.setTitle('Foo') + # interaction workflows can affect temp objects + temp.setGroupValue(organisation) + self.assertEqual(temp.getTitle(), 'Bar') + # but not if it has been forbidden + temp.setTitle('Foo') + self.interaction.setProperties( + 'editObject', + temporary_document_disallowed=True, + method_id='_setGroup.*', + after_script_name=('afterEdit',)) + temp.setGroupValue(None) + self.assertEqual(temp.getTitle(), 'Foo') + + def test_19_temp_object_doesnt_skip_normal(self, quiet=0, run=run_all_test): + if not run: return + if not quiet: + self.logMessage('Skips Temp Objects, but run in normal objects in the same transaction') + self.createInteractionWorkflow() + self.interaction.setProperties( + 'editObject', + once_per_transaction=True, + temporary_document_disallowed=True, + method_id='_setGroup.*', + after_script_name=('afterEdit',)) + params = 'sci, **kw' + body = """\ +context = sci['object'] +context.setTitle('Bar') +""" + self.script.ZPythonScript_edit(params, body) + self.createData() + organisation = self.organisation + organisation.setTitle('Foo') + temp = organisation.asContext() + # temp and organisation have the same path + self.assertEqual(temp.getPath(), organisation.getPath()) + # which means that a transactional variable key based on path would + # match both the organisation and the temp object, but triggering the + # workflow on the temp object should not change it: + temp.setGroupValue(organisation) + self.assertEquals(temp.getTitle(), 'Foo') + # nor should it change the normal object + self.assertEquals(organisation.getTitle(), 'Foo') + # however, it should allow triggering the normal object later on the same + # transaction + organisation.setGroupValue(organisation) + self.assertEquals(organisation.getTitle(), 'Bar') + # while still not changing the temp object + self.assertEquals(temp.getTitle(), 'Foo') def test_regular_expression(self): # test that we can add an interaction by defining methods using regular diff --git a/product/ERP5Type/Base.py b/product/ERP5Type/Base.py index b4ab7de463..9492007e9e 100644 --- a/product/ERP5Type/Base.py +++ b/product/ERP5Type/Base.py @@ -181,17 +181,14 @@ class WorkflowMethod(Method): invoke_once_dict = self._invoke_once.get(portal_type, {}) valid_invoke_once_item_list = [] # Only keep those transitions which were never invoked + once_transition_dict = {} for wf_id, transition_list in invoke_once_dict.iteritems(): valid_transition_list = [] for transition_id in transition_list: once_transition_key = ('Products.ERP5Type.Base.WorkflowMethod.__call__', wf_id, transition_id, instance_path) - try: - already_called_transition = transactional_variable[once_transition_key] - except KeyError: - already_called_transition = 0 - transactional_variable[once_transition_key] = 1 - if not already_called_transition: + once_transition_dict[(wf_id, transition_id)] = once_transition_key + if once_transition_key not in transactional_variable: valid_transition_list.append(transition_id) if valid_transition_list: valid_invoke_once_item_list.append((wf_id, valid_transition_list)) @@ -216,6 +213,12 @@ class WorkflowMethod(Method): for transition_id in transition_list: if candidate_workflow.isWorkflowMethodSupported(instance, transition_id): valid_list.append(transition_id) + once_transition_key = once_transition_dict.get((wf_id, transition_id), + None) + if once_transition_key is not None: + # a run-once transiction, prevent it from running in the + # same transaction again + transactional_variable[once_transition_key] = 1 elif candidate_workflow.__class__.__name__ == 'DCWorkflowDefinition': raise UnsupportedWorkflowMethod(instance, wf_id, transition_id) # XXX Keep the log for projects that needs to comment out -- 2.30.9