Instruction:
Implement a function in Python 3 to
substitute a target state with a handed state

Response:
def substitute_state_as(target_state_m, state, as_template, keep_name=False):
    """ Substitute a target state with a handed state

    The method generates a state model for the state to be inserted and use function substitute_state to finally
    substitute the state.
    In case the state to be inserted is a LibraryState it can be chosen to be inserted as template.
    It can be chosen that the inserted state keeps the name of the target state.

    :param rafcon.gui.models.state.AbstractStateModel target_state_m: State model of the state to be substituted
    :param rafcon.core.states.State state: State to be inserted
    :param bool as_template: The flag determines if a handed state of type LibraryState is insert as template
    :param bool keep_name: The flag to keep the name of the target state
    :return:
    """

    state_m = get_state_model_class_for_state(state)(state)
    # If inserted as template, we have to extract the state_copy and model otherwise keep original name
    if as_template:
        assert isinstance(state_m, LibraryStateModel)
        state_m = state_m.state_copy
        state_m.state.parent = None

    if keep_name:
        state_m.state.name = target_state_m.state.name

    assert target_state_m.parent.states[target_state_m.state.state_id] is target_state_m
    substitute_state(target_state_m, state_m, as_template)


Instruction:
Create a Python 3 function to
add another event to the multi_event

Response:
def orify(e, changed_callback):
    """Add another event to the multi_event

    :param e: the event to be added to the multi_event
    :param changed_callback: a method to call if the event status changes, this method has access to the multi_event
    :return:
    """
    if not hasattr(e, "callbacks"):  # Event has not been orified yet
        e._set = e.set
        e._clear = e.clear
        e.set = lambda: or_set(e)
        e.clear = lambda: or_clear(e)
        e.callbacks = list()
    # Keep track of one callback per multi event
    e.callbacks.append(changed_callback)


Instruction:
Can you create a Python 3 function that
creates a new multi_event object with all events passed in the events parameter.

Response:
def create(*events):
    """Creates a new multi_event

    The multi_event listens to all events passed in the "events" parameter.

    :param events: a list of threading.Events
    :return: The multi_event
    :rtype: threading.Event
    """
    or_event = threading.Event()

    def changed():
        if any([event.is_set() for event in events]):
            or_event.set()
        else:
            or_event.clear()

    for e in events:
        orify(e, changed)

    changed()
    return or_event


Instruction:
How would you explain what the following Python 3 function does
def model_changed(self, model, prop_name, info):
        current_enables = self._get_config_enables()
        if not self._enables == current_enables:
            # check if filtered buffer update needed
            filtered_buffer_update_needed = True
            if all(self._enables[key] == current_enables[key] for key in ['VERBOSE', 'DEBUG', 'INFO', 'WARNING', 'ERROR']):
                follow_mode_key = 'CONSOLE_FOLLOW_LOGGING'
                only_follow_mode_changed = self._enables[follow_mode_key] != current_enables[follow_mode_key]
                filtered_buffer_update_needed = not only_follow_mode_changed

            self._enables = current_enables
            self.view.set_enables(self._enables)
            if filtered_buffer_update_needed:
                self.update_filtered_buffer()
            else:
                self.view.scroll_to_cursor_onscreen()

Response:
React to configuration changes
            Update internal hold enable state propagates it to view and refresh the text buffer.


Instruction:
Explain what the following Python 3 code does
def _handle_double_click(self, event):
        if event.get_button()[1] == 1:  # Left mouse button
            path_info = self.view.tree_view.get_path_at_pos(int(event.x), int(event.y))
            if path_info:  # Valid entry was clicked on
                path = path_info[0]
                item_iter = self.tree_store.get_iter(path)

                # Toggle collapse status if applicable for this kind of state
                if self.view.tree_view.row_expanded(path):
                    self.view.tree_view.collapse_row(path)
                else:
                    if self.tree_store.iter_has_child(item_iter):
                        self.view.tree_view.expand_to_path(path)

Response: Handle double click event.


Instruction:
How would you implement a function in Python 3 that
creates a absolute path in the file system.

Response:
def create_path(path):
    """Creates a absolute path in the file system.

    :param path: The path to be created
    """
    import os
    if not os.path.exists(path):
        os.makedirs(path)


Instruction:
Can you generate the documentation for the following Python 3 function
def get_md5_file_hash(filename):
    import hashlib
    BLOCKSIZE = 65536
    hasher = hashlib.md5()
    with open(filename, 'rb') as afile:
        buf = afile.read(BLOCKSIZE)
        while len(buf) > 0:
            hasher.update(buf)
            buf = afile.read(BLOCKSIZE)
    return hasher.hexdigest()

Response: Calculates the MD5 hash of a file


Instruction:
Create a Python 3 function for
checking if target_file is not existing or differing from source_file

Response:
def file_needs_update(target_file, source_file):
    """Checks if target_file is not existing or differing from source_file

    :param target_file: File target for a copy action
    :param source_file: File to be copied
    :return: True, if target_file not existing or differing from source_file, else False
    :rtype: False
    """
    if not os.path.isfile(target_file) or get_md5_file_hash(target_file) != get_md5_file_hash(source_file):
        return True
    return False


Instruction:
Explain what the following Python 3 code does
def copy_file_if_update_required(source_file, target_file):
    if file_needs_update(target_file, source_file):
        shutil.copy(source_file, target_file)

Response: Copies source_file to target_file if latter one in not existing or outdated


Instruction:
Implement a Python 3 function for
opening file by path and optional filename and return content of the file.

Response:
def read_file(file_path, filename=None):
    """ Open file by path and optional filename

    If no file name is given the path is interpreted as direct path to the file to be read.
    If there is no file at location the return value will be None to offer a option for case handling.

    :param str file_path: Path string.
    :param str filename: File name of the file to be read.
    :return: None or str
    """
    file_path = os.path.realpath(file_path)
    if filename:
        file_path = os.path.join(file_path, filename)

    file_content = None
    if os.path.isfile(file_path):
        with open(file_path, 'r') as file_pointer:
            file_content = file_pointer.read()

    return file_content


Instruction:
Create a Python 3 function to
clean list of paths from elements that do not exist

Response:
def clean_file_system_paths_from_not_existing_paths(file_system_paths):
    """Cleans list of paths from elements that do not exist

    If a path is no more valid/existing, it is removed from the list.

    :param list[str] file_system_paths: list of file system paths to be checked for existing
    """
    paths_to_delete = []
    for path in file_system_paths:
        if not os.path.exists(path):
            paths_to_delete.append(path)
    for path in paths_to_delete:
        file_system_paths.remove(path)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _load_input_data_port_models(self):
        self.input_data_ports = []
        for input_data_port in self.state.input_data_ports.values():
            self._add_model(self.input_data_ports, input_data_port, DataPortModel)

Response: Reloads the input data port models from the state


Instruction:
Here you have a function in Python 3, explain what it does
def _load_output_data_port_models(self):
        self.output_data_ports = []
        for output_data_port in self.state.output_data_ports.values():
            self._add_model(self.output_data_ports, output_data_port, DataPortModel)

Response: Reloads the output data port models from the state


Instruction:
Can you create a Python 3 function that
loads the income model from the core income

Response:
def _load_income_model(self):
        """ Create income model from core income """
        self._add_model(self.income, self.state.income, IncomeModel)


Instruction:
Given the following Python 3 function, write the documentation
def _load_outcome_models(self):
        self.outcomes = []
        for outcome in self.state.outcomes.values():
            self._add_model(self.outcomes, outcome, OutcomeModel)

Response: Load outcome models from core outcomes


Instruction:
Implement a Python 3 function for
recreating model list The method re-initiate a handed list or dictionary of models with the new dictionary of core-objects. :param model_list_or_dict: could be a list or dictionary of one model type :param core_objects_dict: new dictionary of one type of core-elements (rafcon.core) :param model_name: prop_name for the core-element hold by the model, this core-element is covered by the model :param model_class: model-class of the elements that should be insert :param model_key: if model_list_or_dict is a dictionary the key is the id of the respective element (e.g. 'state_id') :return:

Response:
def re_initiate_model_list(self, model_list_or_dict, core_objects_dict, model_name, model_class, model_key):
        """Recreate model list

        The method re-initiate a handed list or dictionary of models with the new dictionary of core-objects.

        :param model_list_or_dict: could be a list or dictionary of one model type
        :param core_objects_dict: new dictionary of one type of core-elements (rafcon.core)
        :param model_name: prop_name for the core-element hold by the model, this core-element is covered by the model
        :param model_class: model-class of the elements that should be insert
        :param model_key: if model_list_or_dict is a dictionary the key is the id of the respective element
                          (e.g. 'state_id')
        :return:
        """
        if model_name == "income":
            if self.income.income != self.state.income:
                self._add_model(self.income, self.state.income, IncomeModel)
            return

        for _ in range(len(model_list_or_dict)):
            self.remove_additional_model(model_list_or_dict, core_objects_dict, model_name, model_key)

        if core_objects_dict:
            for _ in core_objects_dict:
                self.add_missing_model(model_list_or_dict, core_objects_dict, model_name, model_class, model_key)


Instruction:
Make a summary of the following Python 3 code
def _add_model(self, model_list_or_dict, core_element, model_class, model_key=None, load_meta_data=True):

        found_model = self._get_future_expected_model(core_element)
        if found_model:
            found_model.parent = self

        if model_class is IncomeModel:
            self.income = found_model if found_model else IncomeModel(core_element, self)
            return

        if model_key is None:
            model_list_or_dict.append(found_model if found_model else model_class(core_element, self))
        else:
            model_list_or_dict[model_key] = found_model if found_model else model_class(core_element, self,
                                                                                load_meta_data=load_meta_data)

Response: Adds one model for a given core element.


