Best Python code snippet using locust
test_components.py
Source:test_components.py  
1# Copyright 2018 The Kubeflow Authors2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#      http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14import mock15import os16import requests17import sys18import textwrap19import unittest20from contextlib import contextmanager21from pathlib import Path22from .. import components as comp23from ..components._components import _resolve_command_line_and_paths24from ..components._yaml_utils import load_yaml25from ..components.structures import ComponentSpec26class LoadComponentTestCase(unittest.TestCase):27    def _test_load_component_from_file(self, component_path: str):28        task_factory1 = comp.load_component_from_file(component_path)29        arg1 = 330        arg2 = 531        task1 = task_factory1(arg1, arg2)32        self.assertEqual(task_factory1.__name__, 'Add')33        self.assertEqual(task_factory1.__doc__.strip(), 'Add\nReturns sum of two arguments')34        self.assertEqual(task1.component_ref.spec.implementation.container.image, 'python:3.5')35        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)36        self.assertEqual(resolved_cmd.args[0], str(arg1))37        self.assertEqual(resolved_cmd.args[1], str(arg2))38    def test_load_component_from_yaml_file(self):39        component_path = Path(__file__).parent / 'test_data' / 'python_add.component.yaml'40        self._test_load_component_from_file(str(component_path))41    def test_load_component_from_zipped_yaml_file(self):42        component_path = Path(__file__).parent / 'test_data' / 'python_add.component.zip'43        self._test_load_component_from_file(str(component_path))44    def test_load_component_from_url(self):45        component_path = Path(__file__).parent / 'test_data' / 'python_add.component.yaml'46        component_url = 'https://raw.githubusercontent.com/some/repo/components/component_group/python_add/component.yaml'47        component_bytes = component_path.read_bytes()48        component_dict = load_yaml(component_bytes)49        def mock_response_factory(url, params=None, **kwargs):50            if url == component_url:51                response = requests.Response()52                response.url = component_url53                response.status_code = 20054                response._content = component_bytes55                return response56            raise RuntimeError('Unexpected URL "{}"'.format(url))57        with mock.patch('requests.get', mock_response_factory):58            task_factory1 = comp.load_component_from_url(component_url)59        self.assertEqual(task_factory1.__doc__, component_dict['name'] + '\n' + component_dict['description'])60        arg1 = 361        arg2 = 562        task1 = task_factory1(arg1, arg2)63        self.assertEqual(task1.component_ref.spec.implementation.container.image, component_dict['implementation']['container']['image'])64        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)65        self.assertEqual(resolved_cmd.args[0], str(arg1))66        self.assertEqual(resolved_cmd.args[1], str(arg2))67    def test_loading_minimal_component(self):68        component_text = '''\69implementation:70  container:71    image: busybox72'''73        component_dict = load_yaml(component_text)74        task_factory1 = comp.load_component(text=component_text)75        self.assertEqual(task_factory1.component_spec.implementation.container.image, component_dict['implementation']['container']['image'])76    def test_digest_of_loaded_component(self):77        component_text = textwrap.dedent('''\78            implementation:79              container:80                image: busybox81            '''82        )83        task_factory1 = comp.load_component_from_text(component_text)84        task1 = task_factory1()85        self.assertEqual(task1.component_ref.digest, '1ede211233e869581d098673962c2c1e8c1e4cebb7cf5d7332c2f73cb4900823')86    def test_accessing_component_spec_from_task_factory(self):87        component_text = '''\88implementation:89  container:90    image: busybox91'''92        task_factory1 = comp.load_component_from_text(component_text)93        actual_component_spec = task_factory1.component_spec94        actual_component_spec_dict = actual_component_spec.to_dict()95        expected_component_spec_dict = load_yaml(component_text)96        expected_component_spec = ComponentSpec.from_dict(expected_component_spec_dict)97        self.assertEqual(expected_component_spec_dict, actual_component_spec_dict)98        self.assertEqual(expected_component_spec, task_factory1.component_spec)99    def test_fail_on_duplicate_input_names(self):100        component_text = '''\101inputs:102- {name: Data1}103- {name: Data1}104implementation:105  container:106    image: busybox107'''108        with self.assertRaises(ValueError):109            task_factory1 = comp.load_component_from_text(component_text)110    def test_fail_on_duplicate_output_names(self):111        component_text = '''\112outputs:113- {name: Data1}114- {name: Data1}115implementation:116  container:117    image: busybox118'''119        with self.assertRaises(ValueError):120            task_factory1 = comp.load_component_from_text(component_text)121    def test_handle_underscored_input_names(self):122        component_text = '''\123inputs:124- {name: Data}125- {name: _Data}126implementation:127  container:128    image: busybox129'''130        task_factory1 = comp.load_component_from_text(component_text)131    def test_handle_underscored_output_names(self):132        component_text = '''\133outputs:134- {name: Data}135- {name: _Data}136implementation:137  container:138    image: busybox139'''140        task_factory1 = comp.load_component_from_text(component_text)141    def test_handle_input_names_with_spaces(self):142        component_text = '''\143inputs:144- {name: Training data}145implementation:146  container:147    image: busybox148'''149        task_factory1 = comp.load_component_from_text(component_text)150    def test_handle_output_names_with_spaces(self):151        component_text = '''\152outputs:153- {name: Training data}154implementation:155  container:156    image: busybox157'''158        task_factory1 = comp.load_component_from_text(component_text)159    def test_handle_file_outputs_with_spaces(self):160        component_text = '''\161outputs:162- {name: Output data}163implementation:164  container:165    image: busybox166    fileOutputs:167      Output data: /outputs/output-data168'''169        task_factory1 = comp.load_component_from_text(component_text)170    def test_handle_similar_input_names(self):171        component_text = '''\172inputs:173- {name: Input 1}174- {name: Input_1}175- {name: Input-1}176implementation:177  container:178    image: busybox179'''180        task_factory1 = comp.load_component_from_text(component_text)181    def test_conflicting_name_renaming_stability(self):182        # Checking that already pythonic input names are not renamed183        # Checking that renaming is deterministic184        component_text = textwrap.dedent('''\185            inputs:186            - {name: Input 1}187            - {name: Input_1}188            - {name: Input-1}189            - {name: input_1}  # Last in the list, but is pythonic, so it should not be renamed190            implementation:191              container:192                image: busybox193                command:194                - inputValue: Input 1195                - inputValue: Input_1196                - inputValue: Input-1197                - inputValue: input_1198            '''199        )200        task_factory1 = comp.load_component(text=component_text)201        task1 = task_factory1(202          input_1_2='value_1_2',203          input_1_3='value_1_3',204          input_1_4='value_1_4',205          input_1='value_1',  # Expecting this input not to be renamed206        )207        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)208        self.assertEqual(resolved_cmd.command, ['value_1_2', 'value_1_3', 'value_1_4', 'value_1'])209    def test_handle_duplicate_input_output_names(self):210        component_text = '''\211inputs:212- {name: Data}213outputs:214- {name: Data}215implementation:216  container:217    image: busybox218'''219        task_factory1 = comp.load_component_from_text(component_text)220    def test_fail_on_unknown_value_argument(self):221        component_text = '''\222inputs:223- {name: Data}224implementation:225  container:226    image: busybox227    args:228      - {inputValue: Wrong}229'''230        with self.assertRaises(TypeError):231            task_factory1 = comp.load_component_from_text(component_text)232    def test_fail_on_unknown_file_output(self):233        component_text = '''\234outputs:235- {name: Data}236implementation:237  container:238    image: busybox239    fileOutputs:240        Wrong: '/outputs/output.txt'241'''242        with self.assertRaises(TypeError):243            task_factory1 = comp.load_component_from_text(component_text)244    def test_load_component_fail_on_no_sources(self):245        with self.assertRaises(ValueError):246            comp.load_component()247    def test_load_component_fail_on_multiple_sources(self):248        with self.assertRaises(ValueError):249            comp.load_component(filename='', text='')250    def test_load_component_fail_on_none_arguments(self):251        with self.assertRaises(ValueError):252            comp.load_component(filename=None, url=None, text=None)253    def test_load_component_from_file_fail_on_none_arg(self):254        with self.assertRaises(TypeError):255            comp.load_component_from_file(None)256    def test_load_component_from_url_fail_on_none_arg(self):257        with self.assertRaises(TypeError):258            comp.load_component_from_url(None)259    def test_load_component_from_text_fail_on_none_arg(self):260        with self.assertRaises(TypeError):261            comp.load_component_from_text(None)262    def test_input_value_resolving(self):263        component_text = '''\264inputs:265- {name: Data}266implementation:267  container:268    image: busybox269    args:270      - --data271      - inputValue: Data272'''273        task_factory1 = comp.load_component(text=component_text)274        task1 = task_factory1('some-data')275        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)276        self.assertEqual(resolved_cmd.args, ['--data', 'some-data'])277    def test_automatic_output_resolving(self):278        component_text = '''\279outputs:280- {name: Data}281implementation:282  container:283    image: busybox284    args:285      - --output-data286      - {outputPath: Data}287'''288        task_factory1 = comp.load_component(text=component_text)289        task1 = task_factory1()290        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)291        self.assertEqual(len(resolved_cmd.args), 2)292        self.assertEqual(resolved_cmd.args[0], '--output-data')293        self.assertTrue(resolved_cmd.args[1].startswith('/'))294    def test_input_path_placeholder_with_constant_argument(self):295        component_text = '''\296inputs:297- {name: input 1}298implementation:299  container:300    image: busybox301    command:302      - --input-data303      - {inputPath: input 1}304'''305        task_factory1 = comp.load_component_from_text(component_text)306        task1 = task_factory1('Text')307        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)308        self.assertEqual(resolved_cmd.command, ['--input-data', resolved_cmd.input_paths['input 1']])309        self.assertEqual(task1.arguments, {'input 1': 'Text'})310    def test_optional_inputs_reordering(self):311        '''Tests optional input reordering.312        In python signature, optional arguments must come after the required arguments.313        '''314        component_text = '''\315inputs:316- {name: in1}317- {name: in2, optional: true}318- {name: in3}319implementation:320  container:321    image: busybox322'''323        task_factory1 = comp.load_component_from_text(component_text)324        import inspect325        signature = inspect.signature(task_factory1)326        actual_signature = list(signature.parameters.keys())327        self.assertSequenceEqual(actual_signature, ['in1', 'in3', 'in2'], str)328    def test_inputs_reordering_when_inputs_have_defaults(self):329        '''Tests reordering of inputs with default values.330        In python signature, optional arguments must come after the required arguments.331        '''332        component_text = '''\333inputs:334- {name: in1}335- {name: in2, default: val}336- {name: in3}337implementation:338  container:339    image: busybox340'''341        task_factory1 = comp.load_component_from_text(component_text)342        import inspect343        signature = inspect.signature(task_factory1)344        actual_signature = list(signature.parameters.keys())345        self.assertSequenceEqual(actual_signature, ['in1', 'in3', 'in2'], str)346    def test_inputs_reordering_stability(self):347        '''Tests input reordering stability. Required inputs and optional/default inputs should keep the ordering.348        In python signature, optional arguments must come after the required arguments.349        '''350        component_text = '''\351inputs:352- {name: a1}353- {name: b1, default: val}354- {name: a2}355- {name: b2, optional: True}356- {name: a3}357- {name: b3, default: val}358- {name: a4}359- {name: b4, optional: True}360implementation:361  container:362    image: busybox363'''364        task_factory1 = comp.load_component_from_text(component_text)365        import inspect366        signature = inspect.signature(task_factory1)367        actual_signature = list(signature.parameters.keys())368        self.assertSequenceEqual(actual_signature, ['a1', 'a2', 'a3', 'a4', 'b1', 'b2', 'b3', 'b4'], str)369    def test_missing_optional_input_value_argument(self):370        '''Missing optional inputs should resolve to nothing'''371        component_text = '''\372inputs:373- {name: input 1, optional: true}374implementation:375  container:376    image: busybox377    command:378      - a379      - {inputValue: input 1}380      - z381'''382        task_factory1 = comp.load_component_from_text(component_text)383        task1 = task_factory1()384        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)385        self.assertEqual(resolved_cmd.command, ['a', 'z'])386    def test_missing_optional_input_file_argument(self):387        '''Missing optional inputs should resolve to nothing'''388        component_text = '''\389inputs:390- {name: input 1, optional: true}391implementation:392  container:393    image: busybox394    command:395      - a396      - {inputPath: input 1}397      - z398'''399        task_factory1 = comp.load_component_from_text(component_text)400        task1 = task_factory1()401        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)402        self.assertEqual(resolved_cmd.command, ['a', 'z'])403    def test_command_concat(self):404        component_text = '''\405inputs:406- {name: In1}407- {name: In2}408implementation:409  container:410    image: busybox411    args:412      - concat: [{inputValue: In1}, {inputValue: In2}]413'''414        task_factory1 = comp.load_component(text=component_text)415        task1 = task_factory1('some', 'data')416        resolved_cmd = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)417        self.assertEqual(resolved_cmd.args, ['somedata'])418    def test_command_if_boolean_true_then_else(self):419        component_text = '''\420implementation:421  container:422    image: busybox423    args:424      - if:425          cond: true426          then: --true-arg427          else: --false-arg428'''429        task_factory1 = comp.load_component(text=component_text)430        task = task_factory1()431        resolved_cmd = _resolve_command_line_and_paths(task.component_ref.spec, task.arguments)432        self.assertEqual(resolved_cmd.args, ['--true-arg']) 433    def test_command_if_boolean_false_then_else(self):434        component_text = '''\435implementation:436  container:437    image: busybox438    args:439      - if:440          cond: false441          then: --true-arg442          else: --false-arg443'''444        task_factory1 = comp.load_component(text=component_text)445        task = task_factory1()446        resolved_cmd = _resolve_command_line_and_paths(task.component_ref.spec, task.arguments)447        self.assertEqual(resolved_cmd.args, ['--false-arg']) 448    def test_command_if_true_string_then_else(self):449        component_text = '''\450implementation:451  container:452    image: busybox453    args:454      - if:455          cond: 'true'456          then: --true-arg457          else: --false-arg458'''459        task_factory1 = comp.load_component(text=component_text)460        task = task_factory1()461        resolved_cmd = _resolve_command_line_and_paths(task.component_ref.spec, task.arguments)462        self.assertEqual(resolved_cmd.args, ['--true-arg']) 463    def test_command_if_false_string_then_else(self):464        component_text = '''\465implementation:466  container:467    image: busybox468    args:469      - if:470          cond: 'false'471          then: --true-arg472          else: --false-arg473'''474        task_factory1 = comp.load_component(text=component_text)475        task = task_factory1()476        resolved_cmd = _resolve_command_line_and_paths(task.component_ref.spec, task.arguments)477        self.assertEqual(resolved_cmd.args, ['--false-arg']) 478    def test_command_if_is_present_then(self):479        component_text = '''\480inputs:481- {name: In, optional: true}482implementation:483  container:484    image: busybox485    args:486      - if:487          cond: {isPresent: In}488          then: [--in, {inputValue: In}]489          #else: --no-in490'''491        task_factory1 = comp.load_component(text=component_text)492        task_then = task_factory1('data')493        resolved_cmd_then = _resolve_command_line_and_paths(task_then.component_ref.spec, task_then.arguments)494        self.assertEqual(resolved_cmd_then.args, ['--in', 'data']) 495        496        task_else = task_factory1()497        resolved_cmd_else = _resolve_command_line_and_paths(task_else.component_ref.spec, task_else.arguments)498        self.assertEqual(resolved_cmd_else.args, [])499    def test_command_if_is_present_then_else(self):500        component_text = '''\501inputs:502- {name: In, optional: true}503implementation:504  container:505    image: busybox506    args:507      - if:508          cond: {isPresent: In}509          then: [--in, {inputValue: In}]510          else: --no-in511'''512        task_factory1 = comp.load_component(text=component_text)513        task_then = task_factory1('data')514        resolved_cmd_then = _resolve_command_line_and_paths(task_then.component_ref.spec, task_then.arguments)515        self.assertEqual(resolved_cmd_then.args, ['--in', 'data']) 516        517        task_else = task_factory1()518        resolved_cmd_else = _resolve_command_line_and_paths(task_else.component_ref.spec, task_else.arguments)519        self.assertEqual(resolved_cmd_else.args, ['--no-in'])520    def test_command_if_input_value_then(self):521        component_text = '''\522inputs:523- {name: Do test, type: Boolean, optional: true}524- {name: Test data, type: Integer, optional: true}525- {name: Test parameter 1, optional: true}526implementation:527  container:528    image: busybox529    args:530      - if:531          cond: {inputValue: Do test}532          then: [--test-data, {inputValue: Test data}, --test-param1, {inputValue: Test parameter 1}]533'''534        task_factory1 = comp.load_component(text=component_text)535        task_then = task_factory1(True, 'test_data.txt', '42')536        resolved_cmd_then = _resolve_command_line_and_paths(task_then.component_ref.spec, task_then.arguments)537        self.assertEqual(resolved_cmd_then.args, ['--test-data', 'test_data.txt', '--test-param1', '42'])538        539        task_else = task_factory1()540        resolved_cmd_else = _resolve_command_line_and_paths(task_else.component_ref.spec, task_else.arguments)541        self.assertEqual(resolved_cmd_else.args, [])542    def test_handle_default_values_in_task_factory(self):543        component_text = '''\544inputs:545- {name: Data, default: '123'}546implementation:547  container:548    image: busybox549    args:550      - {inputValue: Data}551'''552        task_factory1 = comp.load_component_from_text(text=component_text)553        task1 = task_factory1()554        resolved_cmd1 = _resolve_command_line_and_paths(task1.component_ref.spec, task1.arguments)555        self.assertEqual(resolved_cmd1.args, ['123'])556        task2 = task_factory1('456')557        resolved_cmd2 = _resolve_command_line_and_paths(task2.component_ref.spec, task2.arguments)558        self.assertEqual(resolved_cmd2.args, ['456'])559    def test_check_task_spec_outputs_dictionary(self):560        component_text = '''\561outputs:562- {name: out 1}563- {name: out 2}564implementation:565  container:566    image: busybox567    command: [touch, {outputPath: out 1}, {outputPath: out 2}]568'''569        op = comp.load_component_from_text(component_text)570        task = op()571        self.assertEqual(list(task.outputs.keys()), ['out 1', 'out 2'])572    def test_check_task_object_no_output_attribute_when_0_outputs(self):573        component_text = textwrap.dedent('''\574            implementation:575              container:576                image: busybox577                command: []578            ''',579        )580        op = comp.load_component_from_text(component_text)581        task = op()582        self.assertFalse(hasattr(task, 'output'))583    def test_check_task_object_has_output_attribute_when_1_output(self):584        component_text = textwrap.dedent('''\585            outputs:586            - {name: out 1}587            implementation:588              container:589                image: busybox590                command: [touch, {outputPath: out 1}]591            ''',592        )593        op = comp.load_component_from_text(component_text)594        task = op()595        self.assertEqual(task.output.task_output.output_name, 'out 1')596    def test_check_task_object_no_output_attribute_when_multiple_outputs(self):597        component_text = textwrap.dedent('''\598            outputs:599            - {name: out 1}600            - {name: out 2}601            implementation:602              container:603                image: busybox604                command: [touch, {outputPath: out 1}, {outputPath: out 2}]605            ''',606        )607        op = comp.load_component_from_text(component_text)608        task = op()609        self.assertFalse(hasattr(task, 'output'))610    def test_prevent_passing_unserializable_objects_as_argument(self):611        component_text = textwrap.dedent('''\612            inputs:613            - {name: input 1}614            - {name: input 2}615            implementation:616                container:617                    image: busybox618                    command:619                    - prog620                    - {inputValue: input 1}621                    - {inputPath: input 2}622            '''623        )624        component = comp.load_component_from_text(component_text)625        # Passing normal values to component626        task1 = component(input_1="value 1", input_2="value 2")627        # Passing unserializable values to component628        with self.assertRaises(TypeError):629            component(input_1=task1, input_2="value 2")630        with self.assertRaises(TypeError):631            component(input_1=open, input_2="value 2")632        with self.assertRaises(TypeError):633            component(input_1="value 1", input_2=task1)634        with self.assertRaises(TypeError):635            component(input_1="value 1", input_2=open)636    def test_check_type_validation_of_task_spec_outputs(self):637        producer_component_text = '''\638outputs:639- {name: out1, type: Integer}640- {name: out2, type: String}641implementation:642  container:643    image: busybox644    command: [touch, {outputPath: out1}, {outputPath: out2}]645'''646        consumer_component_text = '''\647inputs:648- {name: data, type: Integer}649implementation:650  container:651    image: busybox652    command: [echo, {inputValue: data}]653'''654        producer_op = comp.load_component_from_text(producer_component_text)655        consumer_op = comp.load_component_from_text(consumer_component_text)656        producer_task = producer_op()657        consumer_op(producer_task.outputs['out1'])658        consumer_op(producer_task.outputs['out2'].without_type())659        consumer_op(producer_task.outputs['out2'].with_type('Integer'))660        with self.assertRaises(TypeError):661          consumer_op(producer_task.outputs['out2'])662    def test_type_compatibility_check_for_simple_types(self):663        component_a = '''\664outputs:665  - {name: out1, type: custom_type}666implementation:667  container:668    image: busybox669    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]670'''671        component_b = '''\672inputs:673  - {name: in1, type: custom_type}674implementation:675  container:676    image: busybox677    command: [echo, {inputValue: in1}]678'''679        task_factory_a = comp.load_component_from_text(component_a)680        task_factory_b = comp.load_component_from_text(component_b)681        a_task = task_factory_a()682        b_task = task_factory_b(in1=a_task.outputs['out1'])683    def test_type_compatibility_check_for_types_with_parameters(self):684        component_a = '''\685outputs:686  - {name: out1, type: {parametrized_type: {property_a: value_a, property_b: value_b}}}687implementation:688  container:689    image: busybox690    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]691'''692        component_b = '''\693inputs:694  - {name: in1, type: {parametrized_type: {property_a: value_a, property_b: value_b}}}695implementation:696  container:697    image: busybox698    command: [echo, {inputValue: in1}]699'''700        task_factory_a = comp.load_component_from_text(component_a)701        task_factory_b = comp.load_component_from_text(component_b)702        a_task = task_factory_a()703        b_task = task_factory_b(in1=a_task.outputs['out1'])704    def test_type_compatibility_check_when_using_positional_arguments(self):705        """Tests that `op2(task1.output)` works as good as `op2(in1=task1.output)`"""706        component_a = '''\707outputs:708  - {name: out1, type: {parametrized_type: {property_a: value_a, property_b: value_b}}}709implementation:710  container:711    image: busybox712    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]713'''714        component_b = '''\715inputs:716  - {name: in1, type: {parametrized_type: {property_a: value_a, property_b: value_b}}}717implementation:718  container:719    image: busybox720    command: [echo, {inputValue: in1}]721'''722        task_factory_a = comp.load_component_from_text(component_a)723        task_factory_b = comp.load_component_from_text(component_b)724        a_task = task_factory_a()725        b_task = task_factory_b(a_task.outputs['out1'])726    def test_type_compatibility_check_when_input_type_is_missing(self):727        component_a = '''\728outputs:729  - {name: out1, type: custom_type}730implementation:731  container:732    image: busybox733    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]734'''735        component_b = '''\736inputs:737  - {name: in1}738implementation:739  container:740    image: busybox741    command: [echo, {inputValue: in1}]742'''743        task_factory_a = comp.load_component_from_text(component_a)744        task_factory_b = comp.load_component_from_text(component_b)745        a_task = task_factory_a()746        b_task = task_factory_b(in1=a_task.outputs['out1'])747    def test_type_compatibility_check_when_argument_type_is_missing(self):748        component_a = '''\749outputs:750  - {name: out1}751implementation:752  container:753    image: busybox754    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]755'''756        component_b = '''\757inputs:758  - {name: in1, type: custom_type}759implementation:760  container:761    image: busybox762    command: [echo, {inputValue: in1}]763'''764        task_factory_a = comp.load_component_from_text(component_a)765        task_factory_b = comp.load_component_from_text(component_b)766        a_task = task_factory_a()767        b_task = task_factory_b(in1=a_task.outputs['out1'])768    def test_fail_type_compatibility_check_when_simple_type_name_is_different(self):769        component_a = '''\770outputs:771  - {name: out1, type: type_A}772implementation:773  container:774    image: busybox775    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]776'''777        component_b = '''\778inputs:779  - {name: in1, type: type_Z}780implementation:781  container:782    image: busybox783    command: [echo, {inputValue: in1}]784'''785        task_factory_a = comp.load_component_from_text(component_a)786        task_factory_b = comp.load_component_from_text(component_b)787        a_task = task_factory_a()788        with self.assertRaises(TypeError):789            b_task = task_factory_b(in1=a_task.outputs['out1'])790    def test_fail_type_compatibility_check_when_parametrized_type_name_is_different(self):791        component_a = '''\792outputs:793  - {name: out1, type: {parametrized_type_A: {property_a: value_a}}}794implementation:795  container:796    image: busybox797    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]798'''799        component_b = '''\800inputs:801  - {name: in1, type: {parametrized_type_Z: {property_a: value_a}}}802implementation:803  container:804    image: busybox805    command: [echo, {inputValue: in1}]806'''807        task_factory_a = comp.load_component_from_text(component_a)808        task_factory_b = comp.load_component_from_text(component_b)809        a_task = task_factory_a()810        with self.assertRaises(TypeError):811            b_task = task_factory_b(in1=a_task.outputs['out1'])812    def test_fail_type_compatibility_check_when_type_property_value_is_different(self):813        component_a = '''\814outputs:815  - {name: out1, type: {parametrized_type: {property_a: value_a}}}816implementation:817  container:818    image: busybox819    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]820'''821        component_b = '''\822inputs:823  - {name: in1, type: {parametrized_type: {property_a: DIFFERENT VALUE}}}824implementation:825  container:826    image: busybox827    command: [echo, {inputValue: in1}]828'''829        task_factory_a = comp.load_component_from_text(component_a)830        task_factory_b = comp.load_component_from_text(component_b)831        a_task = task_factory_a()832        with self.assertRaises(TypeError):833            b_task = task_factory_b(in1=a_task.outputs['out1'])834    @unittest.skip('Type compatibility check currently works the opposite way')835    def test_type_compatibility_check_when_argument_type_has_extra_type_parameters(self):836        component_a = '''\837outputs:838  - {name: out1, type: {parametrized_type: {property_a: value_a, extra_property: extra_value}}}839implementation:840  container:841    image: busybox842    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]843'''844        component_b = '''\845inputs:846  - {name: in1, type: {parametrized_type: {property_a: value_a}}}847implementation:848  container:849    image: busybox850    command: [echo, {inputValue: in1}]851'''852        task_factory_a = comp.load_component_from_text(component_a)853        task_factory_b = comp.load_component_from_text(component_b)854        a_task = task_factory_a()855        b_task = task_factory_b(in1=a_task.outputs['out1'])856    @unittest.skip('Type compatibility check currently works the opposite way')857    def test_fail_type_compatibility_check_when_argument_type_has_missing_type_parameters(self):858        component_a = '''\859outputs:860  - {name: out1, type: {parametrized_type: {property_a: value_a}}}861implementation:862  container:863    image: busybox864    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]865'''866        component_b = '''\867inputs:868  - {name: in1, type: {parametrized_type: {property_a: value_a, property_b: value_b}}}869implementation:870  container:871    image: busybox872    command: [echo, {inputValue: in1}]873'''874        task_factory_a = comp.load_component_from_text(component_a)875        task_factory_b = comp.load_component_from_text(component_b)876        a_task = task_factory_a()877        with self.assertRaises(TypeError):878            b_task = task_factory_b(in1=a_task.outputs['out1'])879    def test_type_compatibility_check_not_failing_when_type_is_ignored(self):880        component_a = '''\881outputs:882  - {name: out1, type: type_A}883implementation:884  container:885    image: busybox886    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]887'''888        component_b = '''\889inputs:890  - {name: in1, type: type_Z}891implementation:892  container:893    image: busybox894    command: [echo, {inputValue: in1}]895'''896        task_factory_a = comp.load_component_from_text(component_a)897        task_factory_b = comp.load_component_from_text(component_b)898        a_task = task_factory_a()899        b_task = task_factory_b(in1=a_task.outputs['out1'].without_type())900    def test_type_compatibility_check_for_types_with_schema(self):901        component_a = '''\902outputs:903  - {name: out1, type: {GCSPath: {openapi_schema_validator: {type: string, pattern: "^gs://.*$" } }}}904implementation:905  container:906    image: busybox907    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]908'''909        component_b = '''\910inputs:911  - {name: in1, type: {GCSPath: {openapi_schema_validator: {type: string, pattern: "^gs://.*$" } }}}912implementation:913  container:914    image: busybox915    command: [echo, {inputValue: in1}]916'''917        task_factory_a = comp.load_component_from_text(component_a)918        task_factory_b = comp.load_component_from_text(component_b)919        a_task = task_factory_a()920        b_task = task_factory_b(in1=a_task.outputs['out1'])921    def test_fail_type_compatibility_check_for_types_with_different_schemas(self):922        component_a = '''\923outputs:924  - {name: out1, type: {GCSPath: {openapi_schema_validator: {type: string, pattern: AAA } }}}925implementation:926  container:927    image: busybox928    command: [bash, -c, 'mkdir -p "$(dirname "$0")"; date > "$0"', {outputPath: out1}]929'''930        component_b = '''\931inputs:932  - {name: in1, type: {GCSPath: {openapi_schema_validator: {type: string, pattern: ZZZ } }}}933implementation:934  container:935    image: busybox936    command: [echo, {inputValue: in1}]937'''938        task_factory_a = comp.load_component_from_text(component_a)939        task_factory_b = comp.load_component_from_text(component_b)940        a_task = task_factory_a()941        with self.assertRaises(TypeError):942            b_task = task_factory_b(in1=a_task.outputs['out1'])943    def test_container_component_without_command_should_warn(self):944        component_a = '''\945name: component without command946inputs:947  - {name: in1, type: String}948implementation:949  container:950    image: busybox951'''952        with self.assertWarnsRegex(953            FutureWarning,954            'Container component must specify command to be compatible with '955            'KFP v2 compatible mode and emissary executor'):956            task_factory_a = comp.load_component_from_text(component_a)957if __name__ == '__main__':...test_task.py
Source:test_task.py  
1# -*- coding: utf-8 -*-2#    Copyright 2015 Hewlett-Packard Development Company, L.P.3#    Copyright (C) 2013 Yahoo! Inc. All Rights Reserved.4#5#    Licensed under the Apache License, Version 2.0 (the "License"); you may6#    not use this file except in compliance with the License. You may obtain7#    a copy of the License at8#9#         http://www.apache.org/licenses/LICENSE-2.010#11#    Unless required by applicable law or agreed to in writing, software12#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT13#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the14#    License for the specific language governing permissions and limitations15#    under the License.16from taskflow import task17from taskflow import test18from taskflow.test import mock19from taskflow.types import notifier20class MyTask(task.Task):21    def execute(self, context, spam, eggs):22        pass23class KwargsTask(task.Task):24    def execute(self, spam, **kwargs):25        pass26class DefaultArgTask(task.Task):27    def execute(self, spam, eggs=()):28        pass29class DefaultProvidesTask(task.Task):30    default_provides = 'def'31    def execute(self):32        return None33class ProgressTask(task.Task):34    def execute(self, values, **kwargs):35        for value in values:36            self.update_progress(value)37class TaskTest(test.TestCase):38    def test_passed_name(self):39        my_task = MyTask(name='my name')40        self.assertEqual('my name', my_task.name)41    def test_generated_name(self):42        my_task = MyTask()43        self.assertEqual('%s.%s' % (__name__, 'MyTask'),44                         my_task.name)45    def test_task_str(self):46        my_task = MyTask(name='my')47        self.assertEqual('my==1.0', str(my_task))48    def test_task_repr(self):49        my_task = MyTask(name='my')50        self.assertEqual('<%s.MyTask my==1.0>' % __name__, repr(my_task))51    def test_no_provides(self):52        my_task = MyTask()53        self.assertEqual({}, my_task.save_as)54    def test_provides(self):55        my_task = MyTask(provides='food')56        self.assertEqual({'food': None}, my_task.save_as)57    def test_multi_provides(self):58        my_task = MyTask(provides=('food', 'water'))59        self.assertEqual({'food': 0, 'water': 1}, my_task.save_as)60    def test_unpack(self):61        my_task = MyTask(provides=('food',))62        self.assertEqual({'food': 0}, my_task.save_as)63    def test_bad_provides(self):64        self.assertRaisesRegexp(TypeError, '^Atom provides',65                                MyTask, provides=object())66    def test_requires_by_default(self):67        my_task = MyTask()68        expected = {69            'spam': 'spam',70            'eggs': 'eggs',71            'context': 'context'72        }73        self.assertEqual(expected,74                         my_task.rebind)75        self.assertEqual(set(['spam', 'eggs', 'context']),76                         my_task.requires)77    def test_requires_amended(self):78        my_task = MyTask(requires=('spam', 'eggs'))79        expected = {80            'spam': 'spam',81            'eggs': 'eggs',82            'context': 'context'83        }84        self.assertEqual(expected, my_task.rebind)85    def test_requires_explicit(self):86        my_task = MyTask(auto_extract=False,87                         requires=('spam', 'eggs', 'context'))88        expected = {89            'spam': 'spam',90            'eggs': 'eggs',91            'context': 'context'92        }93        self.assertEqual(expected, my_task.rebind)94    def test_requires_explicit_not_enough(self):95        self.assertRaisesRegexp(ValueError, '^Missing arguments',96                                MyTask,97                                auto_extract=False, requires=('spam', 'eggs'))98    def test_requires_ignores_optional(self):99        my_task = DefaultArgTask()100        self.assertEqual(set(['spam']), my_task.requires)101        self.assertEqual(set(['eggs']), my_task.optional)102    def test_requires_allows_optional(self):103        my_task = DefaultArgTask(requires=('spam', 'eggs'))104        self.assertEqual(set(['spam', 'eggs']), my_task.requires)105        self.assertEqual(set(), my_task.optional)106    def test_rebind_includes_optional(self):107        my_task = DefaultArgTask()108        expected = {109            'spam': 'spam',110            'eggs': 'eggs',111        }112        self.assertEqual(expected, my_task.rebind)113    def test_rebind_all_args(self):114        my_task = MyTask(rebind={'spam': 'a', 'eggs': 'b', 'context': 'c'})115        expected = {116            'spam': 'a',117            'eggs': 'b',118            'context': 'c'119        }120        self.assertEqual(expected, my_task.rebind)121        self.assertEqual(set(['a', 'b', 'c']),122                         my_task.requires)123    def test_rebind_partial(self):124        my_task = MyTask(rebind={'spam': 'a', 'eggs': 'b'})125        expected = {126            'spam': 'a',127            'eggs': 'b',128            'context': 'context'129        }130        self.assertEqual(expected, my_task.rebind)131        self.assertEqual(set(['a', 'b', 'context']),132                         my_task.requires)133    def test_rebind_unknown(self):134        self.assertRaisesRegexp(ValueError, '^Extra arguments',135                                MyTask, rebind={'foo': 'bar'})136    def test_rebind_unknown_kwargs(self):137        task = KwargsTask(rebind={'foo': 'bar'})138        expected = {139            'foo': 'bar',140            'spam': 'spam'141        }142        self.assertEqual(expected, task.rebind)143    def test_rebind_list_all(self):144        my_task = MyTask(rebind=('a', 'b', 'c'))145        expected = {146            'context': 'a',147            'spam': 'b',148            'eggs': 'c'149        }150        self.assertEqual(expected, my_task.rebind)151        self.assertEqual(set(['a', 'b', 'c']),152                         my_task.requires)153    def test_rebind_list_partial(self):154        my_task = MyTask(rebind=('a', 'b'))155        expected = {156            'context': 'a',157            'spam': 'b',158            'eggs': 'eggs'159        }160        self.assertEqual(expected, my_task.rebind)161        self.assertEqual(set(['a', 'b', 'eggs']),162                         my_task.requires)163    def test_rebind_list_more(self):164        self.assertRaisesRegexp(ValueError, '^Extra arguments',165                                MyTask, rebind=('a', 'b', 'c', 'd'))166    def test_rebind_list_more_kwargs(self):167        task = KwargsTask(rebind=('a', 'b', 'c'))168        expected = {169            'spam': 'a',170            'b': 'b',171            'c': 'c'172        }173        self.assertEqual(expected, task.rebind)174        self.assertEqual(set(['a', 'b', 'c']),175                         task.requires)176    def test_rebind_list_bad_value(self):177        self.assertRaisesRegexp(TypeError, '^Invalid rebind value',178                                MyTask, rebind=object())179    def test_default_provides(self):180        task = DefaultProvidesTask()181        self.assertEqual(set(['def']), task.provides)182        self.assertEqual({'def': None}, task.save_as)183    def test_default_provides_can_be_overridden(self):184        task = DefaultProvidesTask(provides=('spam', 'eggs'))185        self.assertEqual(set(['spam', 'eggs']), task.provides)186        self.assertEqual({'spam': 0, 'eggs': 1}, task.save_as)187    def test_update_progress_within_bounds(self):188        values = [0.0, 0.5, 1.0]189        result = []190        def progress_callback(event_type, details):191            result.append(details.pop('progress'))192        a_task = ProgressTask()193        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, progress_callback)194        a_task.execute(values)195        self.assertEqual(values, result)196    @mock.patch.object(task.LOG, 'warn')197    def test_update_progress_lower_bound(self, mocked_warn):198        result = []199        def progress_callback(event_type, details):200            result.append(details.pop('progress'))201        a_task = ProgressTask()202        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, progress_callback)203        a_task.execute([-1.0, -0.5, 0.0])204        self.assertEqual([0.0, 0.0, 0.0], result)205        self.assertEqual(2, mocked_warn.call_count)206    @mock.patch.object(task.LOG, 'warn')207    def test_update_progress_upper_bound(self, mocked_warn):208        result = []209        def progress_callback(event_type, details):210            result.append(details.pop('progress'))211        a_task = ProgressTask()212        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, progress_callback)213        a_task.execute([1.0, 1.5, 2.0])214        self.assertEqual([1.0, 1.0, 1.0], result)215        self.assertEqual(2, mocked_warn.call_count)216    @mock.patch.object(notifier.LOG, 'warn')217    def test_update_progress_handler_failure(self, mocked_warn):218        def progress_callback(*args, **kwargs):219            raise Exception('Woot!')220        a_task = ProgressTask()221        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, progress_callback)222        a_task.execute([0.5])223        self.assertEqual(1, mocked_warn.call_count)224    def test_register_handler_is_none(self):225        a_task = MyTask()226        self.assertRaises(ValueError, a_task.notifier.register,227                          task.EVENT_UPDATE_PROGRESS, None)228        self.assertEqual(0, len(a_task.notifier))229    def test_deregister_any_handler(self):230        a_task = MyTask()231        self.assertEqual(0, len(a_task.notifier))232        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS,233                                 lambda event_type, details: None)234        self.assertEqual(1, len(a_task.notifier))235        a_task.notifier.deregister_event(task.EVENT_UPDATE_PROGRESS)236        self.assertEqual(0, len(a_task.notifier))237    def test_deregister_any_handler_empty_listeners(self):238        a_task = MyTask()239        self.assertEqual(0, len(a_task.notifier))240        self.assertFalse(a_task.notifier.deregister_event(241            task.EVENT_UPDATE_PROGRESS))242        self.assertEqual(0, len(a_task.notifier))243    def test_deregister_non_existent_listener(self):244        handler1 = lambda event_type, details: None245        handler2 = lambda event_type, details: None246        a_task = MyTask()247        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, handler1)248        self.assertEqual(1, len(list(a_task.notifier.listeners_iter())))249        a_task.notifier.deregister(task.EVENT_UPDATE_PROGRESS, handler2)250        self.assertEqual(1, len(list(a_task.notifier.listeners_iter())))251        a_task.notifier.deregister(task.EVENT_UPDATE_PROGRESS, handler1)252        self.assertEqual(0, len(list(a_task.notifier.listeners_iter())))253    def test_bind_not_callable(self):254        a_task = MyTask()255        self.assertRaises(ValueError, a_task.notifier.register,256                          task.EVENT_UPDATE_PROGRESS, 2)257    def test_copy_no_listeners(self):258        handler1 = lambda event_type, details: None259        a_task = MyTask()260        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, handler1)261        b_task = a_task.copy(retain_listeners=False)262        self.assertEqual(1, len(a_task.notifier))263        self.assertEqual(0, len(b_task.notifier))264    def test_copy_listeners(self):265        handler1 = lambda event_type, details: None266        handler2 = lambda event_type, details: None267        a_task = MyTask()268        a_task.notifier.register(task.EVENT_UPDATE_PROGRESS, handler1)269        b_task = a_task.copy()270        self.assertEqual(1, len(b_task.notifier))271        self.assertTrue(a_task.notifier.deregister_event(272            task.EVENT_UPDATE_PROGRESS))273        self.assertEqual(0, len(a_task.notifier))274        self.assertEqual(1, len(b_task.notifier))275        b_task.notifier.register(task.EVENT_UPDATE_PROGRESS, handler2)276        listeners = dict(list(b_task.notifier.listeners_iter()))277        self.assertEqual(2, len(listeners[task.EVENT_UPDATE_PROGRESS]))278        self.assertEqual(0, len(a_task.notifier))279class FunctorTaskTest(test.TestCase):280    def test_creation_with_version(self):281        version = (2, 0)282        f_task = task.FunctorTask(lambda: None, version=version)283        self.assertEqual(version, f_task.version)284    def test_execute_not_callable(self):285        self.assertRaises(ValueError, task.FunctorTask, 2)286    def test_revert_not_callable(self):287        self.assertRaises(ValueError, task.FunctorTask, lambda: None,288                          revert=2)289class ReduceFunctorTaskTest(test.TestCase):290    def test_invalid_functor(self):291        # Functor not callable292        self.assertRaises(ValueError, task.ReduceFunctorTask, 2, requires=5)293        # Functor takes no arguments294        self.assertRaises(ValueError, task.ReduceFunctorTask, lambda: None,295                          requires=5)296        # Functor takes too few arguments297        self.assertRaises(ValueError, task.ReduceFunctorTask, lambda x: None,298                          requires=5)299    def test_functor_invalid_requires(self):300        # Invalid type, requires is not iterable301        self.assertRaises(TypeError, task.ReduceFunctorTask,302                          lambda x, y: None, requires=1)303        # Too few elements in requires304        self.assertRaises(ValueError, task.ReduceFunctorTask,305                          lambda x, y: None, requires=[1])306class MapFunctorTaskTest(test.TestCase):307    def test_invalid_functor(self):308        # Functor not callable309        self.assertRaises(ValueError, task.MapFunctorTask, 2, requires=5)310        # Functor takes no arguments311        self.assertRaises(ValueError, task.MapFunctorTask, lambda: None,312                          requires=5)313        # Functor takes too many arguments314        self.assertRaises(ValueError, task.MapFunctorTask, lambda x, y: None,315                          requires=5)316    def test_functor_invalid_requires(self):317        # Invalid type, requires is not iterable318        self.assertRaises(TypeError, task.MapFunctorTask, lambda x: None,...coordinator.py
Source:coordinator.py  
1#!/usr/bin/env python2import rospy3import actionlib4from task import Task, TASK_STATE_DELIVER, TASK_STATE_FETCH_TURTLE, TASK_STATE_GET_ITEM, TASK_STATE_INITIAL, \5    TASK_STATE_POSITION_TURTLE, \6    TASK_STATE_GOAL7from turtle import Turtle8from collections import deque9from tams_ur5_turtlebot_delivery_turtlebot.msg import itemRequest, OnlineTurtle10from tams_ur5_turtlebot_delivery_coordination.msg import PlaceObjectAction, PlaceObjectGoal, taskStatus11from tams_ur5_turtlebot_delivery_coordination.msg import task as task_msg12from geometry_msgs.msg import Pose13ARM_WAITING = 014ARM_LOADING = 115ARM_PLACED = 216ARM_PLACE_FAILED = 317class coordinator(object):18    def __init__(self):19        self.tasks = deque()20        self.tasksAssigned = list()21        self.turtleBots = list()22        self.armState = ARM_WAITING23        rospy.Subscriber("/itemRequest", itemRequest, self.addTask)24    def addTask(self, item_request):25        """26        This method adds a Task to the taskque27        :param item_request: a itemRequest ros message28        :return:29        """30        t = Task(item_request.pose, item_request.item, item_request.uuid)31        rospy.loginfo("New Task: " + str(t))32        self.tasks.append(t)33    # in case new TurtleBot is discovered34    def addTurtleBot(self, bot):35        rospy.loginfo("Added Turtle: " + str(bot))36        self.turtleBots.append(bot)37    # in case TurtleBot didn't send status for too long38    # remove from list so it won't be assigned tasks39    def removeTurtleBot(self, bot):40        self.turtleBots.remove(bot)41    # should be used as callback function from a42    # subscriber node periodically collecting data43    # (subscriber triggered every time data is received?)44    def updateTurtleBotStatus(self, data):45        for turtle in self.turtleBots:46            pass47            # (check for aliveness at this point or periodically?) self.removeTurtleBot()48            # create new bot if not present49            # read Bot specific values out of data and update if necessary50    def assignTask(self):51        if not self.tasks:52            return53        for turtle in self.turtleBots:54            # choose the turtle for the task55            # TODO: informed selection. For now choose the first one56            if not turtle.has_task:57                currentTask = self.tasks.popleft()58                currentTask.assign_turtle(turtle)59                currentTask.state = TASK_STATE_FETCH_TURTLE60                self.tasksAssigned.append(currentTask)61                # only assign one task62                break63    def doneCB(self, state, result):64        if result.status == 0:65            rospy.loginfo("received item")66            self.armState = ARM_PLACED67        else:68            #TODO: error handling69            rospy.loginfo("put item in region of interest")70            rospy.sleep(rospy.Duration(10.0))71            self.armState = ARM_PLACE_FAILED72    def main(self):73        rospy.init_node('coordinator', anonymous=False)74        # subscribe to requests75        task_status_publisher = rospy.Publisher('/taskStatus', taskStatus, queue_size=1)76        #create Proxy to placeActionServer of arm77        client = actionlib.SimpleActionClient('PlaceObject', PlaceObjectAction)78        client.wait_for_server()79        rospy.loginfo("Waiting for a turtle...")80        # TODO: callback to register new turtles instead of waiting for exactly one81        robotmsg = rospy.wait_for_message("/turtles", OnlineTurtle, timeout=None)82        t = Turtle(robotmsg.name, 2.466515241951, 5.809623560960491)83        self.addTurtleBot(t) # -1.23849964142, 4.34559011459))84        rate = rospy.Rate(2)85        while not rospy.is_shutdown():86            self.assignTask()87            for task in self.tasksAssigned[:]:88                if task.state is TASK_STATE_FETCH_TURTLE:89                    if task.turtle.go_to_loading():90                        task.state = TASK_STATE_POSITION_TURTLE91                if task.state is TASK_STATE_POSITION_TURTLE:92                    # TODO: mutually lock docking bay93                    if task.turtle.dock():94                        rospy.loginfo(task.turtle.name + ": docked")95                        task.state = TASK_STATE_GET_ITEM96                        goal = PlaceObjectGoal(obj=task.item)97                        client.send_goal(goal, self.doneCB)98                        self.armState = ARM_LOADING99                        rospy.loginfo(task.turtle.name + ": waiting for item to be loaded")100                if task.state is TASK_STATE_GET_ITEM:101                    if self.armState is ARM_PLACED:102                        task.state = TASK_STATE_DELIVER103                        self.armState = ARM_WAITING104                        rospy.loginfo(task.turtle.name + ": deliviering")105                    elif self.armState is ARM_PLACE_FAILED:106                        goal = PlaceObjectGoal(obj=task.item)107                        client.send_goal(goal, self.doneCB)108                        self.armState = ARM_LOADING109                if task.state is TASK_STATE_DELIVER:110                    if task.turtle.goto_goal(task.getGoal().position.x, task.getGoal().position.y):111                        task.state = TASK_STATE_GOAL112                        rospy.loginfo(task.turtle.name + ": delivered")113                        rospy.loginfo(task.turtle.name + ": wait at goal")114                if task.state is TASK_STATE_GOAL:115                    if task.turtle.wait_at_goal():116                        rospy.loginfo(task.turtle.name + ": successfully completed task")117                        task.free_turtle()118                        self.tasksAssigned.remove(task)119            for turtle in self.turtleBots:120                if turtle.docked == False and turtle.has_task == False:121                    turtle.go_to_waiting()122                    123            # send task status124            task_status = taskStatus()125            for a_task in self.tasksAssigned:126                t = task_msg()127                t.pose = a_task.position128                t.item = a_task.item129                t.id = a_task.id130                t.status = a_task.state131                t.num = a_task.taskID132                task_status.tasks.append(t)133            for a_task in self.tasks:134                t = task_msg()135                t.pose = a_task.position136                t.item = a_task.item137                t.id = a_task.id138                t.status = a_task.state139                t.num = a_task.taskID140                task_status.tasks.append(t)141            task_status_publisher.publish(task_status)142            rate.sleep()143if __name__ == '__main__':144    try:145        c = coordinator()146        c.main()147    except rospy.ROSInterruptException:...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
