From 55540e116e7c76088c0772894df9bbe15672fd20 Mon Sep 17 00:00:00 2001 From: Winson Chan Date: Wed, 7 Oct 2015 19:55:31 +0000 Subject: [PATCH] Replace copy.copy with copy.deepcopy The function copy.copy only copies reference and so if the object has dict or nested dicts, these instances can be modified by code that has reference to the original dict. Change-Id: Ib2680f09b5a5d45fd7180e95ab5fedef05664c5b Closes-Bug: #1503851 --- mistral/engine/default_engine.py | 2 +- mistral/engine/task_handler.py | 2 +- mistral/engine/utils.py | 2 +- mistral/expressions.py | 2 +- mistral/services/scheduler.py | 2 +- .../tests/unit/api/v2/test_action_executions.py | 8 ++++---- mistral/tests/unit/api/v2/test_actions.py | 2 +- mistral/tests/unit/api/v2/test_cron_triggers.py | 4 ++-- mistral/tests/unit/api/v2/test_executions.py | 16 ++++++++-------- mistral/tests/unit/api/v2/test_workbooks.py | 2 +- mistral/tests/unit/api/v2/test_workflows.py | 2 +- .../tests/unit/db/v2/test_sqlalchemy_db_api.py | 16 ++++++++-------- mistral/tests/unit/engine/test_with_items.py | 2 +- mistral/workflow/base.py | 2 +- 14 files changed, 32 insertions(+), 32 deletions(-) diff --git a/mistral/engine/default_engine.py b/mistral/engine/default_engine.py index de794a94..9f6a0277 100644 --- a/mistral/engine/default_engine.py +++ b/mistral/engine/default_engine.py @@ -466,7 +466,7 @@ class DefaultEngine(base.Engine, coordination.Service): 'state': states.RUNNING, 'input': wf_input or {}, 'output': {}, - 'context': copy.copy(wf_input) or {}, + 'context': copy.deepcopy(wf_input) or {}, 'task_execution_id': params.get('task_execution_id'), 'runtime_context': { 'with_items_index': params.get('with_items_index', 0) diff --git a/mistral/engine/task_handler.py b/mistral/engine/task_handler.py index 2439e2a6..68d2bd80 100644 --- a/mistral/engine/task_handler.py +++ b/mistral/engine/task_handler.py @@ -405,7 +405,7 @@ def _schedule_run_action(task_ex, task_spec, action_input, index): task_spec.get_target(), utils.merge_dicts( copy.deepcopy(action_input), - copy.copy(task_ex.in_context) + copy.deepcopy(task_ex.in_context) ) ) diff --git a/mistral/engine/utils.py b/mistral/engine/utils.py index aa0d1722..c8dda7dd 100644 --- a/mistral/engine/utils.py +++ b/mistral/engine/utils.py @@ -26,7 +26,7 @@ LOG = logging.getLogger(__name__) def validate_input(definition, input, spec=None): - input_param_names = copy.copy(list((input or {}).keys())) + input_param_names = copy.deepcopy(list((input or {}).keys())) missing_param_names = [] spec_input = (spec.get_input() if spec else diff --git a/mistral/expressions.py b/mistral/expressions.py index 6094f1f8..61b1e32a 100644 --- a/mistral/expressions.py +++ b/mistral/expressions.py @@ -193,7 +193,7 @@ def _evaluate_item(item, context): def evaluate_recursively(data, context): - data = copy.copy(data) + data = copy.deepcopy(data) if not context: return data diff --git a/mistral/services/scheduler.py b/mistral/services/scheduler.py index 753285d9..4deb6d3d 100644 --- a/mistral/services/scheduler.py +++ b/mistral/services/scheduler.py @@ -142,7 +142,7 @@ class CallScheduler(periodic_task.PeriodicTasks): call.target_method_name ) - method_args = copy.copy(call.method_arguments) + method_args = copy.deepcopy(call.method_arguments) if call.serializers: # Deserialize arguments. diff --git a/mistral/tests/unit/api/v2/test_action_executions.py b/mistral/tests/unit/api/v2/test_action_executions.py index 70e7e139..2de7c58a 100644 --- a/mistral/tests/unit/api/v2/test_action_executions.py +++ b/mistral/tests/unit/api/v2/test_action_executions.py @@ -95,18 +95,18 @@ ACTION_EX = { UPDATED_ACTION_EX_DB = copy.copy(ACTION_EX_DB).to_dict() UPDATED_ACTION_EX_DB['state'] = 'SUCCESS' UPDATED_ACTION_EX_DB['task_name'] = 'task1' -UPDATED_ACTION = copy.copy(ACTION_EX) +UPDATED_ACTION = copy.deepcopy(ACTION_EX) UPDATED_ACTION['state'] = 'SUCCESS' UPDATED_ACTION_OUTPUT = UPDATED_ACTION['output'] ERROR_ACTION_EX = copy.copy(ACTION_EX_DB).to_dict() ERROR_ACTION_EX['state'] = 'ERROR' ERROR_ACTION_EX['task_name'] = 'task1' -ERROR_ACTION = copy.copy(ACTION_EX) +ERROR_ACTION = copy.deepcopy(ACTION_EX) ERROR_ACTION['state'] = 'ERROR' ERROR_ACTION_RES = ERROR_ACTION['output'] -BROKEN_ACTION = copy.copy(ACTION_EX) +BROKEN_ACTION = copy.deepcopy(ACTION_EX) BROKEN_ACTION['output'] = 'string not escaped' MOCK_ACTION = mock.MagicMock(return_value=ACTION_EX_DB) @@ -257,7 +257,7 @@ class TestActionExecutionsController(base.FunctionalTest): @mock.patch.object(rpc.EngineClient, 'on_action_complete') def test_put_without_result(self, f): - action_ex = copy.copy(UPDATED_ACTION) + action_ex = copy.deepcopy(UPDATED_ACTION) del action_ex['output'] f.return_value = UPDATED_ACTION_EX_DB diff --git a/mistral/tests/unit/api/v2/test_actions.py b/mistral/tests/unit/api/v2/test_actions.py index d704b7e4..c7238fa3 100644 --- a/mistral/tests/unit/api/v2/test_actions.py +++ b/mistral/tests/unit/api/v2/test_actions.py @@ -81,7 +81,7 @@ my_action: UPDATED_ACTION_DB = copy.copy(ACTION_DB) UPDATED_ACTION_DB['definition'] = UPDATED_ACTION_DEFINITION -UPDATED_ACTION = copy.copy(ACTION) +UPDATED_ACTION = copy.deepcopy(ACTION) UPDATED_ACTION['definition'] = UPDATED_ACTION_DEFINITION MOCK_ACTION = mock.MagicMock(return_value=ACTION_DB) diff --git a/mistral/tests/unit/api/v2/test_cron_triggers.py b/mistral/tests/unit/api/v2/test_cron_triggers.py index bb1429d2..51c54fd6 100644 --- a/mistral/tests/unit/api/v2/test_cron_triggers.py +++ b/mistral/tests/unit/api/v2/test_cron_triggers.py @@ -47,7 +47,7 @@ TRIGGER = { 'remaining_executions': 42 } -trigger_values = copy.copy(TRIGGER) +trigger_values = copy.deepcopy(TRIGGER) trigger_values['workflow_input'] = json.loads( trigger_values['workflow_input']) @@ -61,7 +61,7 @@ TRIGGER_DB.update(trigger_values) UPDATED_TRIGGER_DB = copy.copy(TRIGGER_DB) UPDATED_TRIGGER_DB['pattern'] = '*/1 * * * *' -UPDATED_TRIGGER = copy.copy(TRIGGER) +UPDATED_TRIGGER = copy.deepcopy(TRIGGER) UPDATED_TRIGGER['pattern'] = '*/1 * * * *' MOCK_WF = mock.MagicMock(return_value=WF) diff --git a/mistral/tests/unit/api/v2/test_executions.py b/mistral/tests/unit/api/v2/test_executions.py index 2c1ed68d..92556a80 100644 --- a/mistral/tests/unit/api/v2/test_executions.py +++ b/mistral/tests/unit/api/v2/test_executions.py @@ -54,13 +54,13 @@ WF_EX_JSON = { 'workflow_name': 'some', } -UPDATED_WF_EX = copy.copy(WF_EX) +UPDATED_WF_EX = copy.deepcopy(WF_EX) UPDATED_WF_EX['state'] = states.PAUSED -UPDATED_WF_EX_JSON = copy.copy(WF_EX_JSON) +UPDATED_WF_EX_JSON = copy.deepcopy(WF_EX_JSON) UPDATED_WF_EX_JSON['state'] = states.PAUSED -WF_EX_JSON_WITH_DESC = copy.copy(WF_EX_JSON) +WF_EX_JSON_WITH_DESC = copy.deepcopy(WF_EX_JSON) WF_EX_JSON_WITH_DESC['description'] = "execution description." MOCK_WF_EX = mock.MagicMock(return_value=WF_EX) @@ -98,7 +98,7 @@ class TestExecutionsController(base.FunctionalTest): def test_put(self): resp = self.app.put_json('/v2/executions/123', UPDATED_WF_EX_JSON) - UPDATED_WF_EX_WITH_DESC = copy.copy(UPDATED_WF_EX_JSON) + UPDATED_WF_EX_WITH_DESC = copy.deepcopy(UPDATED_WF_EX_JSON) UPDATED_WF_EX_WITH_DESC['description'] = 'execution description.' self.assertEqual(200, resp.status_int) @@ -110,12 +110,12 @@ class TestExecutionsController(base.FunctionalTest): MOCK_WF_EX ) def test_put_stop(self): - update_exec = copy.copy(WF_EX_JSON) + update_exec = copy.deepcopy(WF_EX_JSON) update_exec['state'] = states.ERROR update_exec['state_info'] = "Force" with mock.patch.object(rpc.EngineClient, 'stop_workflow') as mock_pw: - wf_ex = copy.copy(WF_EX) + wf_ex = copy.deepcopy(WF_EX) wf_ex['state'] = states.ERROR wf_ex['state_info'] = "Force" mock_pw.return_value = wf_ex @@ -134,12 +134,12 @@ class TestExecutionsController(base.FunctionalTest): MOCK_WF_EX ) def test_put_state_info_unset(self): - update_exec = copy.copy(WF_EX_JSON) + update_exec = copy.deepcopy(WF_EX_JSON) update_exec['state'] = states.ERROR update_exec.pop('state_info', None) with mock.patch.object(rpc.EngineClient, 'stop_workflow') as mock_pw: - wf_ex = copy.copy(WF_EX) + wf_ex = copy.deepcopy(WF_EX) wf_ex['state'] = states.ERROR del wf_ex.state_info mock_pw.return_value = wf_ex diff --git a/mistral/tests/unit/api/v2/test_workbooks.py b/mistral/tests/unit/api/v2/test_workbooks.py index 4a356d10..19957e45 100644 --- a/mistral/tests/unit/api/v2/test_workbooks.py +++ b/mistral/tests/unit/api/v2/test_workbooks.py @@ -57,7 +57,7 @@ WORKBOOK = { UPDATED_WORKBOOK_DB = copy.copy(WORKBOOK_DB) UPDATED_WORKBOOK_DB['definition'] = UPDATED_WORKBOOK_DEF -UPDATED_WORKBOOK = copy.copy(WORKBOOK) +UPDATED_WORKBOOK = copy.deepcopy(WORKBOOK) UPDATED_WORKBOOK['definition'] = UPDATED_WORKBOOK_DEF WB_DEF_INVALID_MODEL_EXCEPTION = """ diff --git a/mistral/tests/unit/api/v2/test_workflows.py b/mistral/tests/unit/api/v2/test_workflows.py index 3c5a813b..6a30a11c 100644 --- a/mistral/tests/unit/api/v2/test_workflows.py +++ b/mistral/tests/unit/api/v2/test_workflows.py @@ -106,7 +106,7 @@ flow: UPDATED_WF_DB = copy.copy(WF_DB) UPDATED_WF_DB['definition'] = UPDATED_WF_DEFINITION -UPDATED_WF = copy.copy(WF) +UPDATED_WF = copy.deepcopy(WF) UPDATED_WF['definition'] = UPDATED_WF_DEFINITION WF_DEF_INVALID_MODEL_EXCEPTION = """ diff --git a/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py b/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py index f37c7dc0..fa18de61 100644 --- a/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py +++ b/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py @@ -885,7 +885,7 @@ class TaskExecutionTest(SQLAlchemyTest): def test_create_and_get_and_load_task_execution(self): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) created = db_api.create_task_execution(values) @@ -907,7 +907,7 @@ class TaskExecutionTest(SQLAlchemyTest): with db_api.transaction(): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) task = db_api.create_task_execution(values) @@ -945,7 +945,7 @@ class TaskExecutionTest(SQLAlchemyTest): def test_update_task_execution(self): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) created = db_api.create_task_execution(values) @@ -971,7 +971,7 @@ class TaskExecutionTest(SQLAlchemyTest): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) created = db_api.create_or_update_task_execution(id, values) @@ -997,12 +997,12 @@ class TaskExecutionTest(SQLAlchemyTest): def test_get_task_executions(self): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) created0 = db_api.create_task_execution(values) - values = copy.copy(TASK_EXECS[1]) + values = copy.deepcopy(TASK_EXECS[1]) values.update({'workflow_execution_id': wf_ex.id}) created1 = db_api.create_task_execution(values) @@ -1018,7 +1018,7 @@ class TaskExecutionTest(SQLAlchemyTest): def test_delete_task_execution(self): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) created = db_api.create_task_execution(values) @@ -1038,7 +1038,7 @@ class TaskExecutionTest(SQLAlchemyTest): def test_task_execution_repr(self): wf_ex = db_api.create_workflow_execution(WF_EXECS[0]) - values = copy.copy(TASK_EXECS[0]) + values = copy.deepcopy(TASK_EXECS[0]) values.update({'workflow_execution_id': wf_ex.id}) s = db_api.create_task_execution(values).__repr__() diff --git a/mistral/tests/unit/engine/test_with_items.py b/mistral/tests/unit/engine/test_with_items.py index 4ab586dd..2ca02a6e 100644 --- a/mistral/tests/unit/engine/test_with_items.py +++ b/mistral/tests/unit/engine/test_with_items.py @@ -247,7 +247,7 @@ class WithItemsEngineTest(base.EngineTestCase): def test_with_items_static_var(self): wb_service.create_workbook_v2(WORKBOOK_WITH_STATIC_VAR) - wf_input = copy.copy(WORKFLOW_INPUT) + wf_input = copy.deepcopy(WORKFLOW_INPUT) wf_input.update({'greeting': 'Hello'}) # Start workflow. wf_ex = self.engine.start_workflow('wb1.with_items', wf_input) diff --git a/mistral/workflow/base.py b/mistral/workflow/base.py index 4e7e96f6..33daed3f 100644 --- a/mistral/workflow/base.py +++ b/mistral/workflow/base.py @@ -98,7 +98,7 @@ class WorkflowController(object): upstream_task_execs = self._get_upstream_task_executions(task_spec) return u.merge_dicts( - copy.copy(self.wf_ex.context), + copy.deepcopy(self.wf_ex.context), data_flow.evaluate_upstream_context(upstream_task_execs) )