Instruction:
Explain what the following Python 3 code does
def add_missing_model(self, model_list_or_dict, core_elements_dict, model_name, model_class, model_key):
        def core_element_has_model(core_object):
            for model_or_key in model_list_or_dict:
                model = model_or_key if model_key is None else model_list_or_dict[model_or_key]
                if core_object is getattr(model, model_name):
                    return True
            return False

        if model_name == "income":
            self._add_model(self.income, self.state.income, IncomeModel)
            return

        for core_element in core_elements_dict.values():
            if core_element_has_model(core_element):
                continue

            # get expected model and connect it to self or create a new model
            new_model = self._get_future_expected_model(core_element)
            if new_model:
                new_model.parent = self
            else:
                if type_helpers.type_inherits_of_type(model_class, StateModel):
                    new_model = model_class(core_element, self, expected_future_models=self.expected_future_models)
                    self.expected_future_models = new_model.expected_future_models  # update reused models
                    new_model.expected_future_models = set()  # clean the field because should not be used further
                else:
                    new_model = model_class(core_element, self)

            # insert new model into list or dict
            if model_key is None:
                model_list_or_dict.append(new_model)
            else:
                model_list_or_dict[getattr(core_element, model_key)] = new_model
            return True
        return False

Response: This method will add one missing model to the state object if it does not exist.


Instruction:
Can you create a Python 3 function that
removes one unnecessary model The method will search for the first model-object out of model_list_or_dict that represents no core-object in the dictionary of core-objects handed by core_objects_dict, remove it and return without continue to search for more model-objects which maybe are unnecessary, too. :param model_list_or_dict: could be a list or dictionary of one model type :param core_objects_dict: dictionary of one type of core-elements (rafcon.core) :param model_name: prop_name for the core-element hold by the model, this core-element is covered by the model :param model_key: if model_list_or_dict is a dictionary the key is the id of the respective element (e.g. 'state_id') :return:

Response:
def remove_additional_model(self, model_list_or_dict, core_objects_dict, model_name, model_key, destroy=True):
        """Remove one unnecessary model

        The method will search for the first model-object out of
        model_list_or_dict that represents no core-object in the dictionary of core-objects handed by core_objects_dict,
        remove it and return without continue to search for more model-objects which maybe are unnecessary, too.

        :param model_list_or_dict: could be a list or dictionary of one model type
        :param core_objects_dict: dictionary of one type of core-elements (rafcon.core)
        :param model_name: prop_name for the core-element hold by the model, this core-element is covered by the model
        :param model_key: if model_list_or_dict is a dictionary the key is the id of the respective element
                          (e.g. 'state_id')
        :return:
        """
        if model_name == "income":
            self.income.prepare_destruction()
            self.income = None
            return

        for model_or_key in model_list_or_dict:
            model = model_or_key if model_key is None else model_list_or_dict[model_or_key]
            found = False
            for core_object in core_objects_dict.values():
                if core_object is getattr(model, model_name):
                    found = True
                    break
            if not found:
                if model_key is None:
                    if destroy:
                        model.prepare_destruction()
                    model_list_or_dict.remove(model)
                else:
                    if destroy:
                        model_list_or_dict[model_or_key].prepare_destruction()
                    del model_list_or_dict[model_or_key]
                return


Instruction:
Implement a Python 3 function for
handing model for an core element from expected model list and remove the model from this list

Response:
def _get_future_expected_model(self, core_element):
        """Hand model for an core element from expected model list and remove the model from this list"""
        for model in self.expected_future_models:
            if model.core_element is core_element:
                # print("expected_future_model found -> remove model:", model, [model], id(model))
                self.expected_future_models.remove(model)
                return model
        return None


Instruction:
How would you code a function in Python 3 to
create a copy of the config in form of a dict

Response:
def as_dict(self, use_preliminary=False):
        """Create a copy of the config in form of a dict

        :param bool use_preliminary: Whether to include the preliminary config
        :return: A dict with the copy of the config
        :rtype: dict
        """
        config = dict()
        for key in self.config.keys:
            if use_preliminary and key in self.preliminary_config:
                value = self.preliminary_config[key]
            else:
                value = self.config.get_config_value(key)
            config[key] = value
        return config


Instruction:
Write a Python 3 script to
update the content and reference of the config object with the new configuration dictionary.

Response:
def update_config(self, config_dict, config_file):
        """Update the content and reference of the config

        :param dict config_dict: The new configuration
        :param str config_file: The new file reference
        """
        config_path = path.dirname(config_file)
        self.config.config_file_path = config_file
        self.config.path = config_path
        for config_key, config_value in config_dict.items():
            if config_value != self.config.get_config_value(config_key):
                self.set_preliminary_config_value(config_key, config_value)


Instruction:
Write a Python 3 script for
returning the current config value for the given config key

Response:
def get_current_config_value(self, config_key, use_preliminary=True, default=None):
        """Returns the current config value for the given config key

        :param str config_key: Config key who's value is requested
        :param bool use_preliminary: Whether the preliminary config should be queried first
        :param default: The value to return if config key does not exist
        :return: Copy of the config value
        """
        if use_preliminary and config_key in self.preliminary_config:
            return copy(self.preliminary_config[config_key])
        return copy(self.config.get_config_value(config_key, default))


Instruction:
Can you generate the documentation for the following Python 3 function
def set_preliminary_config_value(self, config_key, config_value):
        if config_value != self.config.get_config_value(config_key):
            self.preliminary_config[config_key] = config_value
        # If the value was reverted to its original value, we can remove the entry
        elif config_key in self.preliminary_config:
            del self.preliminary_config[config_key]

Response: Stores a config value as preliminary new value


Instruction:
Create a Python 3 function to
apply the preliminary config to the configuration and returns True if the applied changes require a refresh of the state machines.

Response:
def apply_preliminary_config(self, save=True):
        """Applies the preliminary config to the configuration

        :param bool save: Whether the config file is be be written to the file system
        :return: Whether the applied changes require a refresh of the state machines
        :rtype: bool
        """
        state_machine_refresh_required = False
        for config_key, config_value in self.preliminary_config.items():
            self.config.set_config_value(config_key, config_value)
            if config_key in self.config.keys_requiring_state_machine_refresh:
                state_machine_refresh_required = True
            elif config_key in self.config.keys_requiring_restart:
                self.changed_keys_requiring_restart.add(config_key)
            if config_key == 'AUTO_RECOVERY_LOCK_ENABLED':
                import rafcon.gui.models.auto_backup
                if config_value:
                    rafcon.gui.models.auto_backup.generate_rafcon_instance_lock_file()
                else:
                    rafcon.gui.models.auto_backup.remove_rafcon_instance_lock_file()
        self.preliminary_config.clear()

        if save:
            self.config.save_configuration()
        return state_machine_refresh_required


Instruction:
Can you generate a brief explanation for the following Python 3 code
def parent(self, parent):
        if parent is None:
            self._parent = None
        else:
            from rafcon.core.states.state import State
            assert isinstance(parent, State)

            old_parent = self.parent
            self._parent = ref(parent)

            valid, message = self._check_validity()
            if not valid:
                if not old_parent:
                    self._parent = None
                else:
                    self._parent = ref(old_parent)

                class_name = self.__class__.__name__
                if global_config.get_config_value("LIBRARY_RECOVERY_MODE") is True:
                    do_delete_item = True
                    # In case of just the data type is wrong raise an Exception but keep the data flow
                    if "not have matching data types" in message:
                        do_delete_item = False
                        self._parent = ref(parent)
                    raise RecoveryModeException("{0} invalid within state \"{1}\" (id {2}): {3}".format(
                        class_name, parent.name, parent.state_id, message), do_delete_item=do_delete_item)
                else:
                    raise ValueError("{0} invalid within state \"{1}\" (id {2}): {3} {4}".format(
                        class_name, parent.name, parent.state_id, message, self))

Response: Setter for the parent state of the state element


Instruction:
Make a summary of the following Python 3 code
def _check_validity(self):
        from rafcon.core.states.state import State

        if not self.parent:
            return True, "no parent"
        if not isinstance(self.parent, State):
            return True, "no parental check"
        return self.parent.check_child_validity(self)

Response: Checks the validity of the state element s properties


Instruction:
Here you have a function in Python 3, explain what it does
def register_new_state_machines(self, model, prop_name, info):
        if info['method_name'] == '__setitem__':
            self.observe_model(info['args'][1])
            self.logger.info(NotificationOverview(info))
        elif info['method_name'] == '__delitem__':
            pass
        else:
            self.logger.warning(NotificationOverview(info))

Response: The method register self as observer newly added StateMachineModels after those were added to the list of state_machines hold by observable StateMachineMangerModel. state_machines.


Instruction:
Can you generate the documentation for the following Python 3 function
def observe_root_state_assignments(self, model, prop_name, info):
        if info['old']:
            self.relieve_model(info['old'])
        if info['new']:
            self.observe_model(info['new'])
            self.logger.info("Exchange observed old root_state model with newly assigned one. sm_id: {}"
                             "".format(info['new'].state.parent.state_machine_id))

Response: The method relies observed root_state models and observes newly assigned root_state models.


Instruction:
Make a summary of the following Python 3 code
def observe_meta_signal_changes(self, changed_model, prop_name, info):
        self.logger.info(NotificationOverview(info))

Response: This method prints the structure of all meta_signal - notifications as log - messages.


Instruction:
Implement a Python 3 function for
setting the dictionary of the Vividict COOKIE

Response:
def set_dict(self, new_dict):
        """Sets the dictionary of the Vividict

        The method is able to handle nested dictionaries, by calling the method recursively.

        :param new_dict: The dict that will be added to the own dict
        """
        for key, value in new_dict.items():
            if isinstance(value, dict):
                self[str(key)] = Vividict(value)
            else:
                self[str(key)] = value


Instruction:
Given the following Python 3 function, write the documentation
def register_view(self, view):
        super(SemanticDataEditorController, self).register_view(view)

        if isinstance(self.model.state, LibraryState) or self.model.state.get_next_upper_library_root_state():
            self.set_editor_lock(True)

        view['open_externally'].connect('clicked', self.open_externally_clicked)
        view['new_entry'].connect('clicked', self.on_add, False)
        view['new_dict_entry'].connect('clicked', self.on_add, True)
        view['delete_entry'].connect('clicked', self.on_remove)
        self._apply_value_on_edited_and_focus_out(self.widget_columns[view.KEY_COLUMN_ID].get_cells()[0],
                                                  self.key_edited)
        self._apply_value_on_edited_and_focus_out(self.widget_columns[view.VALUE_COLUMN_ID].get_cells()[0],
                                                  self.value_edited)
        self.reload_tree_store_data()

