4 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/e7ba2469bca0/ Changeset: e7ba2469bca0 Branch: next-stable User: jmchilton Date: 2014-08-04 15:33:40 Summary: Test cases and test workflows to verify workflow import stability. Affected #: 3 files diff -r f4f50588c63807c1da91b5e820cfa15837a20d75 -r e7ba2469bca0cb7a1d5a8d754885537dc683d490 test/api/test_workflow_topoambigouity.ga --- /dev/null +++ b/test/api/test_workflow_topoambigouity.ga @@ -0,0 +1,471 @@ +{ + "a_galaxy_workflow": "true", + "annotation": "", + "format-version": "0.1", + "name": "topoambigouity", + "steps": { + "0": { + "annotation": "", + "id": 0, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "l" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 193.7604217529297, + "top": 156.00001525878906 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"l\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "1": { + "annotation": "", + "id": 1, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "m" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 199.7639012336731, + "top": 282.9757237434387 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"m\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "2": { + "annotation": "", + "id": 2, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "n" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 213.73957872390747, + "top": 372.92363023757935 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"n\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "3": { + "annotation": "", + "id": 3, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "a" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 387.21183824539185, + "top": 414.39933824539185 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"a\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "4": { + "annotation": "", + "id": 4, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "b" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 389.2083592414856, + "top": 484.4514012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"b\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "5": { + "annotation": "", + "id": 5, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "c" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 402.2465672492981, + "top": 568.4618382453918 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"c\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "6": { + "annotation": "", + "id": 6, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "d" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 398.2881932258606, + "top": 641.5000462532043 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"d\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "7": { + "annotation": "", + "id": 7, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "k" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 931.6736912727356, + "top": 787.8889012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"k\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "8": { + "annotation": "", + "id": 8, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "h" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 923.6006932258606, + "top": 599.7986302375793 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"h\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "9": { + "annotation": "", + "id": 9, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "i" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 921.5694432258606, + "top": 694.7639012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"i\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "10": { + "annotation": "", + "id": 10, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "e" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 683.3750462532043, + "top": 600.5972752571106 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"e\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "11": { + "annotation": "", + "id": 11, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "f" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 692.3854222297668, + "top": 694.5729222297668 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"f\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "12": { + "annotation": "", + "id": 12, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "g" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 681.5173802375793, + "top": 760.7014012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"g\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "13": { + "annotation": "", + "id": 13, + "input_connections": { + "input1": { + "id": 3, + "output_name": "output" + }, + "queries_0|input2": { + "id": 4, + "output_name": "output" + }, + "queries_1|input2": { + "id": 5, + "output_name": "output" + }, + "queries_2|input2": { + "id": 6, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 660.3368382453918, + "top": 404.57295274734497 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "14": { + "annotation": "", + "id": 14, + "input_connections": { + "input1": { + "id": 13, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 10, + "output_name": "output" + }, + "queries_1|input2": { + "id": 11, + "output_name": "output" + }, + "queries_2|input2": { + "id": 12, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 915.5451512336731, + "top": 394.7639012336731 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "15": { + "annotation": "", + "id": 15, + "input_connections": { + "input1": { + "id": 14, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 8, + "output_name": "output" + }, + "queries_1|input2": { + "id": 9, + "output_name": "output" + }, + "queries_2|input2": { + "id": 7, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 217.61113023757935, + "top": 760.8055882453918 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "16": { + "annotation": "", + "id": 16, + "input_connections": { + "input1": { + "id": 0, + "output_name": "output" + }, + "queries_0|input2": { + "id": 1, + "output_name": "output" + }, + "queries_1|input2": { + "id": 2, + "output_name": "output" + }, + "queries_2|input2": { + "id": 15, + "output_name": "out_file1" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 462.9583592414856, + "top": 194.15626573562622 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + } + } +} \ No newline at end of file diff -r f4f50588c63807c1da91b5e820cfa15837a20d75 -r e7ba2469bca0cb7a1d5a8d754885537dc683d490 test/api/test_workflow_topoambigouity_auto_laidout.ga --- /dev/null +++ b/test/api/test_workflow_topoambigouity_auto_laidout.ga @@ -0,0 +1,471 @@ +{ + "a_galaxy_workflow": "true", + "annotation": "", + "format-version": "0.1", + "name": "topoambigouity2", + "steps": { + "0": { + "annotation": "", + "id": 0, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "l" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 193.7604217529297, + "top": 156.00001525878906 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"l\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "1": { + "annotation": "", + "id": 1, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "m" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 199.7639012336731, + "top": 282.9757237434387 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"m\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "2": { + "annotation": "", + "id": 2, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "n" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 213.73957872390747, + "top": 372.92363023757935 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"n\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "3": { + "annotation": "", + "id": 3, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "a" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 387.21183824539185, + "top": 414.39933824539185 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"a\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "4": { + "annotation": "", + "id": 4, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "b" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 389.2083592414856, + "top": 484.4514012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"b\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "5": { + "annotation": "", + "id": 5, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "c" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 402.2465672492981, + "top": 568.4618382453918 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"c\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "6": { + "annotation": "", + "id": 6, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "d" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 398.2881932258606, + "top": 641.5000462532043 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"d\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "7": { + "annotation": "", + "id": 7, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "k" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 931.6736912727356, + "top": 787.8889012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"k\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "8": { + "annotation": "", + "id": 8, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "h" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 923.6006932258606, + "top": 599.7986302375793 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"h\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "9": { + "annotation": "", + "id": 9, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "i" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 921.5694432258606, + "top": 694.7639012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"i\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "10": { + "annotation": "", + "id": 10, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "e" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 683.3750462532043, + "top": 600.5972752571106 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"e\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "11": { + "annotation": "", + "id": 11, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "f" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 692.3854222297668, + "top": 694.5729222297668 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"f\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "12": { + "annotation": "", + "id": 12, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "g" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 681.5173802375793, + "top": 760.7014012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"g\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "13": { + "annotation": "", + "id": 13, + "input_connections": { + "input1": { + "id": 3, + "output_name": "output" + }, + "queries_0|input2": { + "id": 4, + "output_name": "output" + }, + "queries_1|input2": { + "id": 5, + "output_name": "output" + }, + "queries_2|input2": { + "id": 6, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 660.3368382453918, + "top": 404.57295274734497 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "14": { + "annotation": "", + "id": 14, + "input_connections": { + "input1": { + "id": 13, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 10, + "output_name": "output" + }, + "queries_1|input2": { + "id": 11, + "output_name": "output" + }, + "queries_2|input2": { + "id": 12, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 915.5451512336731, + "top": 394.7639012336731 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "15": { + "annotation": "", + "id": 15, + "input_connections": { + "input1": { + "id": 14, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 8, + "output_name": "output" + }, + "queries_1|input2": { + "id": 9, + "output_name": "output" + }, + "queries_2|input2": { + "id": 7, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 217.61113023757935, + "top": 760.8055882453918 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "16": { + "annotation": "", + "id": 16, + "input_connections": { + "input1": { + "id": 0, + "output_name": "output" + }, + "queries_0|input2": { + "id": 1, + "output_name": "output" + }, + "queries_1|input2": { + "id": 2, + "output_name": "output" + }, + "queries_2|input2": { + "id": 15, + "output_name": "out_file1" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 462.9583592414856, + "top": 194.15626573562622 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + } + } +} \ No newline at end of file diff -r f4f50588c63807c1da91b5e820cfa15837a20d75 -r e7ba2469bca0cb7a1d5a8d754885537dc683d490 test/api/test_workflows.py --- a/test/api/test_workflows.py +++ b/test/api/test_workflows.py @@ -105,6 +105,30 @@ self.dataset_populator.wait_for_history( history_id, assert_ok=True ) self.assertEquals("1 2 3\n4 5 6\n7 8 9\n0 a b\n", self.dataset_populator.get_history_dataset_content( history_id ) ) + def test_workflow_stability( self ): + # Run this index stability test with following command: + # ./run_tests.sh test/api/test_workflows.py:WorkflowsApiTestCase.test_workflow_stability + from pkg_resources import resource_string + for workflow_file in [ "test_workflow_topoambigouity.ga", "test_workflow_topoambigouity_auto_laidout.ga" ]: + workflow_str = resource_string( __name__, workflow_file ) + workflow = self.workflow_populator.load_workflow( "test1", content=workflow_str ) + last_step_map = self._step_map( workflow ) + for i in range(10): + uploaded_workflow_id = self.workflow_populator.create_workflow( workflow ) + download_response = self._get( "workflows/%s/download" % uploaded_workflow_id ) + downloaded_workflow = download_response.json() + step_map = self._step_map(downloaded_workflow) + assert step_map == last_step_map + last_step_map = step_map + + def _step_map(self, workflow): + # Build dict mapping 'tep index to input name. + step_map = {} + for step_index, step in workflow["steps"].iteritems(): + if step[ "type" ] == "data_input": + step_map[step_index] = step["inputs"][0]["name"] + return step_map + @skip_without_tool( "cat1" ) def test_extract_from_history( self ): history_id = self.dataset_populator.new_history() https://bitbucket.org/galaxy/galaxy-central/commits/591f0366f034/ Changeset: 591f0366f034 Branch: next-stable User: jmchilton Date: 2014-08-04 15:33:40 Summary: Ensure topological sorting is 'stable' w.r.t to first element of tuple. This improves correctness of 64a25838085978c250a0486b516bb2c8e7c3b850. Affected #: 2 files diff -r e7ba2469bca0cb7a1d5a8d754885537dc683d490 -r 591f0366f034f36e1536ec33afa26bed17ffe66c lib/galaxy/util/topsort.py --- a/lib/galaxy/util/topsort.py +++ b/lib/galaxy/util/topsort.py @@ -12,12 +12,17 @@ topsort( [(1,2), (3,3)] ) -may return any of (but nothing other than) +Valid topological sorts would be any of (but nothing other than) [3, 1, 2] [1, 3, 2] [1, 2, 3] +... however this variant ensures that 'key' order (first element of +tuple) is preserved so the following will be result returned: + + [1, 3, 2] + because those are the permutations of the input elements that respect the "1 precedes 2" and "3 precedes 3" input constraints. Note that a constraint of the form (x, x) is really just a trick @@ -31,8 +36,9 @@ many methods to help analyze and break the cycles. This requires a good deal more code than topsort itself! """ +from collections import OrderedDict +from exceptions import Exception -from exceptions import Exception class CycleError(Exception): def __init__(self, sofar, numpreds, succs): @@ -83,7 +89,7 @@ def get_preds(self): if self.preds is not None: return self.preds - self.preds = preds = {} + self.preds = preds = OrderedDict() remaining_elts = self.get_elements() for x in remaining_elts: preds[x] = [] @@ -112,7 +118,7 @@ from random import choice x = choice(remaining_elts) answer = [] - index = {} + index = OrderedDict() in_answer = index.has_key while not in_answer(x): index[x] = len(answer) # index of x in answer @@ -124,8 +130,8 @@ return answer def topsort(pairlist): - numpreds = {} # elt -> # of predecessors - successors = {} # elt -> list of successors + numpreds = OrderedDict() # elt -> # of predecessors + successors = OrderedDict() # elt -> list of successors for first, second in pairlist: # make sure every elt is a key in numpreds if not numpreds.has_key(first): @@ -174,8 +180,8 @@ return answer def topsort_levels(pairlist): - numpreds = {} # elt -> # of predecessors - successors = {} # elt -> list of successors + numpreds = OrderedDict() # elt -> # of predecessors + successors = OrderedDict() # elt -> list of successors for first, second in pairlist: # make sure every elt is a key in numpreds if not numpreds.has_key(first): diff -r e7ba2469bca0cb7a1d5a8d754885537dc683d490 -r 591f0366f034f36e1536ec33afa26bed17ffe66c test/unit/test_topsort.py --- /dev/null +++ b/test/unit/test_topsort.py @@ -0,0 +1,39 @@ +from galaxy.util import topsort + + +def test_topsort_level_stability(): + data = [ + (0, 2), + (1, 2), + (2, 3), + (2, 4), + (3, 4), + (3, 5), + (6, 2), + ] + assert topsort.topsort_levels( data )[ 0 ] == [ 0, 1, 6 ] + assert topsort.topsort( data ) == [ 0, 1, 6, 2, 3, 4, 5 ] + # Swap first two edges - so 1 appears first + swap( data, 0, 1 ) + assert topsort.topsort_levels( data )[ 0 ] == [ 1, 0, 6 ] + assert topsort.topsort( data ) == [ 1, 0, 6, 2, 3, 4, 5 ] + + # Shouldn't really affect sorting of 1 0 6 + swap( data, 3, 4 ) + assert topsort.topsort_levels( data )[ 0 ] == [ 1, 0, 6 ] + assert topsort.topsort( data ) == [ 1, 0, 6, 2, 3, 4, 5 ] + + # Place 0 before 6 in original list + swap( data, 1, 6 ) + assert topsort.topsort_levels( data )[ 0 ] == [ 1, 6, 0 ] + assert topsort.topsort( data ) == [ 1, 6, 0, 2, 3, 4, 5 ] + + +def test_topsort_doc(): + assert topsort.topsort([(1, 2), (3, 3)]) == [1, 3, 2] + + +def swap(lst, i, j): + tmp = lst[j] + lst[j] = lst[i] + lst[i] = tmp https://bitbucket.org/galaxy/galaxy-central/commits/4aa37815f1fb/ Changeset: 4aa37815f1fb Branch: next-stable User: jmchilton Date: 2014-08-04 15:33:40 Summary: More progress toward guarenteed workflow import step order stability. Previous commit ensured that topsort is stable - but keys are reshuffled by position prior to being sent to topsort - in case their are "ties" when sorting by position ensure that import order is preserved before sorting on position. This is all very dry and seemingly persnickety - but at any rate - after this commit I am fairly confident that Galaxy will import newly saved workflows that have been exported in the same order they were exported in. This means that 64a25838085978c250a0486b516bb2c8e7c3b850 is more correct. Affected #: 1 file diff -r 591f0366f034f36e1536ec33afa26bed17ffe66c -r 4aa37815f1fba179ac45c0a67eaffc319905cf0e lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -1693,8 +1693,18 @@ # the local Galaxy instance. Each tuple in the list of missing_tool_tups # will be ( tool_id, tool_name, tool_version ). missing_tool_tups = [] + supplied_steps = data[ 'steps' ] + # Try to iterate through imported workflow in such a way as to + # preserve step order. + step_indices = supplied_steps.keys() + try: + step_indices = sorted( step_indices, key=int ) + except ValueError: + # to defensive, were these ever or will they ever not be integers? + pass # First pass to build step objects and populate basic values - for step_dict in data[ 'steps' ].itervalues(): + for step_index in step_indices: + step_dict = supplied_steps[ step_index ] # Create the model class for the step step = model.WorkflowStep() steps.append( step ) https://bitbucket.org/galaxy/galaxy-central/commits/cde36ab1fe99/ Changeset: cde36ab1fe99 User: jmchilton Date: 2014-08-04 15:34:07 Summary: Merge next-stable. Affected #: 6 files diff -r 65583750eedecdf26cd786f11809e9641c171d6f -r cde36ab1fe9934579d1fc03c7538853b0f533708 lib/galaxy/util/topsort.py --- a/lib/galaxy/util/topsort.py +++ b/lib/galaxy/util/topsort.py @@ -12,12 +12,17 @@ topsort( [(1,2), (3,3)] ) -may return any of (but nothing other than) +Valid topological sorts would be any of (but nothing other than) [3, 1, 2] [1, 3, 2] [1, 2, 3] +... however this variant ensures that 'key' order (first element of +tuple) is preserved so the following will be result returned: + + [1, 3, 2] + because those are the permutations of the input elements that respect the "1 precedes 2" and "3 precedes 3" input constraints. Note that a constraint of the form (x, x) is really just a trick @@ -31,8 +36,9 @@ many methods to help analyze and break the cycles. This requires a good deal more code than topsort itself! """ +from collections import OrderedDict +from exceptions import Exception -from exceptions import Exception class CycleError(Exception): def __init__(self, sofar, numpreds, succs): @@ -83,7 +89,7 @@ def get_preds(self): if self.preds is not None: return self.preds - self.preds = preds = {} + self.preds = preds = OrderedDict() remaining_elts = self.get_elements() for x in remaining_elts: preds[x] = [] @@ -112,7 +118,7 @@ from random import choice x = choice(remaining_elts) answer = [] - index = {} + index = OrderedDict() in_answer = index.has_key while not in_answer(x): index[x] = len(answer) # index of x in answer @@ -124,8 +130,8 @@ return answer def topsort(pairlist): - numpreds = {} # elt -> # of predecessors - successors = {} # elt -> list of successors + numpreds = OrderedDict() # elt -> # of predecessors + successors = OrderedDict() # elt -> list of successors for first, second in pairlist: # make sure every elt is a key in numpreds if not numpreds.has_key(first): @@ -174,8 +180,8 @@ return answer def topsort_levels(pairlist): - numpreds = {} # elt -> # of predecessors - successors = {} # elt -> list of successors + numpreds = OrderedDict() # elt -> # of predecessors + successors = OrderedDict() # elt -> list of successors for first, second in pairlist: # make sure every elt is a key in numpreds if not numpreds.has_key(first): diff -r 65583750eedecdf26cd786f11809e9641c171d6f -r cde36ab1fe9934579d1fc03c7538853b0f533708 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -1693,8 +1693,18 @@ # the local Galaxy instance. Each tuple in the list of missing_tool_tups # will be ( tool_id, tool_name, tool_version ). missing_tool_tups = [] + supplied_steps = data[ 'steps' ] + # Try to iterate through imported workflow in such a way as to + # preserve step order. + step_indices = supplied_steps.keys() + try: + step_indices = sorted( step_indices, key=int ) + except ValueError: + # to defensive, were these ever or will they ever not be integers? + pass # First pass to build step objects and populate basic values - for step_dict in data[ 'steps' ].itervalues(): + for step_index in step_indices: + step_dict = supplied_steps[ step_index ] # Create the model class for the step step = model.WorkflowStep() steps.append( step ) diff -r 65583750eedecdf26cd786f11809e9641c171d6f -r cde36ab1fe9934579d1fc03c7538853b0f533708 test/api/test_workflow_topoambigouity.ga --- /dev/null +++ b/test/api/test_workflow_topoambigouity.ga @@ -0,0 +1,471 @@ +{ + "a_galaxy_workflow": "true", + "annotation": "", + "format-version": "0.1", + "name": "topoambigouity", + "steps": { + "0": { + "annotation": "", + "id": 0, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "l" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 193.7604217529297, + "top": 156.00001525878906 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"l\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "1": { + "annotation": "", + "id": 1, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "m" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 199.7639012336731, + "top": 282.9757237434387 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"m\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "2": { + "annotation": "", + "id": 2, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "n" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 213.73957872390747, + "top": 372.92363023757935 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"n\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "3": { + "annotation": "", + "id": 3, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "a" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 387.21183824539185, + "top": 414.39933824539185 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"a\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "4": { + "annotation": "", + "id": 4, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "b" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 389.2083592414856, + "top": 484.4514012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"b\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "5": { + "annotation": "", + "id": 5, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "c" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 402.2465672492981, + "top": 568.4618382453918 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"c\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "6": { + "annotation": "", + "id": 6, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "d" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 398.2881932258606, + "top": 641.5000462532043 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"d\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "7": { + "annotation": "", + "id": 7, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "k" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 931.6736912727356, + "top": 787.8889012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"k\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "8": { + "annotation": "", + "id": 8, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "h" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 923.6006932258606, + "top": 599.7986302375793 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"h\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "9": { + "annotation": "", + "id": 9, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "i" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 921.5694432258606, + "top": 694.7639012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"i\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "10": { + "annotation": "", + "id": 10, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "e" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 683.3750462532043, + "top": 600.5972752571106 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"e\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "11": { + "annotation": "", + "id": 11, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "f" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 692.3854222297668, + "top": 694.5729222297668 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"f\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "12": { + "annotation": "", + "id": 12, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "g" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 681.5173802375793, + "top": 760.7014012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"g\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "13": { + "annotation": "", + "id": 13, + "input_connections": { + "input1": { + "id": 3, + "output_name": "output" + }, + "queries_0|input2": { + "id": 4, + "output_name": "output" + }, + "queries_1|input2": { + "id": 5, + "output_name": "output" + }, + "queries_2|input2": { + "id": 6, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 660.3368382453918, + "top": 404.57295274734497 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "14": { + "annotation": "", + "id": 14, + "input_connections": { + "input1": { + "id": 13, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 10, + "output_name": "output" + }, + "queries_1|input2": { + "id": 11, + "output_name": "output" + }, + "queries_2|input2": { + "id": 12, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 915.5451512336731, + "top": 394.7639012336731 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "15": { + "annotation": "", + "id": 15, + "input_connections": { + "input1": { + "id": 14, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 8, + "output_name": "output" + }, + "queries_1|input2": { + "id": 9, + "output_name": "output" + }, + "queries_2|input2": { + "id": 7, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 217.61113023757935, + "top": 760.8055882453918 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "16": { + "annotation": "", + "id": 16, + "input_connections": { + "input1": { + "id": 0, + "output_name": "output" + }, + "queries_0|input2": { + "id": 1, + "output_name": "output" + }, + "queries_1|input2": { + "id": 2, + "output_name": "output" + }, + "queries_2|input2": { + "id": 15, + "output_name": "out_file1" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 462.9583592414856, + "top": 194.15626573562622 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + } + } +} \ No newline at end of file diff -r 65583750eedecdf26cd786f11809e9641c171d6f -r cde36ab1fe9934579d1fc03c7538853b0f533708 test/api/test_workflow_topoambigouity_auto_laidout.ga --- /dev/null +++ b/test/api/test_workflow_topoambigouity_auto_laidout.ga @@ -0,0 +1,471 @@ +{ + "a_galaxy_workflow": "true", + "annotation": "", + "format-version": "0.1", + "name": "topoambigouity2", + "steps": { + "0": { + "annotation": "", + "id": 0, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "l" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 193.7604217529297, + "top": 156.00001525878906 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"l\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "1": { + "annotation": "", + "id": 1, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "m" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 199.7639012336731, + "top": 282.9757237434387 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"m\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "2": { + "annotation": "", + "id": 2, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "n" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 213.73957872390747, + "top": 372.92363023757935 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"n\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "3": { + "annotation": "", + "id": 3, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "a" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 387.21183824539185, + "top": 414.39933824539185 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"a\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "4": { + "annotation": "", + "id": 4, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "b" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 389.2083592414856, + "top": 484.4514012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"b\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "5": { + "annotation": "", + "id": 5, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "c" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 402.2465672492981, + "top": 568.4618382453918 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"c\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "6": { + "annotation": "", + "id": 6, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "d" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 398.2881932258606, + "top": 641.5000462532043 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"d\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "7": { + "annotation": "", + "id": 7, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "k" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 931.6736912727356, + "top": 787.8889012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"k\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "8": { + "annotation": "", + "id": 8, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "h" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 923.6006932258606, + "top": 599.7986302375793 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"h\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "9": { + "annotation": "", + "id": 9, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "i" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 921.5694432258606, + "top": 694.7639012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"i\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "10": { + "annotation": "", + "id": 10, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "e" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 683.3750462532043, + "top": 600.5972752571106 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"e\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "11": { + "annotation": "", + "id": 11, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "f" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 692.3854222297668, + "top": 694.5729222297668 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"f\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "12": { + "annotation": "", + "id": 12, + "input_connections": {}, + "inputs": [ + { + "description": "", + "name": "g" + } + ], + "name": "Input dataset", + "outputs": [], + "position": { + "left": 681.5173802375793, + "top": 760.7014012336731 + }, + "tool_errors": null, + "tool_id": null, + "tool_state": "{\"name\": \"g\"}", + "tool_version": null, + "type": "data_input", + "user_outputs": [] + }, + "13": { + "annotation": "", + "id": 13, + "input_connections": { + "input1": { + "id": 3, + "output_name": "output" + }, + "queries_0|input2": { + "id": 4, + "output_name": "output" + }, + "queries_1|input2": { + "id": 5, + "output_name": "output" + }, + "queries_2|input2": { + "id": 6, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 660.3368382453918, + "top": 404.57295274734497 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "14": { + "annotation": "", + "id": 14, + "input_connections": { + "input1": { + "id": 13, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 10, + "output_name": "output" + }, + "queries_1|input2": { + "id": 11, + "output_name": "output" + }, + "queries_2|input2": { + "id": 12, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 915.5451512336731, + "top": 394.7639012336731 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "15": { + "annotation": "", + "id": 15, + "input_connections": { + "input1": { + "id": 14, + "output_name": "out_file1" + }, + "queries_0|input2": { + "id": 8, + "output_name": "output" + }, + "queries_1|input2": { + "id": 9, + "output_name": "output" + }, + "queries_2|input2": { + "id": 7, + "output_name": "output" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 217.61113023757935, + "top": 760.8055882453918 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + }, + "16": { + "annotation": "", + "id": 16, + "input_connections": { + "input1": { + "id": 0, + "output_name": "output" + }, + "queries_0|input2": { + "id": 1, + "output_name": "output" + }, + "queries_1|input2": { + "id": 2, + "output_name": "output" + }, + "queries_2|input2": { + "id": 15, + "output_name": "out_file1" + } + }, + "inputs": [], + "name": "Concatenate datasets", + "outputs": [ + { + "name": "out_file1", + "type": "input" + } + ], + "position": { + "left": 462.9583592414856, + "top": 194.15626573562622 + }, + "post_job_actions": {}, + "tool_errors": null, + "tool_id": "cat1", + "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}, {\\\"input2\\\": null, \\\"__index__\\\": 1}, {\\\"input2\\\": null, \\\"__index__\\\": 2}]\"}", + "tool_version": "1.0.0", + "type": "tool", + "user_outputs": [] + } + } +} \ No newline at end of file diff -r 65583750eedecdf26cd786f11809e9641c171d6f -r cde36ab1fe9934579d1fc03c7538853b0f533708 test/api/test_workflows.py --- a/test/api/test_workflows.py +++ b/test/api/test_workflows.py @@ -105,6 +105,30 @@ self.dataset_populator.wait_for_history( history_id, assert_ok=True ) self.assertEquals("1 2 3\n4 5 6\n7 8 9\n0 a b\n", self.dataset_populator.get_history_dataset_content( history_id ) ) + def test_workflow_stability( self ): + # Run this index stability test with following command: + # ./run_tests.sh test/api/test_workflows.py:WorkflowsApiTestCase.test_workflow_stability + from pkg_resources import resource_string + for workflow_file in [ "test_workflow_topoambigouity.ga", "test_workflow_topoambigouity_auto_laidout.ga" ]: + workflow_str = resource_string( __name__, workflow_file ) + workflow = self.workflow_populator.load_workflow( "test1", content=workflow_str ) + last_step_map = self._step_map( workflow ) + for i in range(10): + uploaded_workflow_id = self.workflow_populator.create_workflow( workflow ) + download_response = self._get( "workflows/%s/download" % uploaded_workflow_id ) + downloaded_workflow = download_response.json() + step_map = self._step_map(downloaded_workflow) + assert step_map == last_step_map + last_step_map = step_map + + def _step_map(self, workflow): + # Build dict mapping 'tep index to input name. + step_map = {} + for step_index, step in workflow["steps"].iteritems(): + if step[ "type" ] == "data_input": + step_map[step_index] = step["inputs"][0]["name"] + return step_map + @skip_without_tool( "cat1" ) def test_extract_from_history( self ): history_id = self.dataset_populator.new_history() diff -r 65583750eedecdf26cd786f11809e9641c171d6f -r cde36ab1fe9934579d1fc03c7538853b0f533708 test/unit/test_topsort.py --- /dev/null +++ b/test/unit/test_topsort.py @@ -0,0 +1,39 @@ +from galaxy.util import topsort + + +def test_topsort_level_stability(): + data = [ + (0, 2), + (1, 2), + (2, 3), + (2, 4), + (3, 4), + (3, 5), + (6, 2), + ] + assert topsort.topsort_levels( data )[ 0 ] == [ 0, 1, 6 ] + assert topsort.topsort( data ) == [ 0, 1, 6, 2, 3, 4, 5 ] + # Swap first two edges - so 1 appears first + swap( data, 0, 1 ) + assert topsort.topsort_levels( data )[ 0 ] == [ 1, 0, 6 ] + assert topsort.topsort( data ) == [ 1, 0, 6, 2, 3, 4, 5 ] + + # Shouldn't really affect sorting of 1 0 6 + swap( data, 3, 4 ) + assert topsort.topsort_levels( data )[ 0 ] == [ 1, 0, 6 ] + assert topsort.topsort( data ) == [ 1, 0, 6, 2, 3, 4, 5 ] + + # Place 0 before 6 in original list + swap( data, 1, 6 ) + assert topsort.topsort_levels( data )[ 0 ] == [ 1, 6, 0 ] + assert topsort.topsort( data ) == [ 1, 6, 0, 2, 3, 4, 5 ] + + +def test_topsort_doc(): + assert topsort.topsort([(1, 2), (3, 3)]) == [1, 3, 2] + + +def swap(lst, i, j): + tmp = lst[j] + lst[j] = lst[i] + lst[i] = tmp Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.