Response: Called when the view was registered


Instruction:
Can you tell what is the following Python 3 function doing
def set_editor_lock(self, locked=True):
        self.view['new_entry'].set_sensitive(not locked)
        self.view['new_dict_entry'].set_sensitive(not locked)
        self.view['delete_entry'].set_sensitive(not locked)
        # self.view['open_externally'].set_sensitive(not locked)

        for current_column in self.view['semantic_data_tree_view'].get_columns():
            current_column.get_cells()[0].set_property('editable', not locked)

Response: Sets the locked flag for the external editor.


Instruction:
Can you tell what is the following Python 3 function doing
def get_selected_object(self):
        model, paths = self.tree_view.get_selection().get_selected_rows()
        if len(paths) == 1:
            return self.tree_store.get_iter(paths[0]), paths[0]
        else:
            return None, paths

Response: Gets the selected object in the treeview


Instruction:
Write a Python 3 function for
adding a new entry to the semantic data of a state.

Response:
def on_add(self, widget, new_dict=False):
        """" Adds a new entry to the semantic data of a state. Reloads the tree store.

        :param widget: The source widget of the action
        :param bool new_dict: A flag to indicate if the new value is of type dict
        :return:
        """
        self.semantic_data_counter += 1
        treeiter, path = self.get_selected_object()

        value = dict() if new_dict else "New Value"

        # get target dict path
        if treeiter:
            target_dict_path_as_list = self.tree_store[path][self.ID_STORAGE_ID]
            if not self.tree_store[path][self.IS_DICT_STORAGE_ID]:
                target_dict_path_as_list.pop()
        else:
            target_dict_path_as_list = []

        # generate key
        target_dict = self.model.state.get_semantic_data(target_dict_path_as_list)
        new_key_string = generate_semantic_data_key(list(target_dict.keys()))
        self.model.state.add_semantic_data(target_dict_path_as_list, value, new_key_string)

        self.reload_tree_store_data()

        # jump to new element
        self.select_entry(target_dict_path_as_list + [new_key_string])
        logger.debug("Added new semantic data entry!")
        return True


Instruction:
Can you tell what is the following Python 3 function doing
def on_remove(self, widget, data=None):
        treeiter, path = self.get_selected_object()
        if not treeiter:
            return

        # check if an element is selected
        dict_path_as_list = self.tree_store[path][self.ID_STORAGE_ID]
        logger.debug("Deleting semantic data entry with name {}!".format(dict_path_as_list[-1]))
        self.model.state.remove_semantic_data(dict_path_as_list)
        self.reload_tree_store_data()

        # hold cursor position where the last element was removed
        try:
            self.select_entry(self.tree_store[path][self.ID_STORAGE_ID])
        except IndexError:
            if len(self.tree_store):
                if len(path) > 1:
                    possible_before_path = tuple(list(path[:-1]) + [path[-1] - 1])
                    if possible_before_path[-1] > -1:
                        self.select_entry(self.tree_store[possible_before_path][self.ID_STORAGE_ID])
                    else:
                        self.select_entry(self.tree_store[path[:-1]][self.ID_STORAGE_ID])
                else:
                    self.select_entry(self.tree_store[path[0] - 1][self.ID_STORAGE_ID])
        return True

Response: Removes an entry of semantic data of a state.


Instruction:
Make a summary of the following Python 3 code
def add_items_to_tree_iter(self, input_dict, treeiter, parent_dict_path=None):
        if parent_dict_path is None:
            parent_dict_path = []
        self.get_view_selection()
        for key, value in sorted(input_dict.items()):
            element_dict_path = copy.copy(parent_dict_path) + [key]
            if isinstance(value, dict):
                new_iter = self.tree_store.append(treeiter, [key, "", True, element_dict_path])
                self.add_items_to_tree_iter(value, new_iter, element_dict_path)
            else:
                self.tree_store.append(treeiter, [key, value, False, element_dict_path])

Response: Adds all values of the input dictionary to the tree store.


Instruction:
Write a Python 3 function that can
reload the data of the tree store.

Response:
def reload_tree_store_data(self):
        """ Reloads the data of the tree store

        :return:
        """
        model, paths = self.tree_view.get_selection().get_selected_rows()

        self.tree_store.clear()
        self.add_items_to_tree_iter(self.model.state.semantic_data, None)
        self.tree_view.expand_all()

        try:
            for path in paths:
                self.tree_view.get_selection().select_path(path)
        except ValueError:
            pass


Instruction:
Can you create a Python 3 function that
adds a copy of all selected row dict value pairs to the clipboard

Response:
def copy_action_callback(self, *event):
        """Add a copy of all selected row dict value pairs to the clipboard"""
        if react_to_event(self.view, self.tree_view, event) and self.active_entry_widget is None:
            _, dict_paths = self.get_view_selection()
            selected_data_list = []
            for dict_path_as_list in dict_paths:
                value = self.model.state.semantic_data
                for path_element in dict_path_as_list:
                    value = value[path_element]
                selected_data_list.append((path_element, value))
            rafcon.gui.clipboard.global_clipboard.set_semantic_dictionary_list(selected_data_list)


Instruction:
Make a summary of the following Python 3 code
def paste_action_callback(self, *event):
        if react_to_event(self.view, self.tree_view, event) and self.active_entry_widget is None:
            _, dict_paths = self.get_view_selection()
            selected_data_list = rafcon.gui.clipboard.global_clipboard.get_semantic_dictionary_list()

            # enforce paste on root level if semantic data empty or nothing is selected
            if not dict_paths and not self.model.state.semantic_data:
                dict_paths = [[]]

            for target_dict_path_as_list in dict_paths:
                prev_value = self.model.state.semantic_data
                value = self.model.state.semantic_data
                for path_element in target_dict_path_as_list:
                    prev_value = value
                    value = value[path_element]
                if not isinstance(value, dict) and len(dict_paths) <= 1:  # if one selection take parent
                    target_dict_path_as_list.pop(-1)
                    value = prev_value
                if isinstance(value, dict):
                    for key_to_paste, value_to_add in selected_data_list:
                        self.model.state.add_semantic_data(target_dict_path_as_list, value_to_add, key_to_paste)
            self.reload_tree_store_data()

Response: Paste the clipboard into all selected sub - dictionary


Instruction:
Can you generate a brief explanation for the following Python 3 code
def cut_action_callback(self, *event):
        if react_to_event(self.view, self.tree_view, event) and self.active_entry_widget is None:
            _, dict_paths = self.get_view_selection()
            stored_data_list = []
            for dict_path_as_list in dict_paths:
                if dict_path_as_list:
                    value = self.model.state.semantic_data
                    for path_element in dict_path_as_list:
                        value = value[path_element]
                    stored_data_list.append((path_element, value))
                    self.model.state.remove_semantic_data(dict_path_as_list)

            rafcon.gui.clipboard.global_clipboard.set_semantic_dictionary_list(stored_data_list)
            self.reload_tree_store_data()

Response: Add a copy and cut all selected row dict value pairs to the clipboard


Instruction:
How would you explain what the following Python 3 function does
def key_edited(self, path, new_key_str):
        tree_store_path = self.create_tree_store_path_from_key_string(path) if isinstance(path, string_types) else path
        if self.tree_store[tree_store_path][self.KEY_STORAGE_ID] == new_key_str:
            return

        dict_path = self.tree_store[tree_store_path][self.ID_STORAGE_ID]
        old_value = self.model.state.get_semantic_data(dict_path)
        self.model.state.remove_semantic_data(dict_path)

        if new_key_str == "":
            target_dict = self.model.state.semantic_data
            for element in dict_path[0:-1]:
                target_dict = target_dict[element]
            new_key_str = generate_semantic_data_key(list(target_dict.keys()))

        new_dict_path = self.model.state.add_semantic_data(dict_path[0:-1], old_value, key=new_key_str)
        self._changed_id_to = {':'.join(dict_path): new_dict_path}  # use hashable key (workaround for tree view ctrl)
        self.reload_tree_store_data()

Response: Edits the key of a semantic data entry


Instruction:
Explain what the following Python 3 code does
def value_edited(self, path, new_value_str):
        tree_store_path = self.create_tree_store_path_from_key_string(path) if isinstance(path, string_types) else path
        if self.tree_store[tree_store_path][self.VALUE_STORAGE_ID] == new_value_str:
            return

        dict_path = self.tree_store[tree_store_path][self.ID_STORAGE_ID]
        self.model.state.add_semantic_data(dict_path[0:-1], new_value_str, key=dict_path[-1])
        self.reload_tree_store_data()

Response: Adds the value of the semantic data entry to the model state


Instruction:
Explain what the following Python 3 code does
def get_path_for_core_element(self, core_element_id):
        def check_function(row_iter, iter_found):
            row_id = self.tree_store.get_value(row_iter, self.ID_STORAGE_ID)
            if len(row_id) == len(core_element_id):
                if row_id == core_element_id:
                    iter_found.append(self.tree_store.get_path(row_iter))

        found_paths = []
        self.iter_tree_with_handed_function(check_function, found_paths)
        return found_paths[0] if found_paths else None

Response: Get the path to the row representing the core element described by handed core_element_id


Instruction:
Explain what the following Python 3 code does
def save_file_data(self, path):
        try:
            # just create file with empty text first; this command also creates the whole path to the file
            filesystem.write_file(os.path.join(path, storage.SCRIPT_FILE), "", create_full_path=True)
            storage_utils.write_dict_to_json(self.model.state.semantic_data, os.path.join(path, storage.SEMANTIC_DATA_FILE))
        except IOError as e:
            # Only happens if the file doesnt exist yet and would be written to the temp folder.
            # The method write_file doesn't create the path
            logger.error('The operating system raised an error: {}'.format(e))

Response: Saves the semantic data to a file in the specified path.


Instruction:
Can you tell what is the following Python 3 function doing
def load_and_set_file_content(self, file_system_path):
        semantic_data = load_data_file(os.path.join(file_system_path, storage.SEMANTIC_DATA_FILE))
        self.model.state.semantic_data = semantic_data

Response: Loads the semantic data file and sets the content of the semantic data object in the state.


Instruction:
Implement a Python 3 function for
storing the properties of a widget in the configuration file.

Response:
def store_widget_properties(self, widget, widget_name):
        """Sets configuration values for widgets

        If the widget is a window, then the size and position are stored. If the widget is a pane, then only the
        position is stored. If the window is maximized the last insert position before being maximized is keep in the
        config and the maximized flag set to True. The maximized state and the last size and position are strictly
        separated by this.

        :param widget: The widget, for which the position (and possibly the size) will be stored.
        :param widget_name: The window or widget name of the widget, which constitutes a part of its key in the
        configuration file.
        """
        if isinstance(widget, Gtk.Window):
            maximized = bool(widget.is_maximized())
            self.set_config_value('{0}_MAXIMIZED'.format(widget_name), maximized)
            if maximized:
                return
            size = widget.get_size()
            self.set_config_value('{0}_SIZE'.format(widget_name), tuple(size))
            position = widget.get_position()
            self.set_config_value('{0}_POS'.format(widget_name), tuple(position))
        else:  # Gtk.Paned
            position = widget.get_position()
            self.set_config_value('{0}_POS'.format(widget_name), position)


Instruction:
Can you generate the documentation for the following Python 3 function
def update_recently_opened_state_machines_with(self, state_machine):
        if state_machine.file_system_path:
            # check if path is in recent path already
            # logger.info("update recent state machine: {}".format(sm.file_system_path))
            recently_opened_state_machines = self.get_config_value('recently_opened_state_machines', [])
            if state_machine.file_system_path in recently_opened_state_machines:
                del recently_opened_state_machines[recently_opened_state_machines.index(state_machine.file_system_path)]
            recently_opened_state_machines.insert(0, state_machine.file_system_path)
            self.set_config_value('recently_opened_state_machines', recently_opened_state_machines)

Response: Updates the list of recently opened state machines with the file system path of handed state machine.


Instruction:
Make a summary of the following Python 3 code
def extend_recently_opened_by_current_open_state_machines(self):
        from rafcon.gui.singleton import state_machine_manager_model as state_machine_manager_m
        for sm_m in state_machine_manager_m.state_machines.values():
            self.update_recently_opened_state_machines_with(sm_m.state_machine)

Response: Updates the list with all in the state machine manager opened state machines


Instruction:
Here you have a function in Python 3, explain what it does
def prepare_recently_opened_state_machines_list_for_storage(self):
        from rafcon.gui.singleton import global_gui_config
        num = global_gui_config.get_config_value('NUMBER_OF_RECENT_OPENED_STATE_MACHINES_STORED')
        state_machine_paths = self.get_config_value('recently_opened_state_machines', [])
        self.set_config_value('recently_opened_state_machines', state_machine_paths[:num])

Response: Reduce number of paths in the recent opened state machines to limit from gui config


Instruction:
How would you code a function in Python 3 to
remove state machines who s file system path does not exist

Response:
def clean_recently_opened_state_machines(self):
        """Remove state machines who's file system path does not exist"""
        state_machine_paths = self.get_config_value('recently_opened_state_machines', [])
        filesystem.clean_file_system_paths_from_not_existing_paths(state_machine_paths)
        self.set_config_value('recently_opened_state_machines', state_machine_paths)


Instruction:
Create a Python 3 function to
set the execution mode to paused

Response:
def pause(self):
        """Set the execution mode to paused
        """
        if self.state_machine_manager.active_state_machine_id is None:
            logger.info("'Pause' is not a valid action to initiate state machine execution.")
            return
        if self.state_machine_manager.get_active_state_machine() is not None:
            self.state_machine_manager.get_active_state_machine().root_state.recursively_pause_states()

        logger.debug("Pause execution ...")
        self.set_execution_mode(StateMachineExecutionStatus.PAUSED)


Instruction:
Make a summary of the following Python 3 code
def finished_or_stopped(self):
        return (self._status.execution_mode is StateMachineExecutionStatus.STOPPED) or \
               (self._status.execution_mode is StateMachineExecutionStatus.FINISHED)

Response: Returns a boolean indicating whether the condition check is finished or stopped.


Instruction:
Write a Python 3 function that can
start a specific state machine.

Response:
def start(self, state_machine_id=None, start_state_path=None):
        """ Start state machine

        If no state machine is running start a specific state machine.
        If no state machine is provided the currently active state machine is started.
        If there is already a state machine running, just resume it without taking the passed state_machine_id argument
        into account.

        :param state_machine_id: The id if the state machine to be started
        :param start_state_path: The path of the state in the state machine, from which the execution will start
        :return:
        """

        if not self.finished_or_stopped():
            logger.debug("Resume execution engine ...")
            self.run_to_states = []
            if self.state_machine_manager.get_active_state_machine() is not None:
                self.state_machine_manager.get_active_state_machine().root_state.recursively_resume_states()
                if isinstance(state_machine_id, int) and \
                        state_machine_id != self.state_machine_manager.get_active_state_machine().state_machine_id:
                    logger.info("Resumed state machine with id {0} but start of state machine id {1} was requested."
                                "".format(self.state_machine_manager.get_active_state_machine().state_machine_id,
                                          state_machine_id))
            self.set_execution_mode(StateMachineExecutionStatus.STARTED)
        else:
            # do not start another state machine before the old one did not finish its execution
            if self.state_machine_running:
                logger.warning("An old state machine is still running! Make sure that it terminates,"
                               " before you can start another state machine! {0}".format(self))
                return

            logger.debug("Start execution engine ...")
            if state_machine_id is not None:
                self.state_machine_manager.active_state_machine_id = state_machine_id

            if not self.state_machine_manager.active_state_machine_id:
                logger.error("There exists no active state machine!")
                return

            self.set_execution_mode(StateMachineExecutionStatus.STARTED)

            self.start_state_paths = []

            if start_state_path:
                path_list = start_state_path.split("/")
                cur_path = ""
                for path in path_list:
                    if cur_path == "":
                        cur_path = path
                    else:
                        cur_path = cur_path + "/" + path
                    self.start_state_paths.append(cur_path)

            self._run_active_state_machine()


Instruction:
Make a summary of the following Python 3 code
def stop(self):
        logger.debug("Stop the state machine execution ...")
        if self.state_machine_manager.get_active_state_machine() is not None:
            self.state_machine_manager.get_active_state_machine().root_state.recursively_preempt_states()
        self.__set_execution_mode_to_stopped()

        # Notifies states waiting in step mode or those that are paused about execution stop
        self._status.execution_condition_variable.acquire()
        self._status.execution_condition_variable.notify_all()
        self._status.execution_condition_variable.release()
        self.__running_state_machine = None

Response: Stops the execution of the current state machine.


Instruction:
Can you tell what is the following Python 3 function doing
def join(self, timeout=None):
        if self.__wait_for_finishing_thread:
            if not timeout:
                # signal handlers won't work if timeout is None and the thread is joined
                while True:
                    self.__wait_for_finishing_thread.join(0.5)
                    if not self.__wait_for_finishing_thread.isAlive():
                        break
            else:
                self.__wait_for_finishing_thread.join(timeout)
            return not self.__wait_for_finishing_thread.is_alive()
        else:
            logger.warning("Cannot join as state machine was not started yet.")
            return False

Response: Blocking wait for the execution to finish


Instruction:
Can you create a Python 3 function that
runs the active state machine and observe its status

Response:
def _run_active_state_machine(self):
        """Store running state machine and observe its status
        """

        # Create new concurrency queue for root state to be able to synchronize with the execution
        self.__running_state_machine = self.state_machine_manager.get_active_state_machine()
        if not self.__running_state_machine:
            logger.error("The running state machine must not be None")
        self.__running_state_machine.root_state.concurrency_queue = queue.Queue(maxsize=0)

        if self.__running_state_machine:
            self.__running_state_machine.start()

            self.__wait_for_finishing_thread = threading.Thread(target=self._wait_for_finishing)
            self.__wait_for_finishing_thread.start()
        else:
            logger.warning("Currently no active state machine! Please create a new state machine.")
            self.set_execution_mode(StateMachineExecutionStatus.STOPPED)


Instruction:
Here you have a function in Python 3, explain what it does
def _wait_for_finishing(self):
        self.state_machine_running = True
        self.__running_state_machine.join()
        self.__set_execution_mode_to_finished()
        self.state_machine_manager.active_state_machine_id = None
        plugins.run_on_state_machine_execution_finished()
        # self.__set_execution_mode_to_stopped()
        self.state_machine_running = False

Response: Observe running state machine and stop engine if execution has finished


Instruction:
Write a Python 3 script for
taking a backward step for all active states in the state machine

Response:
def backward_step(self):
        """Take a backward step for all active states in the state machine
        """
        logger.debug("Executing backward step ...")
        self.run_to_states = []
        self.set_execution_mode(StateMachineExecutionStatus.BACKWARD)


Instruction:
Here you have a function in Python 3, explain what it does
def step_mode(self, state_machine_id=None):
        logger.debug("Activate step mode")

        if state_machine_id is not None:
            self.state_machine_manager.active_state_machine_id = state_machine_id

        self.run_to_states = []
        if self.finished_or_stopped():
            self.set_execution_mode(StateMachineExecutionStatus.STEP_MODE)
            self._run_active_state_machine()
        else:
            self.set_execution_mode(StateMachineExecutionStatus.STEP_MODE)

Response: Set the execution mode to stepping mode.


Instruction:
Write a Python 3 function that can
take a forward step into for all active states in the state machine.

Response:
def step_into(self):
        """Take a forward step (into) for all active states in the state machine
        """
        logger.debug("Execution step into ...")
        self.run_to_states = []
        if self.finished_or_stopped():
            self.set_execution_mode(StateMachineExecutionStatus.FORWARD_INTO)
            self._run_active_state_machine()
        else:
            self.set_execution_mode(StateMachineExecutionStatus.FORWARD_INTO)


Instruction:
Given the following Python 3 function, write the documentation
def step_over(self):
        logger.debug("Execution step over ...")
        self.run_to_states = []
        if self.finished_or_stopped():
            self.set_execution_mode(StateMachineExecutionStatus.FORWARD_OVER)
            self._run_active_state_machine()
        else:
            self.set_execution_mode(StateMachineExecutionStatus.FORWARD_OVER)

Response: Take a forward step over for all active states in the state machine.


Instruction:
Implement a function in Python 3 to
take a forward step for all active states in the state machine and run the active state machine.

Response:
def step_out(self):
        """Take a forward step (out) for all active states in the state machine
        """
        logger.debug("Execution step out ...")
        self.run_to_states = []
        if self.finished_or_stopped():
            self.set_execution_mode(StateMachineExecutionStatus.FORWARD_OUT)
            self._run_active_state_machine()
        else:
            self.set_execution_mode(StateMachineExecutionStatus.FORWARD_OUT)


Instruction:
Implement a Python 3 function for
executing the state machine until a specific state.

Response:
def run_to_selected_state(self, path, state_machine_id=None):
        """Execute the state machine until a specific state. This state won't be executed. This is an asynchronous task
        """
        if self.state_machine_manager.get_active_state_machine() is not None:
            self.state_machine_manager.get_active_state_machine().root_state.recursively_resume_states()

        if not self.finished_or_stopped():
            logger.debug("Resume execution engine and run to selected state!")
            self.run_to_states = []
            self.run_to_states.append(path)
            self.set_execution_mode(StateMachineExecutionStatus.RUN_TO_SELECTED_STATE)
        else:
            logger.debug("Start execution engine and run to selected state!")
            if state_machine_id is not None:
                self.state_machine_manager.active_state_machine_id = state_machine_id
            self.set_execution_mode(StateMachineExecutionStatus.RUN_TO_SELECTED_STATE)
            self.run_to_states = []
            self.run_to_states.append(path)
            self._run_active_state_machine()


Instruction:
Implement a Python 3 function for
waiting as long as the execution_mode is in paused or step_mode.

Response:
def _wait_while_in_pause_or_in_step_mode(self):
        """ Waits as long as the execution_mode is in paused or step_mode
        """
        while (self._status.execution_mode is StateMachineExecutionStatus.PAUSED) \
                or (self._status.execution_mode is StateMachineExecutionStatus.STEP_MODE):
            try:
                self._status.execution_condition_variable.acquire()
                self.synchronization_counter += 1
                logger.verbose("Increase synchronization_counter: " + str(self.synchronization_counter))
                self._status.execution_condition_variable.wait()
            finally:
                self._status.execution_condition_variable.release()


Instruction:
Write a Python 3 function that can
check if the calling thread is blocking and waits for the execution of the current state.

Response:
def _wait_if_required(self, container_state, next_child_state_to_execute, woke_up_from_pause_or_step_mode):
        """ Calls a blocking wait for the calling thread, depending on the execution mode.

        :param container_state: the current hierarhcy state to handle the execution mode for
        :param next_child_state_to_execute: the next child state for :param container_state to be executed
        :param woke_up_from_pause_or_step_mode: a flag to check if the execution just woke up from paused- or step-mode
        """
        wait = True
        # if there is a state in self.run_to_states then RAFCON was commanded
        #    a) a step_over
        #    b) a step_out
        #    c) a run_until
        for state_path in copy.deepcopy(self.run_to_states):
            next_child_state_path = None
            # can be None in case of no transition given
            if next_child_state_to_execute:
                next_child_state_path = next_child_state_to_execute.get_path()
            if state_path == container_state.get_path():
                # the execution did a whole step_over inside hierarchy state "state" (case a) )
                # or a whole step_out into the hierarchy state "state" (case b) )
                # thus we delete its state path from self.run_to_states
                # and wait for another step (of maybe different kind)
                wait = True
                self.run_to_states.remove(state_path)
                break
            elif state_path == next_child_state_path:
                # this is the case that execution has reached a specific state explicitly marked via
                # run_to_selected_state() (case c) )
                # if this is the case run_to_selected_state() is finished and the execution
                # has to wait for new execution commands
                wait = True
                self.run_to_states.remove(state_path)
                break
            # don't wait if its just a normal step
            else:
                wait = False
                # do not break here, the state_path may be of another state machine branch
                # break
        # don't wait if the the execution just woke up from step mode or pause
        if wait and not woke_up_from_pause_or_step_mode:
            logger.debug("Stepping mode: waiting for next step!")
            try:
                self._status.execution_condition_variable.acquire()
                self.synchronization_counter += 1
                logger.verbose("Increase synchronization_counter: " + str(self.synchronization_counter))
                self._status.execution_condition_variable.wait()
            finally:
                self._status.execution_condition_variable.release()
            # if the status was set to PAUSED or STEP_MODE don't wake up!
            self._wait_while_in_pause_or_in_step_mode()
            # container_state was notified => thus, a new user command was issued, which has to be handled!
            container_state.execution_history.new_execution_command_handled = False


Instruction:
Can you generate the documentation for the following Python 3 function
def handle_execution_mode(self, container_state, next_child_state_to_execute=None):
        self.state_counter_lock.acquire()
        self.state_counter += 1
        # logger.verbose("Increase state_counter!" + str(self.state_counter))
        self.state_counter_lock.release()

        woke_up_from_pause_or_step_mode = False

        if (self._status.execution_mode is StateMachineExecutionStatus.PAUSED) \
                or (self._status.execution_mode is StateMachineExecutionStatus.STEP_MODE):
            self._wait_while_in_pause_or_in_step_mode()
            # new command was triggered => execution command has to handled
            container_state.execution_history.new_execution_command_handled = False
            woke_up_from_pause_or_step_mode = True

        # no elif here: if the execution woke up from e.g. paused mode, it has to check the current execution mode
        if self._status.execution_mode is StateMachineExecutionStatus.STARTED:
            # logger.debug("Execution engine started!")
            pass

        elif self._status.execution_mode is StateMachineExecutionStatus.STOPPED:
            logger.debug("Execution engine stopped. State '{0}' is going to quit in the case of "
                         "no preemption handling has to be done!".format(container_state.name))

        elif self._status.execution_mode is StateMachineExecutionStatus.FINISHED:
            # this must never happen during execution of the execution engine
            raise Exception

        else:  # all other step modes
            logger.verbose("before wait")
            self._wait_if_required(container_state, next_child_state_to_execute, woke_up_from_pause_or_step_mode)
            logger.verbose("after wait")

            # calculate states to which should be run
            if self._status.execution_mode is StateMachineExecutionStatus.BACKWARD:
                pass
            elif self._status.execution_mode is StateMachineExecutionStatus.FORWARD_INTO:
                pass
            elif self._status.execution_mode is StateMachineExecutionStatus.FORWARD_OVER:
                if not container_state.execution_history.new_execution_command_handled:
                    # the state that called this method is a hierarchy state => thus we save this state and wait until
                    # thise very state will execute its next state; only then we will wait on the condition variable
                    self.run_to_states.append(container_state.get_path())
                else:
                    pass
            elif self._status.execution_mode is StateMachineExecutionStatus.FORWARD_OUT:
                from rafcon.core.states.state import State
                if isinstance(container_state.parent, State):
                    if not container_state.execution_history.new_execution_command_handled:
                        from rafcon.core.states.library_state import LibraryState
                        if isinstance(container_state.parent, LibraryState):
                            parent_path = container_state.parent.parent.get_path()
                        else:
                            parent_path = container_state.parent.get_path()
                        self.run_to_states.append(parent_path)
                    else:
                        pass
                else:
                    # if step_out is called from the highest level just run the state machine to the end
                    self.run_to_states = []
                    self.set_execution_mode(StateMachineExecutionStatus.STARTED)
            elif self._status.execution_mode is StateMachineExecutionStatus.RUN_TO_SELECTED_STATE:
                # "run_to_states" were already updated thus doing nothing
                pass

        container_state.execution_history.new_execution_command_handled = True

        # in the case that the stop method wakes up the paused or step mode a StateMachineExecutionStatus.STOPPED
        # will be returned
        return_value = self._status.execution_mode

        return return_value

Response: Checks the current execution status and returns it.


Instruction:
Write a Python 3 script to
modify the run_to_states list for the given state.

Response:
def _modify_run_to_states(self, state):
        """
        This is a special case. Inside a hierarchy state a step_over is triggered and affects the last child.
        In this case the self.run_to_states has to be modified in order to contain the parent of the hierarchy state.
        Otherwise the execution won't respect the step_over any more and run until the end of the state machine.
        The same holds for a step_out.
        The reason for this is, that handle_execution_mode() can not be called between
        the last state of a hierarchy state and the termination of the hierarchy state itself.
        """
        if self._status.execution_mode is StateMachineExecutionStatus.FORWARD_OVER or \
                self._status.execution_mode is StateMachineExecutionStatus.FORWARD_OUT:
            for state_path in copy.deepcopy(self.run_to_states):
                if state_path == state.get_path():
                    logger.verbose("Modifying run_to_states; triggered by state %s!", state.name)
                    self.run_to_states.remove(state_path)
                    from rafcon.core.states.state import State
                    if isinstance(state.parent, State):
                        from rafcon.core.states.library_state import LibraryState
                        if isinstance(state.parent, LibraryState):
                            parent_path = state.parent.parent.get_path()
                        else:
                            parent_path = state.parent.get_path()
                        self.run_to_states.append(parent_path)
                    break


Instruction:
Can you generate the documentation for the following Python 3 function
def set_execution_mode(self, execution_mode, notify=True):
        if not isinstance(execution_mode, StateMachineExecutionStatus):
            raise TypeError("status must be of type StateMachineExecutionStatus")
        self._status.execution_mode = execution_mode
        if notify:
            self._status.execution_condition_variable.acquire()
            self._status.execution_condition_variable.notify_all()
            self._status.execution_condition_variable.release()

Response: An observed setter for the execution mode of the state machine status.


Instruction:
Write a Python 3 script for
preempting the state and all of it child states.

Response:
def recursively_preempt_states(self):
        """ Preempt the state and all of it child states.
        """
        super(ContainerState, self).recursively_preempt_states()
        # notify the transition condition variable to let the state instantaneously stop
        self._transitions_cv.acquire()
        self._transitions_cv.notify_all()
        self._transitions_cv.release()
        for state in self.states.values():
            state.recursively_preempt_states()


Instruction:
Can you create a Python 3 function that
pauses the state and all of it child states.

Response:
def recursively_pause_states(self):
        """ Pause the state and all of it child states.
        """
        super(ContainerState, self).recursively_pause_states()
        for state in self.states.values():
            state.recursively_pause_states()


Instruction:
Can you create a Python 3 function that
resumes the state and all of it child states.

Response:
def recursively_resume_states(self):
        """ Resume the state and all of it child states.
        """
        super(ContainerState, self).recursively_resume_states()
        for state in self.states.values():
            state.recursively_resume_states()


Instruction:
Write a Python 3 script for
setting up the scoped data for the current state class.

Response:
def setup_run(self):
        """ Executes a generic set of actions that has to be called in the run methods of each derived state class.

        :return:
        """
        super(ContainerState, self).setup_run()
        # reset the scoped data
        self._scoped_data = {}
        self._start_state_modified = False
        self.add_default_values_of_scoped_variables_to_scoped_data()
        self.add_input_data_to_scoped_data(self.input_data)


Instruction:
Write a Python 3 script for
handling the situation when no start state exists during execution

Response:
def handle_no_start_state(self):
        """Handles the situation, when no start state exists during execution

        The method waits, until a transition is created. It then checks again for an existing start state and waits
        again, if this is not the case. It returns the None state if the the state machine was stopped.
        """
        start_state = self.get_start_state(set_final_outcome=True)
        while not start_state:
            # depending on the execution mode pause execution
            execution_signal = state_machine_execution_engine.handle_execution_mode(self)
            if execution_signal is StateMachineExecutionStatus.STOPPED:
                # this will be caught at the end of the run method
                return None

            self._transitions_cv.acquire()
            self._transitions_cv.wait(3.0)
            self._transitions_cv.release()
            start_state = self.get_start_state(set_final_outcome=True)
        return start_state


Instruction:
Can you write a function in Python 3 where it
groups states and scoped variables into a new hierarchy state.

Response:
def group_states(self, state_ids, scoped_variable_ids=None):
        """ Group states and scoped variables into a new hierarchy state and remain internal connections.
            Interconnecting transitions and data flows to parent and other child states are removed, at the moment.

        :param state_ids: state_id's of all states that are to be grouped.
        :param scoped_variable_ids: data_port_id's of all scoped variables that are to be grouped, too.
        :return:
        """
        # TODO remember changed state or state element ids and provide them for the model functionalities
        assert all([state_id in self.states.keys() for state_id in state_ids])
        if scoped_variable_ids is None:
            scoped_variable_ids = []
        assert all([p_id in self.scoped_variables.keys() for p_id in scoped_variable_ids])
        from rafcon.core.states.barrier_concurrency_state import DeciderState
        if any(isinstance(self.states[child_state_id], DeciderState) for child_state_id in state_ids):
            raise ValueError("State of type DeciderState can not be grouped.")

        def create_name(name_str, used_names):
            number_str = ""
            number_of_str = 0
            while name_str + number_str in used_names:
                number_str = "_{}".format(number_of_str)
                number_of_str += 1
            return name_str + number_str

        [related_transitions, related_data_flows] = self.related_linkage_states_and_scoped_variables(state_ids,
                                                                                scoped_variable_ids)

        def assign_ingoing_outgoing(df, going_data_linkage_for_port, ingoing=True):
            internal = 'internal' if ingoing else 'external'
            external = 'external' if ingoing else 'internal'
            if (df.to_state, df.to_key) in going_data_linkage_for_port['to']:
                going_data_linkage_for_port['to'][(df.to_state, df.to_key)][external].append(df)
            else:
                going_data_linkage_for_port['to'][(df.to_state, df.to_key)] = {external: [df], internal: [df]}
            if (df.from_state, df.from_key) in going_data_linkage_for_port['from']:
                going_data_linkage_for_port['from'][(df.from_state, df.from_key)][internal].append(df)
            else:
                going_data_linkage_for_port['from'][(df.from_state, df.from_key)] = {external: [df], internal: [df]}

        def print_df_from_and_to(going_data_linkage_for_port):
            logger.verbose('data linkage FROM: ')
            for port, port_dfs in going_data_linkage_for_port['from'].items():
                logger.verbose("\tport: {0} {1}".format(port, '' if 'args' not in port_dfs else port_dfs['args']))
                logger.verbose("\t\texternal: \n\t\t\t" + "\n\t\t\t".join([str(df) for df in port_dfs['external']]))
                logger.verbose("\t\tinternal: \n\t\t\t" + "\n\t\t\t".join([str(df) for df in port_dfs['internal']]))
            logger.verbose('data linkage TO: ')
            for port, port_dfs in going_data_linkage_for_port['to'].items():
                logger.verbose("\tport: {0} {1}".format(port, '' if 'args' not in port_dfs else port_dfs['args']))
                logger.verbose("\t\texternal: \n\t\t\t" + "\n\t\t\t".join([str(df) for df in port_dfs['external']]))
                logger.verbose("\t\tinternal: \n\t\t\t" + "\n\t\t\t".join([str(df) for df in port_dfs['internal']]))

        def reduce_dfs(port_data_linkages, df_id):
            for port_key in list(port_data_linkages.keys()):
                port_df = port_data_linkages[port_key]
                port_df['internal'] = [df for df in port_df['internal'] if df.data_flow_id != df_id]
                port_df['external'] = [df for df in port_df['external'] if df.data_flow_id != df_id]
                if not port_df['internal'] and not port_df['external']:
                    del port_data_linkages[port_key]

        def do_prior_in_out_going(going_data_linkage_for_port, prior_port_key, prior_locate_key):
            # logger.info("PRIOR IN OUT {0}, {1}".format(prior_port_key, prior_locate_key))
            minor_port_key = 'from' if prior_port_key == 'to' else 'to'
            minor_locate_key = 'external' if prior_locate_key == 'internal' else 'internal'
            for port_key in list(going_data_linkage_for_port[prior_port_key].keys()):
                port_dfs = going_data_linkage_for_port[prior_port_key][port_key]
                # print(prior_port_key, ": check: ", port_key, " length: ", len(port_dfs[prior_locate_key]))
                if len(port_dfs[prior_locate_key]) > 1:
                    for df in port_dfs[prior_locate_key]:
                        # print("remove: ", df.data_flow_id, prior_locate_key, minor_port_key)
                        reduce_dfs(going_data_linkage_for_port[minor_port_key], df.data_flow_id)
            for port_key in list(going_data_linkage_for_port[minor_port_key].keys()):
                port_dfs = going_data_linkage_for_port[minor_port_key][port_key]
                # print(minor_port_key, ": check: ", port_key, " length: ", len(port_dfs[minor_locate_key]))
                if len(port_dfs[minor_locate_key]) > 1:
                    for df in port_dfs[minor_locate_key]:
                        # print("remove: ", df.data_flow_id, minor_locate_key, prior_port_key)
                        reduce_dfs(going_data_linkage_for_port[prior_port_key], df.data_flow_id)
            for port_key in list(going_data_linkage_for_port[prior_port_key].keys()):
                port_dfs = going_data_linkage_for_port[prior_port_key][port_key]
                # print(prior_port_key, ": check: ", port_key, " length: ", len(port_dfs[prior_locate_key]))
                if len(port_dfs[prior_locate_key]) == 1:
                    for df in port_dfs[prior_locate_key]:
                        # print("remove: ", df.data_flow_id, prior_locate_key, minor_port_key)
                        reduce_dfs(going_data_linkage_for_port[minor_port_key], df.data_flow_id)

        def create_data_port_args(going_data_linkage_for_port):
            names = []
            for goal, data_port_linkage in going_data_linkage_for_port['to'].items():
                state = self.states[goal[0]] if goal[0] != self.state_id else self
                port = state.get_data_port_by_id(goal[1])
                data_port_linkage['args'] = port.state_element_to_dict(port)
                data_port_linkage['args']['name'] = create_name(data_port_linkage['args']['name'], names)
                names.append(data_port_linkage['args']['name'])
            for goal, data_port_linkage in going_data_linkage_for_port['from'].items():
                state = self.states[goal[0]] if goal[0] != self.state_id else self
                port = state.get_data_port_by_id(goal[1])
                data_port_linkage['args'] = port.state_element_to_dict(port)
                data_port_linkage['args']['name'] = create_name(data_port_linkage['args']['name'], names)
                names.append(data_port_linkage['args']['name'])

        ################## IDENTIFY/PRE-PROCESS INGOING DATA FLOWS ###################
        # ingoing data linkage to rebuild -> overview of all with duplicates
        ingoing_data_linkage_for_port = {'from': {}, 'to': {}}
        for df in related_data_flows['ingoing']:
            assign_ingoing_outgoing(df, ingoing_data_linkage_for_port)

        # logger.info("GROUP DATA INGOING BEFORE")
        # print_df_from_and_to(ingoing_data_linkage_for_port)

        # prior to-linkage-merge for ingoing over from-linkage-merge -> less internal ingoing data flows
        do_prior_in_out_going(ingoing_data_linkage_for_port, prior_port_key='to', prior_locate_key='external')

        # logger.info("GROUPED INGOING DATA AFTER")
        # print_df_from_and_to(ingoing_data_linkage_for_port)

        # get name and args for ports
        create_data_port_args(ingoing_data_linkage_for_port)
        # logger.info("GROUPED INGOING DATA PORTS")
        # print_df_from_and_to(ingoing_data_linkage_for_port)

        ################## IDENTIFY/PRE-PROCESS OUTGOING DATA FLOWS ###################
        # outgoing data linkage to rebuild -> overview of all with duplicates
        outgoing_data_linkage_for_port = {'from': {}, 'to': {}}
        for df in related_data_flows['outgoing']:
            assign_ingoing_outgoing(df, outgoing_data_linkage_for_port, ingoing=False)

        # logger.info("GROUP DATA OUTGOING BEFORE")
        # print_df_from_and_to(outgoing_data_linkage_for_port)

        # prior from-linkage-merge for outgoing over to-linkage-merge -> less outgoing data flows
        do_prior_in_out_going(outgoing_data_linkage_for_port, prior_port_key='from', prior_locate_key='external')

        # logger.info("GROUPED OUTGOING DATA AFTER")
        # print_df_from_and_to(outgoing_data_linkage_for_port)

        # get name and args for ports
        create_data_port_args(outgoing_data_linkage_for_port)
        # logger.info("GROUPED OUTGOING DATA PORTS")
        # print_df_from_and_to(outgoing_data_linkage_for_port)

        ############################# CREATE NEW STATE #############################
        # all internal transitions
        transitions_internal = {t.transition_id: self.remove_transition(t.transition_id, destroy=False)
                                for t in related_transitions['enclosed']}
        # all internal data flows
        data_flows_internal = {df.data_flow_id: self.remove_data_flow(df.data_flow_id, destroy=False)
                               for df in related_data_flows['enclosed']}
        # TODO add warning if a data-flow is connected to scoped variables which has ingoing and outgoing data flows
        # TODO linked with selected states -> group would change behavior and scoped would need to be selected or
        # TODO                                local scoped variable need to be introduced in new hierarchy state
        # all internal scoped variables
        scoped_variables_to_group = {dp_id: self.remove_scoped_variable(dp_id, destroy=False)
                                     for dp_id in scoped_variable_ids}
        # all states
        states_to_group = {state_id: self.remove_state(state_id, recursive=False, destroy=False)
                           for state_id in state_ids}
        from rafcon.core.states.hierarchy_state import HierarchyState
        # secure state id conflicts for the taken transitions
        from rafcon.core.id_generator import state_id_generator
        state_id = state_id_generator(used_state_ids=state_ids + [self.state_id])
        # if scoped variables are used all data flows have to be checked if those link to those and correct the state_id
        if scoped_variable_ids:
            for data_flow in data_flows_internal.values():
                if data_flow.from_state == self.state_id:
                    data_flow.from_state = state_id
                if data_flow.to_state == self.state_id:
                    data_flow.to_state = state_id
        s = HierarchyState(states=states_to_group, transitions=transitions_internal, data_flows=data_flows_internal,
                           scoped_variables=scoped_variables_to_group, state_id=state_id)
        state_id = self.add_state(s)

        def find_logical_destinations_of_transitions(transitions):
            destinations = {}
            for t in transitions:
                if (t.to_state, t.to_outcome) in destinations:
                    destinations[(t.to_state, t.to_outcome)].append(t)
                else:
                    destinations[(t.to_state, t.to_outcome)] = [t]
            return destinations

        ################## IDENTIFY TRANSITIONS #####################
        # transition from ingoing transition
        ingoing_logical_destinations = find_logical_destinations_of_transitions(related_transitions['ingoing'])
        if len(ingoing_logical_destinations) > 1:
            logger.warning("There is only one ingoing transition on a state possible. \n"
                           "The following transitions are removed by 'group_states': \n{}"
                           "".format('\n'.join([str(destination) for destination in ingoing_logical_destinations.items()[1:]])))
        ingoing_transitions = None
        if len(ingoing_logical_destinations) > 0:
            ingoing_transitions = list(ingoing_logical_destinations.items())[0][1]
        # transitions from outgoing transitions
        transitions_outgoing = {t.transition_id: t for t in related_transitions['outgoing']}
        outgoing_logical_destinations = find_logical_destinations_of_transitions(related_transitions['outgoing'])

        ################## DO INGOING TRANSITIONS ###################
        if ingoing_transitions:
            t = ingoing_transitions[0]
            s.add_transition(None, None, t.to_state, t.to_outcome)
            for t in ingoing_transitions:
                self.add_transition(t.from_state, t.from_outcome, s.state_id, None)

        ################## DO OUTGOING OUTCOMES ###################
        # outcomes from outgoing transitions
        outcomes_outgoing_transitions = {}
        new_outcome_ids = {}
        state_outcomes_by_name = {oc.name: oc_id for oc_id, oc in s.outcomes.items()}
        for goal, transitions in list(outgoing_logical_destinations.items()):
            t = transitions[0]
            name = s.states[t.from_state].outcomes[t.from_outcome].name
            # print((t.to_state, t.to_outcome))
            # print(outcomes_outgoing_transitions)
            if goal in outcomes_outgoing_transitions:
                # logger.info("old outcome {}".format((t.to_state, t.to_outcome)))
                name = outcomes_outgoing_transitions[goal]
            else:
                name = create_name(name, list(new_outcome_ids.keys()))
                outcomes_outgoing_transitions[goal] = name
            # print(outcomes_outgoing_transitions, "\n", new_outcome_ids)
            if name not in new_outcome_ids:
                if name in state_outcomes_by_name:
                    new_outcome_ids[name] = state_outcomes_by_name[name]
                    # logger.info("old outcome_id {0}\n{1}".format(state_outcomes_by_name[name], new_outcome_ids))
                else:
                    new_outcome_ids[name] = s.add_outcome(name=name)
                    # logger.info("new outcome_id {0}\n{1}".format(new_outcome_ids[name], new_outcome_ids))
            # else:
            #     logger.info("name {0} in {1} -> {2}".format(name, new_outcome_ids, outcomes_outgoing_transitions))

        ################## DO OUTGOING TRANSITIONS ###################
        # external outgoing transitions
        # print("external transitions to create", outcomes_outgoing_transitions)
        for goal, name in outcomes_outgoing_transitions.items():
            try:
                # avoid to use a outcome twice
                if any([t for t in s.parent.transitions.values()
                        if t.from_state == s.state_id and t.from_outcome == new_outcome_ids[name]]):
                    continue
                # add the transition for the outcome
                self.add_transition(s.state_id, new_outcome_ids[name], goal[0], goal[1])
            except ValueError:
                logger.exception("Error while recreation of logical linkage.")
        # internal outgoing transitions
        # print("internal transitions to create", transitions_outgoing)
        for t_id, t in transitions_outgoing.items():
            name = outcomes_outgoing_transitions[(t.to_state, t.to_outcome)]
            s.add_transition(t.from_state, t.from_outcome, s.state_id, new_outcome_ids[name], t_id)

        new_state_ids = {self.state_id: s.state_id}
        ############## REBUILD INGOING DATA LINKAGE ################
        full_linkage = copy(ingoing_data_linkage_for_port['from'])
        full_linkage.update(ingoing_data_linkage_for_port['to'])
        for port, data_port_linkage in full_linkage.items():
            # input data ports from ingoing data flows
            args = data_port_linkage['args']
            args['data_port_id'] = None
            args['data_port_id'] = s.add_input_data_port(**args)
            # internal data flows from ingoing data flows
            # print("ingoing internal data flows")
            for df in data_port_linkage['internal']:
                # print(df)
                s.add_data_flow(from_state_id=s.state_id, from_data_port_id=args['data_port_id'],
                                to_state_id=new_state_ids.get(df.to_state, df.to_state),
                                to_data_port_id=df.to_key, data_flow_id=df.data_flow_id)
            # external data flows from ingoing data flows
            # print("ingoing external data flows")
            for df in data_port_linkage['external']:
                # print(df)
                self.add_data_flow(from_state_id=df.from_state,
                                   from_data_port_id=df.from_key, to_state_id=s.state_id,
                                   to_data_port_id=args['data_port_id'], data_flow_id=df.data_flow_id)

        ############## REBUILD OUTGOING DATA LINKAGE ################
        full_linkage = copy(outgoing_data_linkage_for_port['from'])
        full_linkage.update(outgoing_data_linkage_for_port['to'])
        for port, data_port_linkage in full_linkage.items():
            # output data ports from outgoing data flows
            args = data_port_linkage['args']
            args['data_port_id'] = None
            args['data_port_id'] = s.add_output_data_port(**args)
            # internal data flows from outgoing data flows
            # print("outgoing internal data flows")
            for df in data_port_linkage['internal']:
                # print(df)
                s.add_data_flow(from_state_id=new_state_ids.get(df.from_state, df.from_state),
                                from_data_port_id=df.from_key, to_state_id=s.state_id,
                                to_data_port_id=args['data_port_id'], data_flow_id=df.data_flow_id)
            # external data flows from outgoing data flows
            # print("outgoing external data flows")
            for df in data_port_linkage['external']:
                # print(df)
                self.add_data_flow(from_state_id=s.state_id, from_data_port_id=args['data_port_id'],
                                   to_state_id=df.to_state, to_data_port_id=df.to_key, data_flow_id=df.data_flow_id)

        return self.states[state_id]


Instruction:
Given the following Python 3 function, write the documentation
def add_state(self, state, storage_load=False):
        assert isinstance(state, State)
        # logger.info("add state {}".format(state))

        # handle the case that the child state id is the same as the container state id or future sibling state id
        while state.state_id == self.state_id or state.state_id in self.states:
            state.change_state_id()

        # TODO: add validity checks for states and then remove this check => to discuss
        if state.state_id in self._states.keys():
            raise AttributeError("State id %s already exists in the container state", state.state_id)
        else:
            state.parent = self
            self._states[state.state_id] = state

        return state.state_id

Response: Adds a state to the container state.


Instruction:
Explain what the following Python 3 code does
def remove_state(self, state_id, recursive=True, force=False, destroy=True):
        if state_id not in self.states:
            raise AttributeError("State_id %s does not exist" % state_id)

        if state_id == self.start_state_id:
            self.set_start_state(None)

        # first delete all transitions and data_flows, which are connected to the state to be deleted
        keys_to_delete = []
        for key, transition in self.transitions.items():
            if transition.from_state == state_id or transition.to_state == state_id:
                keys_to_delete.append(key)
        for key in keys_to_delete:
            self.remove_transition(key, True)

        keys_to_delete = []
        for key, data_flow in self.data_flows.items():
            if data_flow.from_state == state_id or data_flow.to_state == state_id:
                keys_to_delete.append(key)
        for key in keys_to_delete:
            self.remove_data_flow(key)

        if recursive and not destroy:
            raise AttributeError("The recursive flag requires the destroy flag to be set, too.")

        if destroy:
            # Recursively delete all transitions, data flows and states within the state to be deleted
            self.states[state_id].destroy(recursive)

        # final delete the state it self
        self.states[state_id].parent = None
        return self.states.pop(state_id)

Response: Removes a state from the container state.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def destroy(self, recursive):
        for transition_id in list(self.transitions.keys()):
            self.remove_transition(transition_id, destroy=recursive)
        for data_flow_id in list(self.data_flows.keys()):
            self.remove_data_flow(data_flow_id, destroy=recursive)
        for scoped_variable_id in list(self.scoped_variables.keys()):
            self.remove_scoped_variable(scoped_variable_id, destroy=recursive)
        for state_id in list(self.states.keys()):
            if recursive:
                self.remove_state(state_id, recursive, force=True, destroy=recursive)
            else:
                del self.states[state_id]
        super(ContainerState, self).destroy(recursive)

Response: Removes all the state elements.


Instruction:
Implement a Python 3 function for
returning a tuple of related_transitions related_data_flows and related_internal_transitions for the given state_id.

Response:
def related_linkage_state(self, state_id):
        """ TODO: document
        """

        related_transitions = {'external': {'ingoing': [], 'outgoing': []},
                               'internal': {'enclosed': [], 'ingoing': [], 'outgoing': []}}
        related_data_flows = {'external': {'ingoing': [], 'outgoing': []},
                              'internal': {'enclosed': [], 'ingoing': [], 'outgoing': []}}
        # ingoing logical linkage to rebuild
        related_transitions['external']['ingoing'] = [t for t in self.transitions.values() if t.to_state == state_id]
        # outgoing logical linkage to rebuild
        related_transitions['external']['outgoing'] = [t for t in self.transitions.values() if t.from_state == state_id]
        # ingoing data linkage to rebuild
        related_data_flows['external']['ingoing'] = [df for df in self.data_flows.values() if df.to_state == state_id]
        # outgoing outgoing linkage to rebuild
        related_data_flows['external']['outgoing'] = [df for df in self.data_flows.values() if df.from_state == state_id]

        state = self.states[state_id]
        if not isinstance(state, ContainerState):
            return related_transitions, related_data_flows

        for t_id, t in state.transitions.items():
            # check if internal of new hierarchy state
            if t.from_state in state.states and t.to_state in state.states:
                related_transitions['internal']['enclosed'].append(t)
            elif t.to_state in state.states:
                related_transitions['internal']['ingoing'].append(t)
            elif t.from_state in state.states:
                related_transitions['internal']['outgoing'].append(t)
            else:
                raise AttributeError("All transition have to be ingoing, outgoing or internal.")

        for df_id, df in state.data_flows.items():
            # check if internal of hierarchy state
            if df.from_state in state.states and df.to_state in state.states or \
                    df.from_state in state.states and state.state_id == df.to_state and df.to_key in state.scoped_variables or \
                    state.state_id == df.from_state and df.from_key in state.scoped_variables and df.to_state in state.states:
                related_data_flows['internal']['enclosed'].append(df)
            elif df.to_state in state.states or \
                    state.state_id == df.to_state and df.to_key in state.scoped_variables or \
                    df.to_state == df.from_state and df.from_key in state.input_data_ports:
                related_data_flows['internal']['ingoing'].append(df)
            elif df.from_state in state.states or \
                    state.state_id == df.from_state and df.from_key in state.scoped_variables or \
                    df.to_state == df.from_state and df.to_key in state.output_data_ports:
                related_data_flows['internal']['outgoing'].append(df)
            else:
                raise AttributeError("All data flow have to be ingoing, outgoing or internal.")

        return related_transitions, related_data_flows


Instruction:
Can you tell what is the following Python 3 function doing
def related_linkage_states_and_scoped_variables(self, state_ids, scoped_variables):

        # find all related transitions
        related_transitions = {'enclosed': [], 'ingoing': [], 'outgoing': []}
        for t in self.transitions.values():
            # check if internal of new hierarchy state
            if t.from_state in state_ids and t.to_state in state_ids:
                related_transitions['enclosed'].append(t)
            elif t.to_state in state_ids:
                related_transitions['ingoing'].append(t)
            elif t.from_state in state_ids:
                related_transitions['outgoing'].append(t)

        # find all related data flows
        related_data_flows = {'enclosed': [], 'ingoing': [], 'outgoing': []}
        for df in self.data_flows.values():
            # check if internal of new hierarchy state
            if df.from_state in state_ids and df.to_state in state_ids or \
                    df.from_state in state_ids and self.state_id == df.to_state and df.to_key in scoped_variables or \
                    self.state_id == df.from_state and df.from_key in scoped_variables and df.to_state in state_ids:
                related_data_flows['enclosed'].append(df)
            elif df.to_state in state_ids or \
                    self.state_id == df.to_state and df.to_key in scoped_variables:
                related_data_flows['ingoing'].append(df)
            elif df.from_state in state_ids or \
                    self.state_id == df.from_state and df.from_key in scoped_variables:
                related_data_flows['outgoing'].append(df)

        return related_transitions, related_data_flows

Response: This function returns a list of related linkage states and scoped variables.


Instruction:
Here you have a function in Python 3, explain what it does
def change_state_type(self, state, new_state_class):
        from rafcon.gui.helpers.state import create_new_state_from_state_with_type

        state_id = state.state_id

        if state_id not in self.states:
            raise ValueError("State '{0}' with id '{1}' does not exist".format(state.name, state_id))

        new_state = create_new_state_from_state_with_type(state, new_state_class)
        new_state.parent = self

        assert new_state.state_id == state_id

        self.states[state_id] = new_state

        return new_state

Response: Changes the type of the state to another type


Instruction:
Write a Python 3 function that can
set the start state of a container state

Response:
def set_start_state(self, state):
        """Sets the start state of a container state

        :param state: The state_id of a state or a direct reference ot he state (that was already added
                    to the container) that will be the start state of this container state.

        """
        if state is None:
            self.start_state_id = None
        elif isinstance(state, State):
            self.start_state_id = state.state_id
        else:
            self.start_state_id = state


Instruction:
How would you explain what the following Python 3 function does
def get_start_state(self, set_final_outcome=False):

        # overwrite the start state in the case that a specific start state is specific e.g. by start_from_state
        if self.get_path() in state_machine_execution_engine.start_state_paths:
            for state_id, state in self.states.items():
                if state.get_path() in state_machine_execution_engine.start_state_paths:
                    state_machine_execution_engine.start_state_paths.remove(self.get_path())
                    self._start_state_modified = True
                    return state

        if self.start_state_id is None:
            return None

        # It is possible to connect the income directly with an outcome
        if self.start_state_id == self.state_id:
            if set_final_outcome:
                for transition_id in self.transitions:
                    # the transition of which the from state is None is the transition that directly connects the income
                    if self.transitions[transition_id].from_state is None:
                        to_outcome_id = self.transitions[transition_id].to_outcome
                        self.final_outcome = self.outcomes[to_outcome_id]
                        break
            return self

        return self.states[self.start_state_id]

Response: Get the start state of the container state.


Instruction:
Can you create a Python 3 function that
removes the state element from the container state.

Response:
def remove(self, state_element, recursive=True, force=False, destroy=True):
        """Remove item from state

        :param StateElement state_element: State or state element to be removed
        :param bool recursive: Only applies to removal of state and decides whether the removal should be called
            recursively on all child states
        :param bool force: if the removal should be forced without checking constraints
        :param bool destroy: a flag that signals that the state element will be fully removed and disassembled
        """
        if isinstance(state_element, State):
            return self.remove_state(state_element.state_id, recursive=recursive, force=force, destroy=destroy)
        elif isinstance(state_element, Transition):
            return self.remove_transition(state_element.transition_id, destroy=destroy)
        elif isinstance(state_element, DataFlow):
            return self.remove_data_flow(state_element.data_flow_id, destroy=destroy)
        elif isinstance(state_element, ScopedVariable):
            return self.remove_scoped_variable(state_element.data_port_id, destroy=destroy)
        else:
            super(ContainerState, self).remove(state_element, force=force, destroy=destroy)


Instruction:
Can you generate the documentation for the following Python 3 function
def check_transition_id(self, transition_id):
        if transition_id is not None:
            if transition_id in self._transitions.keys():
                raise AttributeError("The transition id %s already exists. Cannot add transition!", transition_id)
        else:
            transition_id = generate_transition_id()
            while transition_id in self._transitions.keys():
                transition_id = generate_transition_id()
        return transition_id

Response: Checks the transition id and calculates a new one if it does not exist.


Instruction:
How would you explain what the following Python 3 function does
def check_if_outcome_already_connected(self, from_state_id, from_outcome):
        for trans_key, transition in self.transitions.items():
            if transition.from_state == from_state_id:
                if transition.from_outcome == from_outcome:
                    raise AttributeError("Outcome %s of state %s is already connected" %
                                         (str(from_outcome), str(from_state_id)))

Response: check if outcome of from state is not already connected to the transition to