Instruction:
How would you code a function in Python 3 to
create a new transition.

Response:
def create_transition(self, from_state_id, from_outcome, to_state_id, to_outcome, transition_id):
        """ Creates a new transition.

        Lookout: Check the parameters first before creating a new transition

        :param from_state_id: The source state of the transition
        :param from_outcome: The outcome of the source state to connect the transition to
        :param to_state_id: The target state of the transition
        :param to_outcome: The target outcome of a container state
        :param transition_id: An optional transition id for the new transition
        :raises exceptions.AttributeError: if the from or to state is incorrect
        :return: the id of the new transition
        """

        # get correct states
        if from_state_id is not None:
            if from_state_id == self.state_id:
                from_state = self
            else:
                from_state = self.states[from_state_id]

        # finally add transition
        if from_outcome is not None:
            if from_outcome in from_state.outcomes:
                if to_outcome is not None:
                    if to_outcome in self.outcomes:  # if to_state is None then the to_outcome must be an outcome of self
                        self.transitions[transition_id] = \
                            Transition(from_state_id, from_outcome, to_state_id, to_outcome, transition_id, self)
                    else:
                        raise AttributeError("to_state does not have outcome %s", to_outcome)
                else:  # to outcome is None but to_state is not None, so the transition is valid
                    self.transitions[transition_id] = \
                        Transition(from_state_id, from_outcome, to_state_id, to_outcome, transition_id, self)
            else:
                raise AttributeError("from_state does not have outcome %s", from_state)
        else:
            self.transitions[transition_id] = \
                Transition(None, None, to_state_id, to_outcome, transition_id, self)

        # notify all states waiting for transition to be connected
        self._transitions_cv.acquire()
        self._transitions_cv.notify_all()
        self._transitions_cv.release()

        return transition_id


Instruction:
Make a summary of the following Python 3 code
def add_transition(self, from_state_id, from_outcome, to_state_id, to_outcome, transition_id=None):

        transition_id = self.check_transition_id(transition_id)

        # Set from_state_id to None for start transitions, as from_state_id and from_outcome should both be None for
        # these transitions
        if from_state_id == self.state_id and from_outcome is None:
            from_state_id = None

        new_transition = Transition(from_state_id, from_outcome, to_state_id, to_outcome, transition_id, self)
        self.transitions[transition_id] = new_transition

        # notify all states waiting for transition to be connected
        self._transitions_cv.acquire()
        self._transitions_cv.notify_all()
        self._transitions_cv.release()
        # self.create_transition(from_state_id, from_outcome, to_state_id, to_outcome, transition_id)
        return transition_id

Response: Adds a transition to the container state


Instruction:
Can you generate a brief explanation for the following Python 3 code
def get_transition_for_outcome(self, state, outcome):
        if not isinstance(state, State):
            raise TypeError("state must be of type State")
        if not isinstance(outcome, Outcome):
            raise TypeError("outcome must be of type Outcome")
        result_transition = None
        for key, transition in self.transitions.items():
            if transition.from_state == state.state_id and transition.from_outcome == outcome.outcome_id:
                result_transition = transition
        return result_transition

Response: Determines the next transition for the given outcome.


Instruction:
Can you generate the documentation for the following Python 3 function
def remove_transition(self, transition_id, destroy=True):
        if transition_id == -1 or transition_id == -2:
            raise AttributeError("The transition_id must not be -1 (Aborted) or -2 (Preempted)")
        if transition_id not in self._transitions:
            raise AttributeError("The transition_id %s does not exist" % str(transition_id))

        self.transitions[transition_id].parent = None
        return self.transitions.pop(transition_id)

Response: Removes a transition from the container state.


Instruction:
Here you have a function in Python 3, explain what it does
def remove_outcome_hook(self, outcome_id):
        for transition_id in list(self.transitions.keys()):
            transition = self.transitions[transition_id]
            if transition.to_outcome == outcome_id and transition.to_state == self.state_id:
                self.remove_transition(transition_id)

Response: Removes the outcome from the internal state.


Instruction:
Write a Python 3 function for
checking the data flow id and calculate a new one if it does not exist.

Response:
def check_data_flow_id(self, data_flow_id):
        """ Check the data flow id and calculate a new one if its None

        :param data_flow_id: The data flow id to check
        :return: The new data flow id
        :raises exceptions.AttributeError: if data_flow.data_flow_id already exists
        """
        if data_flow_id is not None:
            if data_flow_id in self._data_flows.keys():
                raise AttributeError("The data_flow id %s already exists. Cannot add data_flow!", data_flow_id)
        else:
            data_flow_id = generate_data_flow_id()
            while data_flow_id in self._data_flows.keys():
                data_flow_id = generate_data_flow_id()
        return data_flow_id


Instruction:
Can you generate a brief explanation for the following Python 3 code
def add_data_flow(self, from_state_id, from_data_port_id, to_state_id, to_data_port_id, data_flow_id=None):
        data_flow_id = self.check_data_flow_id(data_flow_id)

        self.data_flows[data_flow_id] = DataFlow(from_state_id, from_data_port_id, to_state_id, to_data_port_id,
                                                 data_flow_id, self)
        return data_flow_id

Response: Adds a data flow to the container state


Instruction:
Can you generate the documentation for the following Python 3 function
def remove_data_flow(self, data_flow_id, destroy=True):
        if data_flow_id not in self._data_flows:
            raise AttributeError("The data_flow_id %s does not exist" % str(data_flow_id))

        self._data_flows[data_flow_id].parent = None
        return self._data_flows.pop(data_flow_id)

Response: Removes a data flow from the container state


Instruction:
Here you have a function in Python 3, explain what it does
def remove_data_flows_with_data_port_id(self, data_port_id):
        # delete all data flows in parent related to data_port_id and self.state_id = external data flows
        # checking is_root_state_of_library is only necessary in case of scoped variables, as the scoped variables
        # they are not destroyed by the library state, as the library state does not have a reference to the scoped vars
        if not self.is_root_state and not self.is_root_state_of_library:
            data_flow_ids_to_remove = []
            for data_flow_id, data_flow in self.parent.data_flows.items():
                if data_flow.from_state == self.state_id and data_flow.from_key == data_port_id or \
                                        data_flow.to_state == self.state_id and data_flow.to_key == data_port_id:
                    data_flow_ids_to_remove.append(data_flow_id)

            for data_flow_id in data_flow_ids_to_remove:
                self.parent.remove_data_flow(data_flow_id)

        # delete all data flows in self related to data_port_id and self.state_id = internal data flows
        data_flow_ids_to_remove = []
        for data_flow_id, data_flow in self.data_flows.items():
            if data_flow.from_state == self.state_id and data_flow.from_key == data_port_id or \
                                    data_flow.to_state == self.state_id and data_flow.to_key == data_port_id:
                data_flow_ids_to_remove.append(data_flow_id)

        for data_flow_id in data_flow_ids_to_remove:
            self.remove_data_flow(data_flow_id)

Response: Removes all data flows with the passed data_port_id from the state.


Instruction:
Can you create a Python 3 function that
gets the scoped variable for a unique name

Response:
def get_scoped_variable_from_name(self, name):
        """ Get the scoped variable for a unique name

        :param name: the unique name of the scoped variable
        :return: the scoped variable specified by the name
        :raises exceptions.AttributeError: if the name is not in the the scoped_variables dictionary
        """
        for scoped_variable_id, scoped_variable in self.scoped_variables.items():
            if scoped_variable.name == name:
                return scoped_variable_id
        raise AttributeError("Name %s is not in scoped_variables dictionary", name)


Instruction:
Here you have a function in Python 3, explain what it does
def add_scoped_variable(self, name, data_type=None, default_value=None, scoped_variable_id=None):
        if scoped_variable_id is None:
            # All data port ids have to passed to the id generation as the data port id has to be unique inside a state
            scoped_variable_id = generate_data_port_id(self.get_data_port_ids())
        self._scoped_variables[scoped_variable_id] = ScopedVariable(name, data_type, default_value,
                                                                    scoped_variable_id, self)

        # Check for name uniqueness
        valid, message = self._check_data_port_name(self._scoped_variables[scoped_variable_id])
        if not valid:
            self._scoped_variables[scoped_variable_id].parent = None
            del self._scoped_variables[scoped_variable_id]
            raise ValueError(message)

        return scoped_variable_id

Response: Adds a scoped variable to the state.


Instruction:
Create a Python 3 function to
remove a scoped variable from the container state.

Response:
def remove_scoped_variable(self, scoped_variable_id, destroy=True):
        """Remove a scoped variable from the container state

        :param scoped_variable_id: the id of the scoped variable to remove
        :raises exceptions.AttributeError: if the id of the scoped variable already exists
        """
        if scoped_variable_id not in self._scoped_variables:
            raise AttributeError("A scoped variable with id %s does not exist" % str(scoped_variable_id))

        # delete all data flows connected to scoped_variable
        if destroy:
            self.remove_data_flows_with_data_port_id(scoped_variable_id)

        # delete scoped variable
        self._scoped_variables[scoped_variable_id].parent = None
        return self._scoped_variables.pop(scoped_variable_id)


Instruction:
Make a summary of the following Python 3 code
def get_data_port(self, state_id, port_id):
        if state_id == self.state_id:
            return self.get_data_port_by_id(port_id)
        for child_state_id, child_state in self.states.items():
            if state_id != child_state_id:
                continue
            port = child_state.get_data_port_by_id(port_id)
            if port:
                return port
        return None

Response: Searches for a data port in the state with the specified id and returns the data port object.


Instruction:
Can you tell what is the following Python 3 function doing
def get_data_port_by_id(self, data_port_id):
        data_port = super(ContainerState, self).get_data_port_by_id(data_port_id)
        if data_port:
            return data_port
        if data_port_id in self.scoped_variables:
            return self.scoped_variables[data_port_id]
        return None

Response: Search for the given data port id in the state and return the data port with the searched id or None if not found.


Instruction:
Can you tell what is the following Python 3 function doing
def get_inputs_for_state(self, state):
        result_dict = {}

        tmp_dict = self.get_default_input_values_for_state(state)
        result_dict.update(tmp_dict)

        for input_port_key, value in state.input_data_ports.items():
            # for all input keys fetch the correct data_flow connection and read data into the result_dict
            actual_value = None
            actual_value_time = 0
            for data_flow_key, data_flow in self.data_flows.items():

                if data_flow.to_key == input_port_key:
                    if data_flow.to_state == state.state_id:
                        # fetch data from the scoped_data list: the key is the data_port_key + the state_id
                        key = str(data_flow.from_key) + data_flow.from_state
                        if key in self.scoped_data:
                            if actual_value is None or actual_value_time < self.scoped_data[key].timestamp:
                                actual_value = deepcopy(self.scoped_data[key].value)
                                actual_value_time = self.scoped_data[key].timestamp

            if actual_value is not None:
                result_dict[value.name] = actual_value

        return result_dict

Response: Retrieves all input data for a state


Instruction:
Can you create a Python 3 function that
adds a dictionary to the scoped data

Response:
def add_input_data_to_scoped_data(self, dictionary):
        """Add a dictionary to the scoped data

        As the input_data dictionary maps names to values, the functions looks for the proper data_ports keys in the
        input_data_ports dictionary

        :param dictionary: The dictionary that is added to the scoped data
        :param state: The state to which the input_data was passed (should be self in most cases)
        """
        for dict_key, value in dictionary.items():
            for input_data_port_key, data_port in list(self.input_data_ports.items()):
                if dict_key == data_port.name:
                    self.scoped_data[str(input_data_port_key) + self.state_id] = \
                        ScopedData(data_port.name, value, type(value), self.state_id, ScopedVariable, parent=self)
                    # forward the data to scoped variables
                    for data_flow_key, data_flow in self.data_flows.items():
                        if data_flow.from_key == input_data_port_key and data_flow.from_state == self.state_id:
                            if data_flow.to_state == self.state_id and data_flow.to_key in self.scoped_variables:
                                current_scoped_variable = self.scoped_variables[data_flow.to_key]
                                self.scoped_data[str(data_flow.to_key) + self.state_id] = \
                                    ScopedData(current_scoped_variable.name, value, type(value), self.state_id,
                                               ScopedVariable, parent=self)


Instruction:
Explain what the following Python 3 code does
def add_state_execution_output_to_scoped_data(self, dictionary, state):
        for output_name, value in dictionary.items():
            for output_data_port_key, data_port in list(state.output_data_ports.items()):
                if output_name == data_port.name:
                    if not isinstance(value, data_port.data_type):
                        if (not ((type(value) is float or type(value) is int) and
                                     (data_port.data_type is float or data_port.data_type is int)) and
                                not (isinstance(value, type(None)))):
                            logger.error("The data type of output port {0} should be of type {1}, but is of type {2}".
                                         format(output_name, data_port.data_type, type(value)))
                    self.scoped_data[str(output_data_port_key) + state.state_id] = \
                        ScopedData(data_port.name, value, type(value), state.state_id, OutputDataPort, parent=self)

Response: Adds a state execution output to the scoped data


Instruction:
Here you have a function in Python 3, explain what it does
def add_default_values_of_scoped_variables_to_scoped_data(self):
        for key, scoped_var in self.scoped_variables.items():
            self.scoped_data[str(scoped_var.data_port_id) + self.state_id] = \
                ScopedData(scoped_var.name, scoped_var.default_value, scoped_var.data_type, self.state_id,
                           ScopedVariable, parent=self)

Response: Add the default values of the scoped variables to the scoped data dictionary


Instruction:
Create a Python 3 function for
updating the values of the scoped variables with the output dictionary of a specific state.

Response:
def update_scoped_variables_with_output_dictionary(self, dictionary, state):
        """Update the values of the scoped variables with the output dictionary of a specific state.

        :param: the dictionary to update the scoped variables with
        :param: the state the output dictionary belongs to
        """
        for key, value in dictionary.items():
            output_data_port_key = None
            # search for the correct output data port key of the source state
            for o_key, o_port in state.output_data_ports.items():
                if o_port.name == key:
                    output_data_port_key = o_key
                    break
            if output_data_port_key is None:
                if not key == "error":
                    logger.warning("Output variable %s was written during state execution, "
                                   "that has no data port connected to it.", str(key))
            for data_flow_key, data_flow in self.data_flows.items():
                if data_flow.from_key == output_data_port_key and data_flow.from_state == state.state_id:
                    if data_flow.to_state == self.state_id:  # is target of data flow own state id?
                        if data_flow.to_key in self.scoped_variables.keys():  # is target data port scoped?
                            current_scoped_variable = self.scoped_variables[data_flow.to_key]
                            self.scoped_data[str(data_flow.to_key) + self.state_id] = \
                                ScopedData(current_scoped_variable.name, value, type(value), state.state_id,
                                           ScopedVariable, parent=self)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def change_state_id(self, state_id=None):
        old_state_id = self.state_id
        super(ContainerState, self).change_state_id(state_id)
        # Use private variables to change ids to prevent validity checks
        # change id in all transitions
        for transition in self.transitions.values():
            if transition.from_state == old_state_id:
                transition._from_state = self.state_id
            if transition.to_state == old_state_id:
                transition._to_state = self.state_id

        # change id in all data_flows
        for data_flow in self.data_flows.values():
            if data_flow.from_state == old_state_id:
                data_flow._from_state = self.state_id
            if data_flow.to_state == old_state_id:
                data_flow._to_state = self.state_id

Response: Changes the id of the state of the container state to a new id. This function replaces the old state_id with the new state_id in all the state tables and data flows and transitions.


Instruction:
Can you implement a function in Python 3 that
calculates the target state of a transition

Response:
def get_state_for_transition(self, transition):
        """Calculate the target state of a transition

        :param transition: The transition of which the target state is determined
        :return: the to-state of the transition
        :raises exceptions.TypeError: if the transition parameter is of wrong type
        """
        if not isinstance(transition, Transition):
            raise TypeError("transition must be of type Transition")
        # the to_state is None when the transition connects an outcome of a child state to the outcome of a parent state
        if transition.to_state == self.state_id or transition.to_state is None:
            return self
        else:
            return self.states[transition.to_state]


Instruction:
Can you generate the documentation for the following Python 3 function
def write_output_data(self, specific_output_dictionary=None):
        if isinstance(specific_output_dictionary, dict):
            output_dict = specific_output_dictionary
        else:
            output_dict = self.output_data

        for output_name, value in self.output_data.items():
            output_port_id = self.get_io_data_port_id_from_name_and_type(output_name, OutputDataPort)
            actual_value = None
            actual_value_was_written = False
            actual_value_time = 0
            for data_flow_id, data_flow in self.data_flows.items():
                if data_flow.to_state == self.state_id:
                    if data_flow.to_key == output_port_id:
                        scoped_data_key = str(data_flow.from_key) + data_flow.from_state
                        if scoped_data_key in self.scoped_data:
                            # if self.scoped_data[scoped_data_key].timestamp > actual_value_time is True
                            # the data of a previous execution of the same state is overwritten
                            if actual_value is None or self.scoped_data[scoped_data_key].timestamp > actual_value_time:
                                actual_value = deepcopy(self.scoped_data[scoped_data_key].value)
                                actual_value_time = self.scoped_data[scoped_data_key].timestamp
                                actual_value_was_written = True
                        else:
                            if not self.backward_execution:
                                logger.debug(
                                    "Output data with name {0} of state {1} was not found in the scoped data "
                                    "of state {2}. Thus the state did not write onto this output. "
                                    "This can mean a state machine design error.".format(
                                        str(output_name), str(self.states[data_flow.from_state].get_path()),
                                        self.get_path()))
            if actual_value_was_written:
                output_dict[output_name] = actual_value

Response: Write the scoped data to output of the container state.


Instruction:
Can you generate the documentation for the following Python 3 function
def check_child_validity(self, child):
        # First let the state do validity checks for outcomes and data ports
        valid, message = super(ContainerState, self).check_child_validity(child)
        if not valid and not message.startswith("Invalid state element"):
            return False, message
        # Continue with checks if previous ones did not fail
        # Check type of child and call appropriate validity test
        if isinstance(child, DataFlow):
            return self._check_data_flow_validity(child)
        if isinstance(child, Transition):
            return self._check_transition_validity(child)
        return valid, message

Response: Check validity of passed child object


Instruction:
Implement a function in Python 3 to
check the validity of a data port

Response:
def check_data_port_connection(self, check_data_port):
        """Checks the connection validity of a data port

        The method is called by a child state to check the validity of a data port in case it is connected with data
        flows. The data port does not belong to 'self', but to one of self.states.
        If the data port is connected to a data flow, the method checks, whether these connect consistent data types
        of ports.

        :param rafcon.core.data_port.DataPort check_data_port: The port to check
        :return: valid, message
        """
        for data_flow in self.data_flows.values():
            # Check whether the data flow connects the given port
            from_port = self.get_data_port(data_flow.from_state, data_flow.from_key)
            to_port = self.get_data_port(data_flow.to_state, data_flow.to_key)
            if check_data_port is from_port or check_data_port is to_port:
                # check if one of the data_types if type 'object'; in this case the data flow is always valid
                if not (from_port.data_type is object or to_port.data_type is object):
                    if not type_inherits_of_type(from_port.data_type, to_port.data_type):
                        return False, "Connection of two non-compatible data types"
        return True, "valid"


Instruction:
Here you have a function in Python 3, explain what it does
def _check_data_port_id(self, data_port):
        # First check inputs and outputs
        valid, message = super(ContainerState, self)._check_data_port_id(data_port)
        if not valid:
            return False, message
        # Container state also has scoped variables
        for scoped_variable_id, scoped_variable in self.scoped_variables.items():
            if data_port.data_port_id == scoped_variable_id and data_port is not scoped_variable:
                return False, "data port id already existing in state"
        return True, message

Response: Checks the validity of a data port id


Instruction:
Can you write a function in Python 3 where it
checks the validity of a data port name

Response:
def _check_data_port_name(self, data_port):
        """Checks the validity of a data port name

        Checks whether the name of the given data port is already used by anther data port within the state. Names
        must be unique with input data ports, output data ports and scoped variables.

        :param rafcon.core.data_port.DataPort data_port: The data port to be checked
        :return bool validity, str message: validity is True, when the data port is valid, False else. message gives
            more information especially if the data port is not valid
        """
        # First check inputs and outputs
        valid, message = super(ContainerState, self)._check_data_port_name(data_port)
        if not valid:
            return False, message

        if data_port.data_port_id in self.scoped_variables:
            for scoped_variable in self.scoped_variables.values():
                if data_port.name == scoped_variable.name and data_port is not scoped_variable:
                    return False, "scoped variable name already existing in state's scoped variables"

        return True, message


Instruction:
Explain what the following Python 3 code does
def _check_data_flow_validity(self, check_data_flow):
        valid, message = self._check_data_flow_id(check_data_flow)
        if not valid:
            return False, message

        valid, message = self._check_data_flow_ports(check_data_flow)
        if not valid:
            return False, message

        return self._check_data_flow_types(check_data_flow)

Response: Checks the validity of a data flow


Instruction:
Can you write a function in Python 3 where it
checks the validity of a data flow id

Response:
def _check_data_flow_id(self, data_flow):
        """Checks the validity of a data flow id

        Checks whether the id of the given data flow is already by anther data flow used within the state.

        :param rafcon.core.data_flow.DataFlow data_flow: The data flow to be checked
        :return bool validity, str message: validity is True, when the data flow is valid, False else. message gives
            more information especially if the data flow is not valid
        """
        data_flow_id = data_flow.data_flow_id
        if data_flow_id in self.data_flows and data_flow is not self.data_flows[data_flow_id]:
            return False, "data_flow_id already existing"
        return True, "valid"


Instruction:
Given the following Python 3 function, write the documentation
def _check_data_flow_ports(self, data_flow):
        from_state_id = data_flow.from_state
        to_state_id = data_flow.to_state
        from_data_port_id = data_flow.from_key
        to_data_port_id = data_flow.to_key

        # Check whether to and from port are existing
        from_data_port = self.get_data_port(from_state_id, from_data_port_id)
        if not from_data_port:
            return False, "Data flow origin not existing -> {0}".format(data_flow)
        to_data_port = self.get_data_port(to_state_id, to_data_port_id)
        if not to_data_port:
            return False, "Data flow target not existing -> {0}".format(data_flow)

        # Data_ports without parents are not allowed to be connected twice
        if not from_data_port.parent:
            return False, "Source data port does not have a parent -> {0}".format(data_flow)
        if not to_data_port.parent:
            return False, "Target data port does not have a parent -> {0}".format(data_flow)

        # Check if data ports are identical
        if from_data_port is to_data_port:
            return False, "Source and target data ports of data flow must not be identical -> {}".format(data_flow)

        # Check, whether the origin of the data flow is valid
        if from_state_id == self.state_id:  # data_flow originates in container state
            if from_data_port_id not in self.input_data_ports and from_data_port_id not in self.scoped_variables:
                return False, "Data flow origin port must be an input port or scoped variable, when the data flow " \
                              "starts in the parent state -> {0}".format(data_flow)
        else:  # data flow originates in child state
            if from_data_port_id not in from_data_port.parent.output_data_ports:
                return False, "Data flow origin port must be an output port, when the data flow " \
                              "starts in the child state -> {0}".format(data_flow)

        # Check, whether the target of a data flow is valid
        if to_state_id == self.state_id:  # data_flow ends in container state
            if to_data_port_id not in self.output_data_ports and to_data_port_id not in self.scoped_variables:
                return False, "Data flow target port must be an output port or scoped variable, when the data flow " \
                              "goes to the parent state -> {0}".format(data_flow)
        else:  # data_flow ends in child state
            if to_data_port_id not in to_data_port.parent.input_data_ports:
                return False, "Data flow target port must be an input port, when the data flow goes to a child state" \
                              " -> {0}".format(data_flow)

        # Check if data flow connects two scoped variables
        if isinstance(from_data_port, ScopedVariable) and isinstance(to_data_port, ScopedVariable):
            return False, "Data flows must not connect two scoped variables -> {}".format(data_flow)

        # Check, whether the target port is already connected
        for existing_data_flow in self.data_flows.values():
            to_data_port_existing = self.get_data_port(existing_data_flow.to_state, existing_data_flow.to_key)
            from_data_port_existing = self.get_data_port(existing_data_flow.from_state, existing_data_flow.from_key)
            if to_data_port is to_data_port_existing and data_flow is not existing_data_flow:
                if from_data_port is from_data_port_existing:
                    return False, "Exactly the same data flow is already existing -> {0}".format(data_flow)

        return True, "valid"

Response: Checks the validity of the ports of a data flow


Instruction:
Implement a Python 3 function for
checking the validity of the data flow connection

Response:
def _check_data_flow_types(self, check_data_flow):
        """Checks the validity of the data flow connection

        Checks whether the ports of a data flow have matching data types.

        :param rafcon.core.data_flow.DataFlow check_data_flow: The data flow to be checked
        :return bool validity, str message: validity is True, when the data flow is valid, False else. message gives
            more information especially if the data flow is not valid
        """
        # Check whether the data types or origin and target fit
        from_data_port = self.get_data_port(check_data_flow.from_state, check_data_flow.from_key)
        to_data_port = self.get_data_port(check_data_flow.to_state, check_data_flow.to_key)
        # Connections from the data port type "object" are always allowed
        if from_data_port.data_type is object:
            return True, "valid"
        if not type_inherits_of_type(from_data_port.data_type, to_data_port.data_type):
            return False, "Data flow (id: {0}) with origin state \"{1}\" (from data port name: {2}) " \
                          "and target state \"{3}\" (to data port name: {4}) " \
                          "do not have matching data types (from '{5}' to '{6}')".format(
                              check_data_flow.data_flow_id,
                              from_data_port.parent.name,
                              from_data_port.name,
                              to_data_port.parent.name,
                              to_data_port.name,
                              from_data_port.data_type,
                              to_data_port.data_type)
        return True, "valid"


Instruction:
How would you explain what the following Python 3 function does
def _check_transition_validity(self, check_transition):
        valid, message = self._check_transition_id(check_transition)
        if not valid:
            return False, message

        # Separate check for start transitions
        if check_transition.from_state is None:
            return self._check_start_transition(check_transition)

        valid, message = self._check_transition_origin(check_transition)
        if not valid:
            return False, message

        valid, message = self._check_transition_target(check_transition)
        if not valid:
            return False, message

        return self._check_transition_connection(check_transition)

Response: Checks the validity of a transition.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _check_transition_id(self, transition):
        transition_id = transition.transition_id
        if transition_id in self.transitions and transition is not self.transitions[transition_id]:
            return False, "transition_id already existing"
        return True, "valid"

Response: Checks whether the transition id is already used by another transition within the state


Instruction:
Write a Python 3 function that can
check whether the given transition is a start transition

Response:
def _check_start_transition(self, start_transition):
        """Checks the validity of a start transition

        Checks whether the given transition is a start transition a whether it is the only one within the state.

        :param rafcon.core.transition.Transition start_transition: The transition to be checked
        :return bool validity, str message: validity is True, when the transition is valid, False else. message gives
            more information especially if the transition is not valid
        """
        for transition in self.transitions.values():
            if transition.from_state is None:
                if start_transition is not transition:
                    return False, "Only one start transition is allowed"

        if start_transition.from_outcome is not None:
            return False, "from_outcome must not be set in start transition"

        return self._check_transition_target(start_transition)


Instruction:
Implement a function in Python 3 to
check the validity of a transition target

Response:
def _check_transition_target(self, transition):
        """Checks the validity of a transition target

        Checks whether the transition target is valid.

        :param rafcon.core.transition.Transition transition: The transition to be checked
        :return bool validity, str message: validity is True, when the transition is valid, False else. message gives
            more information especially if the transition is not valid
        """

        to_state_id = transition.to_state
        to_outcome_id = transition.to_outcome

        if to_state_id == self.state_id:
            if to_outcome_id not in self.outcomes:
                return False, "to_outcome is not existing"
        else:
            if to_state_id not in self.states:
                return False, "to_state is not existing"
            if to_outcome_id is not None:
                return False, "to_outcome must be None as transition goes to child state"

        return True, "valid"


Instruction:
Implement a function in Python 3 to
check the validity of a transition origin

Response:
def _check_transition_origin(self, transition):
        """Checks the validity of a transition origin

        Checks whether the transition origin is valid.

        :param rafcon.core.transition.Transition transition: The transition to be checked
        :return bool validity, str message: validity is True, when the transition is valid, False else. message gives
            more information especially if the transition is not valid
        """
        from_state_id = transition.from_state
        from_outcome_id = transition.from_outcome

        if from_state_id == self.state_id:
            return False, "from_state_id of transition must not be the container state itself." \
                          " In the case of a start transition both the from state and the from_outcome are None."

        if from_state_id != self.state_id and from_state_id not in self.states:
            return False, "from_state not existing"

        from_outcome = self.get_outcome(from_state_id, from_outcome_id)
        if from_outcome is None:
            return False, "from_outcome not existing in from_state"

        return True, "valid"


Instruction:
How would you code a function in Python 3 to
check the validity of a transition connection

Response:
def _check_transition_connection(self, check_transition):
        """Checks the validity of a transition connection

        Checks whether the transition is allowed to connect the origin with the target.

        :param rafcon.core.transition.Transition check_transition: The transition to be checked
        :return bool validity, str message: validity is True, when the transition is valid, False else. message gives
            more information especially if the transition is not valid
        """
        from_state_id = check_transition.from_state
        from_outcome_id = check_transition.from_outcome
        to_state_id = check_transition.to_state
        to_outcome_id = check_transition.to_outcome

        # check for connected origin
        for transition in self.transitions.values():
            if transition.from_state == from_state_id:
                if transition.from_outcome == from_outcome_id:
                    if check_transition is not transition:
                        return False, "transition origin already connected to another transition"

        if from_state_id in self.states and to_state_id in self.states and to_outcome_id is not None:
            return False, "no transition from one outcome to another one on the same hierarchy allowed"

        return True, "valid"


Instruction:
Can you create a Python 3 function that
returns the numer of child states and the maximal child states.

Response:
def get_states_statistics(self, hierarchy_level):
        """
        Returns the numer of child states
        :return:
        """
        number_of_all_child_states = 0
        max_child_hierarchy_level = 0
        for s in self.states.values():
            child_hierarchy_level = 0
            number_of_child_states, child_hierarchy_level = s.get_states_statistics(child_hierarchy_level)
            number_of_all_child_states += number_of_child_states
            if child_hierarchy_level > max_child_hierarchy_level:
                max_child_hierarchy_level = child_hierarchy_level

        return number_of_all_child_states + 1, hierarchy_level + max_child_hierarchy_level + 1


Instruction:
Write a Python 3 script for
returning the number of child states that are in the same state.

Response:
def get_number_of_transitions(self):
        """
        Returns the numer of child states
        :return:
        """
        number_of_all_transitions = 0
        for s in self.states.values():
            number_of_all_transitions += s.get_number_of_transitions()
        return number_of_all_transitions + len(self.transitions)


Instruction:
Here you have a function in Python 3, explain what it does
def start_state_id(self):
        for transition_id in self.transitions:
            if self.transitions[transition_id].from_state is None:
                to_state = self.transitions[transition_id].to_state
                if to_state is not None:
                    return to_state
                else:
                    return self.state_id
        return None

Response: Returns the id of the first state in which the first transition goes to.


Instruction:
Can you implement a function in Python 3 that
sets the start state of the container state.

Response:
def start_state_id(self, start_state_id, to_outcome=None):
        """Set the start state of the container state

        See property

        :param start_state_id: The state id of the state which should be executed first in the Container state
        :raises exceptions.ValueError: if the start_state_id does not exist in
                                    :py:attr:`rafcon.core.states.container_state.ContainerState.states`
        """
        if start_state_id is not None and start_state_id not in self.states:
            raise ValueError("start_state_id does not exist")

        if start_state_id is None and to_outcome is not None:  # this is the case if the start state is the state itself
            if to_outcome not in self.outcomes:
                raise ValueError("to_outcome does not exist")
            if start_state_id != self.state_id:
                raise ValueError("to_outcome defined but start_state_id is not state_id")

        # First we remove the transition to the start state
        for transition_id in self.transitions:
            if self.transitions[transition_id].from_state is None:
                # If the current start state is the same as the old one, we don't have to do anything
                if self.transitions[transition_id].to_state == start_state_id:
                    return
                self.remove_transition(transition_id)
                break
        if start_state_id is not None:
            self.add_transition(None, None, start_state_id, to_outcome)


Instruction:
Can you generate the documentation for the following Python 3 function
def scoped_variables(self, scoped_variables):
        if not isinstance(scoped_variables, dict):
            raise TypeError("scoped_variables must be of type dict")
        if [sv_id for sv_id, sv in scoped_variables.items() if not isinstance(sv, ScopedVariable)]:
            raise TypeError("element of scope variable must be of type ScopedVariable")
        if [sv_id for sv_id, sv in scoped_variables.items() if not sv_id == sv.data_port_id]:
            raise AttributeError("The key of the scope variable dictionary and "
                                 "the id of the scope variable do not match")

        old_scoped_variables = self._scoped_variables
        self._scoped_variables = scoped_variables
        for port_id, scoped_variable in scoped_variables.items():
            try:
                scoped_variable.parent = self
            except ValueError:
                self._scoped_variables = old_scoped_variables
                raise

        # check that all old_scoped_variables are no more referencing self as there parent
        for old_scoped_variable in old_scoped_variables.values():
            if old_scoped_variable not in self._scoped_variables.values() and old_scoped_variable.parent is self:
                old_scoped_variable.parent = None

Response:
Setter for _scoped_variables field
MimeType


Instruction:
Create a Python 3 function for
calling the custom execute function of the state object and returns the result of the execution.

Response:
def _execute(self, execute_inputs, execute_outputs, backward_execution=False):
        """Calls the custom execute function of the script.py of the state

        """
        self._script.build_module()

        outcome_item = self._script.execute(self, execute_inputs, execute_outputs, backward_execution)

        # in the case of backward execution the outcome is not relevant
        if backward_execution:
            return

        # If the state was preempted, the state must be left on the preempted outcome
        if self.preempted:
            return Outcome(-2, "preempted")

        # Outcome id was returned
        if outcome_item in self.outcomes:
            return self.outcomes[outcome_item]

        # Outcome name was returned
        for outcome_id, outcome in self.outcomes.items():
            if outcome.name == outcome_item:
                return self.outcomes[outcome_id]

        logger.error("Returned outcome of {0} not existing: {1}".format(self, outcome_item))
        return Outcome(-1, "aborted")


Instruction:
Can you generate the documentation for the following Python 3 function
def run(self):
        if self.is_root_state:
            self.execution_history.push_call_history_item(self, CallType.EXECUTE, None, self.input_data)

        logger.debug("Running {0}{1}".format(self, " (backwards)" if self.backward_execution else ""))
        if self.backward_execution:
            self.setup_backward_run()
        else:
            self.setup_run()

        try:
            outcome = self._execute(self.input_data, self.output_data, self.backward_execution)
            self.state_execution_status = StateExecutionStatus.WAIT_FOR_NEXT_STATE

            if self.backward_execution:
                # outcome handling is not required as we are in backward mode and the execution order is fixed
                result = self.finalize()
            else:
                # check output data
                self.check_output_data_type()
                result = self.finalize(outcome)

            if self.is_root_state:
                self.execution_history.push_return_history_item(self, CallType.EXECUTE, None, self.output_data)
            return result
        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            formatted_exc = traceback.format_exception(exc_type, exc_value, exc_traceback)
            truncated_exc = []
            for line in formatted_exc:
                if os.path.join("rafcon", "core") not in line:
                    truncated_exc.append(line)
            logger.error("{0} had an internal error: {1}: {2}\n{3}".format(self, type(e).__name__, e,
                                                                           ''.join(truncated_exc)))
            # write error to the output_data of the state
            self.output_data["error"] = e
            self.state_execution_status = StateExecutionStatus.WAIT_FOR_NEXT_STATE
            return self.finalize(Outcome(-1, "aborted"))

Response: This method executes the state and returns the result of the execution.


Instruction:
Can you generate the documentation for the following Python 3 function
def register_view(self, view):
        super(StateMachineTreeController, self).register_view(view)
        self.view.connect('button_press_event', self.mouse_click)
        self.view_is_registered = True
        self.update(with_expand=True)

Response: Called when the view was registered


Instruction:
Explain what the following Python 3 code does
def register_actions(self, shortcut_manager):
        shortcut_manager.add_callback_for_action("delete", self._delete_selection)
        shortcut_manager.add_callback_for_action("add", partial(self._add_new_state, state_type=StateType.EXECUTION))
        shortcut_manager.add_callback_for_action("add2", partial(self._add_new_state, state_type=StateType.HIERARCHY))
        shortcut_manager.add_callback_for_action("copy", self.copy_action_callback)
        shortcut_manager.add_callback_for_action("cut", self.cut_action_callback)
        shortcut_manager.add_callback_for_action("paste", self.paste_action_callback)

Response: Register callback methods for triggered actions


Instruction:
Given the following Python 3 function, write the documentation
def register(self):
        self._do_selection_update = True
        # relieve old model
        if self.__my_selected_sm_id is not None:  # no old models available
            self.relieve_model(self._selected_sm_model)
        # set own selected state machine id
        self.__my_selected_sm_id = self.model.selected_state_machine_id
        if self.__my_selected_sm_id is not None:
            # observe new model
            self._selected_sm_model = self.model.state_machines[self.__my_selected_sm_id]
            self.observe_model(self._selected_sm_model)  # for selection
            self.update()
        else:
            self._selected_sm_model = None
            self.state_row_iter_dict_by_state_path.clear()
            self.tree_store.clear()
        self._do_selection_update = False

Response: Change the state machine that is observed for new selected states to the selected state machine.


Instruction:
Here you have a function in Python 3, explain what it does
def paste_action_callback(self, *event):
        if react_to_event(self.view, self.tree_view, event):
            sm_selection, _ = self.get_state_machine_selection()
            # only list specific elements are cut by widget
            if len(sm_selection.states) == 1:
                global_clipboard.paste(sm_selection.get_selected_state(), limited=['states', 'transitions', 'data_flows'])
            else:
                logger.warning("Please select only one state to paste.")
            return True

Response: Callback method for paste action


Instruction:
Write a Python 3 script for
triggering when the add new state is clicked.

Response:
def _add_new_state(self, *event, **kwargs):
        """Triggered when shortcut keys for adding a new state are pressed, or Menu Bar "Edit, Add State" is clicked.

        Adds a new state only if the the state machine tree is in focus.
        """
        if react_to_event(self.view, self.view['state_machine_tree_view'], event):
            state_type = StateType.EXECUTION if 'state_type' not in kwargs else kwargs['state_type']
            gui_helper_state_machine.add_new_state(self._selected_sm_model, state_type)
            return True


Instruction:
How would you explain what the following Python 3 function does
def selection_changed(self, widget, event=None):
        # do not forward cursor selection updates if state update is running
        # TODO maybe make this generic for respective abstract controller
        if self._state_which_is_updated:
            return
        super(StateMachineTreeController, self).selection_changed(widget, event)

Response: Notify state machine about tree view selection


Instruction:
Create a Python 3 function for
considering the tree to be collapsed and expand into all tree items with the flag set True

Response:
def redo_expansion_state(self, ignore_not_existing_rows=False):
        """ Considers the tree to be collapsed and expand into all tree item with the flag set True """

        def set_expansion_state(state_path):
            state_row_iter = self.state_row_iter_dict_by_state_path[state_path]
            if state_row_iter:  # may elements are missing afterwards
                state_row_path = self.tree_store.get_path(state_row_iter)
                self.view.expand_to_path(state_row_path)

        if self.__my_selected_sm_id is not None and self.__my_selected_sm_id in self.__expansion_state:
            expansion_state = self.__expansion_state[self.__my_selected_sm_id]
            try:
                for state_path, state_row_expanded in expansion_state.items():
                    if state_path in self.state_row_iter_dict_by_state_path:
                        if state_row_expanded:
                            set_expansion_state(state_path)
                    else:
                        if not ignore_not_existing_rows and self._selected_sm_model and \
                                self._selected_sm_model.state_machine.get_state_by_path(state_path, as_check=True):
                            state = self._selected_sm_model.state_machine.get_state_by_path(state_path)
                            if isinstance(state, LibraryState) or state.is_root_state_of_library or \
                                    state.get_next_upper_library_root_state():
                                continue
                            logger.error("State not in StateMachineTree but in StateMachine, {0}.".format(state_path))

            except (TypeError, KeyError):
                logger.error("Expansion state of state machine {0} could not be restored"
                             "".format(self.__my_selected_sm_id))


Instruction:
Can you generate the documentation for the following Python 3 function
def update(self, changed_state_model=None, with_expand=False):
        if not self.view_is_registered:
            return

        # define initial state-model for update
        if changed_state_model is None:
            # reset all
            parent_row_iter = None
            self.state_row_iter_dict_by_state_path.clear()
            self.tree_store.clear()
            if self._selected_sm_model:
                changed_state_model = self._selected_sm_model.root_state
            else:
                return
        else:  # pick
            if changed_state_model.state.is_root_state:
                parent_row_iter = self.state_row_iter_dict_by_state_path[changed_state_model.state.get_path()]
            else:
                if changed_state_model.state.is_root_state_of_library:
                    # because either lib-state or lib-state-root is in tree the next higher hierarchy state is updated
                    changed_upper_state_m = changed_state_model.parent.parent
                else:
                    changed_upper_state_m = changed_state_model.parent
                # TODO check the work around of the next 2 lines while refactoring -> it is a check to be more robust
                while changed_upper_state_m.state.get_path() not in self.state_row_iter_dict_by_state_path:
                    # show Warning because because avoided method states_update
                    logger.warning("Take a parent state because this is not in.")
                    changed_upper_state_m = changed_upper_state_m.parent
                parent_row_iter = self.state_row_iter_dict_by_state_path[changed_upper_state_m.state.get_path()]

        # do recursive update
        self.insert_and_update_recursively(parent_row_iter, changed_state_model, with_expand)

Response: Updates the state - model of the current state - model with the new state - model of the current state - model.


Instruction:
Given the following Python 3 function, write the documentation
def show_content(self, state_model):
        upper_most_lib_state_m = None
        if isinstance(state_model, LibraryStateModel):
            uppermost_library_root_state = state_model.state.get_uppermost_library_root_state()
            if uppermost_library_root_state is None:
                upper_most_lib_state_m = state_model
            else:
                upper_lib_state = uppermost_library_root_state.parent
                upper_most_lib_state_m = self._selected_sm_model.get_state_model_by_path(upper_lib_state.get_path())
        if upper_most_lib_state_m:
            return upper_most_lib_state_m.show_content()
        else:
            return True

Response: Check if the state machine tree specific show content flag is set.


Instruction:
Can you write a function in Python 3 where it
inserts and update the handed state model in the tree store element iteratorparent_iter.

Response:
def insert_and_update_recursively(self, parent_iter, state_model, with_expand=False):
        """ Insert and/or update the handed state model in parent tree store element iterator

        :param parent_iter: Parent tree store iterator the insert should be performed in
        :param StateModel state_model: Model of state that has to be insert and/or updated
        :param bool with_expand: Trigger to expand tree
        :return:
        """
        # the case handling of this method
        # 0 - create - common state
        # 0.1 - modify attributes of common state which is already in the list
        # 1 - create - library with show content -> add library root state
        # 2 - create - library without show content -> add library state
        # 3 - in as library with show content -> switch library without show content, remove children + LibRootState
        # 3.1 - in as library with show content -> nothing to do
        # 4 - in as library without show content -> switch library with show content, add children + remove LibState
        # 4.1 - in as library without show content -> nothing to do

        # if state model is LibraryStateModel with enabled show content state_model becomes the library root state model
        if isinstance(state_model, LibraryStateModel) and self.show_content(state_model) and state_model.state_copy_initialized:
            _state_model = state_model
            state_model = state_model.state_copy
        else:
            _state_model = state_model

        if self._state_which_is_updated is None:
            self._state_which_is_updated = _state_model

        # TODO remove this workaround for removing LibraryStateModel or there root states by default
        if isinstance(_state_model, LibraryStateModel) and _state_model.state_copy_initialized:
            state_row_iter = None
            if _state_model.state.get_path() in self.state_row_iter_dict_by_state_path:
                state_row_iter = self.state_row_iter_dict_by_state_path[_state_model.state.get_path()]
            if state_model.state.get_path() in self.state_row_iter_dict_by_state_path:
                state_row_iter = self.state_row_iter_dict_by_state_path[state_model.state.get_path()]

            if state_row_iter:
                self.remove_tree_children(state_row_iter)
                del self.state_row_iter_dict_by_state_path[self.tree_store.get_value(state_row_iter, self.STATE_PATH_STORAGE_ID)]
                self.tree_store.remove(state_row_iter)

        # if library root state is used instate of library state show both in type and state id
        _state_id = _state_model.state.state_id
        # _state_id += '' if _state_model is state_model else '/' + state_model.state.state_id  TODO enable this line
        _state_type = type(_state_model.state).__name__
        _state_type += '' if _state_model is state_model else '/' + type(state_model.state).__name__

        # check if in
        state_path = state_model.state.get_path()
        if state_path not in self.state_row_iter_dict_by_state_path:
            # if not in -> insert it
            state_row_iter = self.tree_store.insert_before(parent=parent_iter, sibling=None,
                                                           row=(state_model.state.name,
                                                                _state_id,
                                                                _state_type,
                                                                _state_model,
                                                                state_model.state.get_path()))
            self.state_row_iter_dict_by_state_path[state_path] = state_row_iter
            if with_expand:
                parent_path = self.tree_store.get_path(state_row_iter)
                self.view.expand_to_path(parent_path)
        else:
            # if in -> check if up to date
            state_row_iter = self.state_row_iter_dict_by_state_path[state_model.state.get_path()]
            self.update_tree_store_row(state_model)

        # check children
        # - check if ALL children are in
        if isinstance(state_model, ContainerStateModel):
            for child_state_id, child_state_model in state_model.states.items():
                self.insert_and_update_recursively(state_row_iter, child_state_model, with_expand=False)

        # - check if TOO MUCH children are in
        # if state_model.state.get_library_root_state() is not None or isinstance(state_model, LibraryStateModel):
        for n in reversed(range(self.tree_store.iter_n_children(state_row_iter))):
            child_iter = self.tree_store.iter_nth_child(state_row_iter, n)
            child_state_path = self.tree_store.get_value(child_iter, self.STATE_PATH_STORAGE_ID)
            child_model = None
            if self._selected_sm_model.state_machine.get_state_by_path(child_state_path, as_check=True):
                child_model = self._selected_sm_model.get_state_model_by_path(child_state_path)
            child_id = self.tree_store.get_value(child_iter, self.ID_STORAGE_ID)

            # check if there are left over rows of old states (switch from HS or CS to S and so on)
            show_content_flag = isinstance(child_model, LibraryStateModel) and self.show_content(child_model) and \
                                child_model.state_copy_initialized
            child_is_lib_with_show_content = isinstance(child_model, LibraryStateModel) and show_content_flag
            child_is_lib_without_show_content = isinstance(child_model, LibraryStateModel) and not show_content_flag

            if not isinstance(state_model, ContainerStateModel) or child_model is None or \
                    child_id not in state_model.states and not child_is_lib_with_show_content \
                    and isinstance(child_model, LibraryStateModel) and child_id == child_model.state.state_copy.state_id \
                    or child_is_lib_without_show_content and child_id == child_model.state.state_copy.state_id or \
                    isinstance(_state_model, LibraryStateModel) and not self.show_content(_state_model) or \
                    child_model.state.is_root_state_of_library and not self.show_content(child_model.parent):

                self.remove_tree_children(child_iter)
                del self.state_row_iter_dict_by_state_path[self.tree_store.get_value(child_iter, self.STATE_PATH_STORAGE_ID)]
                self.tree_store.remove(child_iter)

        if self._state_which_is_updated is _state_model:
            self._state_which_is_updated = None


Instruction:
Can you generate the documentation for the following Python 3 function
def get_state_machine_selection(self):
        if self._selected_sm_model:
            return self._selected_sm_model.selection, self._selected_sm_model.selection.states
        else:
            return None, set()

Response: Getter state machine selection


Instruction:
Write a Python 3 script to
double click event handler

Response:
def _handle_double_click(self, event):
        """ Double click with left mouse button focuses the state and toggles the collapse status"""
        if event.get_button()[1] == 1:  # Left mouse button
            path_info = self.tree_view.get_path_at_pos(int(event.x), int(event.y))
            if path_info:  # Valid entry was clicked on
                path = path_info[0]
                iter = self.tree_store.get_iter(path)
                state_model = self.tree_store.get_value(iter, self.MODEL_STORAGE_ID)

                # Set focus to StateModel
                selection = self._selected_sm_model.selection
                selection.focus = state_model

                # Toggle collapse status if applicable for this kind of state
                if self.view.row_expanded(path):
                    self.view.collapse_row(path)
                else:
                    if isinstance(state_model, ContainerStateModel) or \
                                    isinstance(state_model, LibraryStateModel) and self.show_content(state_model):
                        self.view.expand_to_path(path)


Instruction:
Implement a Python 3 function for
executing the user execute function specified in the script

Response:
def execute(self, state, inputs=None, outputs=None, backward_execution=False):
        """Execute the user 'execute' function specified in the script

        :param ExecutionState state: the state belonging to the execute function, refers to 'self'
        :param dict inputs: the input data of the script
        :param dict outputs: the output data of the script
        :param bool backward_execution: Flag whether to run the script in backwards mode
        :return: Return value of the execute script
        :rtype: str | int
        """
        if not outputs:
            outputs = {}
        if not inputs:
            inputs = {}
        if backward_execution:
            if hasattr(self._compiled_module, "backward_execute"):
                return self._compiled_module.backward_execute(
                    state, inputs, outputs, rafcon.core.singleton.global_variable_manager
                )
            else:
                logger.debug("No backward execution method found for state %s" % state.name)
                return None
        else:
            return self._compiled_module.execute(state, inputs, outputs,
                                                 rafcon.core.singleton.global_variable_manager)


Instruction:
Write a Python 3 function for
loading the script from the filesystem

Response:
def _load_script(self):
        """Loads the script from the filesystem

        :raises exceptions.IOError: if the script file could not be opened
        """
        script_text = filesystem.read_file(self.path, self.filename)

        if not script_text:
            raise IOError("Script file could not be opened or was empty: {0}"
                          "".format(os.path.join(self.path, self.filename)))
        self.script = script_text


Instruction:
Write a Python 3 script for
building a temporary module from the script file and returns the module object.

Response:
def build_module(self):
        """Builds a temporary module from the script file

        :raises exceptions.IOError: if the compilation of the script module failed
        """
        try:
            imp.acquire_lock()
            module_name = os.path.splitext(self.filename)[0] + str(self._script_id)

            # load module
            tmp_module = imp.new_module(module_name)

            code = compile(self.script, '%s (%s)' % (self.filename, self._script_id), 'exec')

            try:
                exec(code, tmp_module.__dict__)
            except RuntimeError as e:
                raise IOError("The compilation of the script module failed - error message: %s" % str(e))

            # return the module
            self.compiled_module = tmp_module
        finally:
            imp.release_lock()


Instruction:
Implement a function in Python 3 to
call when the View was registered

Response:
def register_view(self, view):
        """Called when the View was registered"""
        super(MenuBarController, self).register_view(view)
        data_flow_mode = global_runtime_config.get_config_value("DATA_FLOW_MODE", False)
        view["data_flow_mode"].set_active(data_flow_mode)

        show_data_flows = global_runtime_config.get_config_value("SHOW_DATA_FLOWS", True)
        view["show_data_flows"].set_active(show_data_flows)

        show_data_values = global_runtime_config.get_config_value("SHOW_DATA_FLOW_VALUE_LABELS", True)
        view["show_data_values"].set_active(show_data_values)

        show_aborted_preempted = global_runtime_config.get_config_value("SHOW_ABORTED_PREEMPTED", False)
        view["show_aborted_preempted"].set_active(show_aborted_preempted)

        view["expert_view"].hide()
        view["grid"].hide()

        # use dedicated function to connect the buttons to be able to access the handler id later on
        self.connect_button_to_function('new', 'activate', self.on_new_activate)
        self.connect_button_to_function('open', 'activate', self.on_open_activate)
        self.connect_button_to_function('save', 'activate', self.on_save_activate)
        self.connect_button_to_function('save_as', 'activate', self.on_save_as_activate)
        self.connect_button_to_function('save_as_copy', 'activate', self.on_save_as_copy_activate)
        self.connect_button_to_function('menu_preferences', 'activate', self.on_menu_preferences_activate)
        self.connect_button_to_function('refresh_all', 'activate', self.on_refresh_all_activate)
        self.connect_button_to_function('refresh_libraries', 'activate', self.on_refresh_libraries_activate)
        self.connect_button_to_function('bake_state_machine', 'activate', self.on_bake_state_machine_activate)
        self.connect_button_to_function('quit', 'activate', self.on_quit_activate)

        self.connect_button_to_function('cut', 'activate', self.on_cut_selection_activate)
        self.connect_button_to_function('copy', 'activate', self.on_copy_selection_activate)
        self.connect_button_to_function('paste', 'activate', self.on_paste_clipboard_activate)
        self.connect_button_to_function('delete', 'activate', self.on_delete_activate)
        self.connect_button_to_function('is_start_state', 'activate', self.on_toggle_is_start_state_active)
        self.connect_button_to_function('add', 'activate', self.on_add_state_activate)
        self.connect_button_to_function('group', 'activate', self.on_group_states_activate)
        self.connect_button_to_function('ungroup', 'activate', self.on_ungroup_state_activate)
        self.connect_button_to_function('substitute_state', 'activate', self.on_substitute_selected_state_activate)
        self.connect_button_to_function('save_state_as', 'activate', self.on_save_selected_state_as_activate)
        self.connect_button_to_function('undo', 'activate', self.on_undo_activate)
        self.connect_button_to_function('redo', 'activate', self.on_redo_activate)
        self.connect_button_to_function('grid', 'activate', self.on_grid_toggled)

        self.connect_button_to_function('data_flow_mode', 'toggled', self.on_data_flow_mode_toggled)
        self.connect_button_to_function('show_data_flows', 'toggled', self.on_show_data_flows_toggled)
        self.connect_button_to_function('show_data_values', 'toggled', self.on_show_data_values_toggled)
        self.connect_button_to_function('show_aborted_preempted', 'toggled', self.on_show_aborted_preempted_toggled)
        self.connect_button_to_function('expert_view', 'activate', self.on_expert_view_activate)
        self.connect_button_to_function('full_screen', 'toggled', self.on_full_screen_mode_toggled)

        self.connect_button_to_function('start', 'activate', self.on_start_activate)
        self.connect_button_to_function('start_from_selected', 'activate', self.on_start_from_selected_state_activate)
        self.connect_button_to_function('run_to_selected', 'activate', self.on_run_to_selected_state_activate)
        self.connect_button_to_function('pause', 'activate', self.on_pause_activate)
        self.connect_button_to_function('stop', 'activate', self.on_stop_activate)
        self.connect_button_to_function('step_mode', 'activate', self.on_step_mode_activate)
        self.connect_button_to_function('step_into', 'activate', self.on_step_into_activate)
        self.connect_button_to_function('step_over', 'activate', self.on_step_over_activate)
        self.connect_button_to_function('step_out', 'activate', self.on_step_out_activate)
        self.connect_button_to_function('backward_step', 'activate', self.on_backward_step_activate)
        self.connect_button_to_function('about', 'activate', self.on_about_activate)
        self.full_screen_window.connect('key_press_event', self.on_escape_key_press_event_leave_full_screen)
        self.view['menu_edit'].connect('select', self.check_edit_menu_items_status)
        self.registered_view = True
        self._update_recently_opened_state_machines()
        # do not move next line - here to show warning in GUI debug console
        self.create_logger_warning_if_shortcuts_are_overwritten_by_menu_bar()


Instruction:
Make a summary of the following Python 3 code
def on_config_value_changed(self, config_m, prop_name, info):
        config_key = info['args'][1]
        # config_value = info['args'][2]

        if config_key == "LIBRARY_PATHS":
            library_manager.refresh_libraries()
        elif config_key == "SHORTCUTS":
            self.refresh_shortcuts()
        elif config_key == "recently_opened_state_machines":
            self._update_recently_opened_state_machines()

Response: Callback when a config value has been changed


Instruction:
Can you generate the documentation for the following Python 3 function
def _update_recently_opened_state_machines(self):
        if not self.registered_view:
            return

        for item in self.view.sub_menu_open_recently.get_children():
            self.view.sub_menu_open_recently.remove(item)

        menu_item = gui_helper_label.create_menu_item("remove invalid paths", constants.ICON_ERASE,
                                                      global_runtime_config.clean_recently_opened_state_machines)
        self.view.sub_menu_open_recently.append(menu_item)
        self.view.sub_menu_open_recently.append(Gtk.SeparatorMenuItem())

        for sm_path in global_runtime_config.get_config_value("recently_opened_state_machines", []):
            # define label string
            root_state_name = gui_helper_state_machine.get_root_state_name_of_sm_file_system_path(sm_path)
            if root_state_name is None and not os.path.isdir(sm_path):
                root_state_name = 'NOT_ACCESSIBLE'
            label_string = "'{0}' in {1}".format(root_state_name, sm_path) if root_state_name is not None else sm_path

            # define icon of menu item
            is_in_libs = library_manager.is_os_path_within_library_root_paths(sm_path)
            button_image = constants.SIGN_LIB if is_in_libs else constants.BUTTON_OPEN

            # prepare state machine open call_back function
            sm_open_function = partial(self.on_open_activate, path=sm_path)

            # create and insert new menu item
            menu_item = gui_helper_label.create_menu_item(label_string, button_image, sm_open_function)
            self.view.sub_menu_open_recently.append(menu_item)

        self.view.sub_menu_open_recently.show_all()

Response: Method update the recent opened state machines list.


Instruction:
Here you have a function in Python 3, explain what it does
def on_full_screen_activate(self, *args):
        self.sm_notebook.set_show_tabs(False)
        self.main_window_view['graphical_editor_vbox'].remove(self.sm_notebook)
        self.full_screen_window.add(self.sm_notebook)
        position = self.main_window_view.get_top_widget().get_position()
        self.full_screen_window.show()
        self.full_screen_window.move(position[0], position[1])
        self.full_screen_window.set_decorated(False)
        self.full_screen_window.fullscreen()
        self.main_window_view.get_top_widget().iconify()

Response: Function to display the currently selected state machine in full screen mode


Instruction:
Make a summary of the following Python 3 code
def unregister_view(self):
        for handler_id in self.handler_ids.keys():
            self.view[handler_id].disconnect(self.handler_ids[handler_id])

Response: Unregister all registered functions to a view element


Instruction:
Can you implement a function in Python 3 that
registers callback methods for triggered actions in the given shortcuts.

Response:
def register_actions(self, shortcut_manager):
        """Register callback methods for triggered actions

        :param rafcon.gui.shortcut_manager.ShortcutManager shortcut_manager: Shortcut Manager Object holding mappings
            between shortcuts and actions.
        """
        self.add_callback_to_shortcut_manager('save', partial(self.call_action_callback, "on_save_activate"))
        self.add_callback_to_shortcut_manager('save_as', partial(self.call_action_callback, "on_save_as_activate"))
        self.add_callback_to_shortcut_manager('save_as_copy', partial(self.call_action_callback,
                                                                      "on_save_as_copy_activate"))
        self.add_callback_to_shortcut_manager('save_state_as', partial(self.call_action_callback,
                                                                       "on_save_selected_state_as_activate"))
        self.add_callback_to_shortcut_manager('substitute_state', partial(self.call_action_callback,
                                                                          "on_substitute_selected_state_activate"))
        self.add_callback_to_shortcut_manager('substitute_library_with_template',
                                              partial(self.call_action_callback,
                                                      "on_substitute_library_with_template_activate"))
        self.add_callback_to_shortcut_manager('open', partial(self.call_action_callback, "on_open_activate"))
        self.add_callback_to_shortcut_manager('open_library_state_separately',
                                              self.on_open_library_state_separately_activate)
        self.add_callback_to_shortcut_manager('new', partial(self.call_action_callback, "on_new_activate"))
        self.add_callback_to_shortcut_manager('quit', partial(self.call_action_callback, "on_quit_activate"))

        self.add_callback_to_shortcut_manager('is_start_state', partial(self.call_action_callback,
                                                                        "on_toggle_is_start_state_active"))
        callback_function = partial(self.call_action_callback, "on_add_transitions_from_closest_sibling_state_active")
        self.add_callback_to_shortcut_manager('transition_from_closest_sibling_state', callback_function)
        callback_function = partial(self.call_action_callback, "on_add_transitions_to_closest_sibling_state_active")
        self.add_callback_to_shortcut_manager('transition_to_closest_sibling_state', callback_function)
        callback_function = partial(self.call_action_callback, "on_add_transitions_to_parent_state_active")
        self.add_callback_to_shortcut_manager('transition_to_parent_state', callback_function)
        self.add_callback_to_shortcut_manager('group', partial(self.call_action_callback, "on_group_states_activate"))
        self.add_callback_to_shortcut_manager('ungroup', partial(self.call_action_callback,
                                                                 "on_ungroup_state_activate"))

        self.add_callback_to_shortcut_manager('start', partial(self.call_action_callback, "on_start_activate"))
        self.add_callback_to_shortcut_manager('start_from_selected', partial(self.call_action_callback,
                                                                             "on_start_from_selected_state_activate"))
        self.add_callback_to_shortcut_manager('run_to_selected', partial(self.call_action_callback,
                                                                         "on_run_to_selected_state_activate"))

        self.add_callback_to_shortcut_manager('stop', partial(self.call_action_callback, "on_stop_activate"))
        self.add_callback_to_shortcut_manager('pause', partial(self.call_action_callback, "on_pause_activate"))
        self.add_callback_to_shortcut_manager('step_mode', partial(self.call_action_callback, "on_step_mode_activate"))
        self.add_callback_to_shortcut_manager('step', partial(self.call_action_callback, "on_step_into_activate"))
        self.add_callback_to_shortcut_manager('backward_step', partial(self.call_action_callback,
                                                                       "on_backward_step_activate"))

        self.add_callback_to_shortcut_manager('reload', partial(self.call_action_callback, "on_refresh_all_activate"))

        self.add_callback_to_shortcut_manager('show_data_flows', self.show_data_flows_toggled_shortcut)
        self.add_callback_to_shortcut_manager('show_data_values', self.show_data_values_toggled_shortcut)
        self.add_callback_to_shortcut_manager('data_flow_mode', self.data_flow_mode_toggled_shortcut)
        self.add_callback_to_shortcut_manager('show_aborted_preempted', self.show_aborted_preempted)

        self.add_callback_to_shortcut_manager('fullscreen', self.on_toggle_full_screen_mode)


Instruction:
Explain what the following Python 3 code does
def add_callback_to_shortcut_manager(self, action, callback):
        if action not in self.registered_shortcut_callbacks:
            self.registered_shortcut_callbacks[action] = []
        self.registered_shortcut_callbacks[action].append(callback)
        self.shortcut_manager.add_callback_for_action(action, callback)

Response: Helper function to add a callback to the shortcut manager.


Instruction:
Can you write a function in Python 3 where it
removes all callbacks registered to the shortcut manager.

Response:
def remove_all_callbacks(self):
        """
        Remove all callbacks registered to the shortcut manager
        :return:
        """
        for action in self.registered_shortcut_callbacks.keys():
            for callback in self.registered_shortcut_callbacks[action]:
                self.shortcut_manager.remove_callback_for_action(action, callback)
        # delete all registered shortcut callbacks
        self.registered_shortcut_callbacks = {}


Instruction:
Can you generate the documentation for the following Python 3 function
def point_left_of_line(point, line_start, line_end):
    # determine sign of determinant
    # ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0
    return ((line_end[0] - line_start[0]) * (point[1] - line_start[1]) -
            (line_end[1] - line_start[1]) * (point[0] - line_start[0])) < 0

Response: Determines if a point is left of a line in a line in a Knockout system.


Instruction:
Can you implement a function in Python 3 that
checks whether a point lies on a line in a

Response:
def point_on_line(point, line_start, line_end, accuracy=50.):
    """Checks whether a point lies on a line

    The function checks whether the point "point" (P) lies on the line defined by its starting point line_start (A) and
    its end point line_end (B).
    This is done by comparing the distance of [AB] with the sum of the distances [AP] and [PB]. If the difference is
    smaller than [AB] / accuracy, the point P is assumed to be on the line. By increasing the value of accuracy (the
    default is 50), the tolerance is decreased.
    :param point: Point to be checked (tuple with x any y coordinate)
    :param line_start: Starting point of the line (tuple with x any y coordinate)
    :param line_end: End point of the line (tuple with x any y coordinate)
    :param accuracy: The higher this value, the less distance is tolerated
    :return: True if the point is one the line, False if not
    """
    length = dist(line_start, line_end)
    ds = length / float(accuracy)
    if -ds < (dist(line_start, point) + dist(point, line_end) - length) < ds:
        return True

    return False


Instruction:
Can you write a function in Python 3 where it
checks whether a point p is within the given triangle

Response:
def point_in_triangle(p, v1, v2, v3):
    """Checks whether a point is within the given triangle

    The function checks, whether the given point p is within the triangle defined by the the three corner point v1,
    v2 and v3.
    This is done by checking whether the point is on all three half-planes defined by the three edges of the triangle.
    :param p: The point to be checked (tuple with x any y coordinate)
    :param v1: First vertex of the triangle (tuple with x any y coordinate)
    :param v2: Second vertex of the triangle (tuple with x any y coordinate)
    :param v3: Third vertex of the triangle (tuple with x any y coordinate)
    :return: True if the point is within the triangle, False if not
    """
    def _test(p1, p2, p3):
        return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1])

    b1 = _test(p, v1, v2) < 0.0
    b2 = _test(p, v2, v3) < 0.0
    b3 = _test(p, v3, v1) < 0.0

    return (b1 == b2) and (b2 == b3)


Instruction:
Given the following Python 3 function, write the documentation
def equal(t1, t2, digit=None):

    if not len(t1) == len(t2):
        return False

    for idx in range(len(t1)):
        if digit is not None:
            if not round(t1[idx], digit) == round(t2[idx], digit):
                return False
        else:
            if not t1[idx] == t2[idx]:
                return False

    return True

Response: Compare two iterators and their elements on specific digit precision


Instruction:
Can you generate a brief explanation for the following Python 3 code
def cal_dist_between_2_coord_frame_aligned_boxes(box1_pos, box1_size, box2_pos, box2_size):
    box1_x_min, box1_y_min = box1_pos
    box1_x_max, box1_y_max = (box1_pos[0] + box1_size[0], box1_pos[1] + box1_size[1])
    box2_x_min, box2_y_min = box2_pos
    box2_x_max, box2_y_max = (box2_pos[0] + box2_size[0], box2_pos[1] + box2_size[1])

    # 1|2|3                              +-> x    => works also for opengl - both boxes described in same coordinates
    # 4|5|6  -> 5 is covered by  box1    |
    # 7|8|9                             \/ y
    # - case 1 the right lower corner of box2 is above and left to box1 upper left corner
    # - case 5 is when the boxes are overlapping so the distance is 0
    # - in case 1, 3, 7, 9 respective corners of box1 to box2 are the minimal distance
    # - 2, 4, 6, 8 can be covered by either simply calculation via either x or y axis
    if box2_x_max < box1_x_min and box2_y_max < box1_y_min:  # case 1 -> box2 is fully in sector 1
        distance = sqrt((box1_x_min - box2_x_max)**2 + (box1_y_min - box2_y_max)**2)
    elif box2_x_min > box1_x_max and box2_y_max < box1_y_min:  # case 3 -> box2 is fully in sector 3
        distance = sqrt((box2_x_min - box1_x_max)**2 + (box1_y_min - box2_y_max)**2)
    elif box2_x_max < box1_x_min and box2_y_min > box1_y_max:  # case 7 -> box2 is fully in sector 7
        distance = sqrt((box1_x_min - box2_x_max)**2 + (box2_y_min - box1_y_max)**2)
    elif box2_x_min > box1_x_max and box2_y_min > box1_y_max:  # case 9 -> box2 is fully in sector 9
        distance = sqrt((box2_x_min - box1_x_max)**2 + (box2_y_min - box1_y_max)**2)
    elif box2_y_max < box1_y_min:  # case 2 -> box2 is party in sector 2 and in 1 or 3
        distance = box1_y_min - box2_y_max
    elif box2_x_max < box1_x_min:  # case 4 -> box2 is party in sector 4 and in 1 or 7
        distance = box1_x_min - box2_x_max
    elif box2_x_min > box1_x_max:  # case 6 -> box2 is party in sector 6 and in 3 or 9
        distance = box2_x_min - box1_x_max
    elif box2_y_min > box1_y_max:  # case 8 -> box2 is party in sector 8 and in 7 or 9
        distance = box2_y_min - box1_y_max
    else:  # case 5 box2 reach into area of box1
        distance = 0.

    return distance

Response: Calculates the Euclidean distance between two boxes that are parallel to the coordinate axis.


Instruction:
How would you implement a function in Python 3 that
triggers when mouse click is pressed in the history tree.

Response:
def mouse_click(self, widget, event=None):
        """Triggered when mouse click is pressed in the history tree. The method shows all scoped data for an execution
        step as tooltip or fold and unfold the tree by double-click and select respective state for double clicked
        element.
        """
        if event.type == Gdk.EventType._2BUTTON_PRESS and event.get_button()[1] == 1:

            (model, row) = self.history_tree.get_selection().get_selected()
            if row is not None:
                histroy_item_path = self.history_tree_store.get_path(row)
                histroy_item_iter = self.history_tree_store.get_iter(histroy_item_path)
                # logger.info(history_item.state_reference)
                # TODO generalize double-click folding and unfolding -> also used in states tree of state machine
                if histroy_item_path is not None and self.history_tree_store.iter_n_children(histroy_item_iter):
                    if self.history_tree.row_expanded(histroy_item_path):
                        self.history_tree.collapse_row(histroy_item_path)
                    else:
                        self.history_tree.expand_to_path(histroy_item_path)
                sm = self.get_history_item_for_tree_iter(histroy_item_iter).state_reference.get_state_machine()
                if sm:
                    if sm.state_machine_id != self.model.selected_state_machine_id:
                        self.model.selected_state_machine_id = sm.state_machine_id
                else:
                    logger.info("No state machine could be found for selected item's state reference and "
                                "therefore no selection is performed.")
                    return
                active_sm_m = self.model.get_selected_state_machine_model()
                assert active_sm_m.state_machine is sm
                state_path = self.get_history_item_for_tree_iter(histroy_item_iter).state_reference.get_path()
                ref_state_m = active_sm_m.get_state_model_by_path(state_path)
                if ref_state_m and active_sm_m:
                    active_sm_m.selection.set(ref_state_m)

            return True

        if event.type == Gdk.EventType.BUTTON_PRESS and event.get_button()[1] == 2:
            x = int(event.x)
            y = int(event.y)
            pthinfo = self.history_tree.get_path_at_pos(x, y)
            if pthinfo is not None:
                path, col, cellx, celly = pthinfo
                self.history_tree.grab_focus()
                self.history_tree.set_cursor(path, col, 0)
                self.open_selected_history_separately(None)

        if event.type == Gdk.EventType.BUTTON_PRESS and event.get_button()[1] == 3:
            x = int(event.x)
            y = int(event.y)
            time = event.time
            pthinfo = self.history_tree.get_path_at_pos(x, y)
            if pthinfo is not None:
                path, col, cellx, celly = pthinfo
                self.history_tree.grab_focus()
                self.history_tree.set_cursor(path, col, 0)

                popup_menu = Gtk.Menu()

                model, row = self.history_tree.get_selection().get_selected()
                history_item = model[row][self.HISTORY_ITEM_STORAGE_ID]
                if not isinstance(history_item, ScopedDataItem) or history_item.scoped_data is None:
                    return
                scoped_data = history_item.scoped_data
                input_output_data = history_item.child_state_input_output_data
                state_reference = history_item.state_reference

                self.append_string_to_menu(popup_menu, "------------------------")
                self.append_string_to_menu(popup_menu, "Scoped Data: ")
                self.append_string_to_menu(popup_menu, "------------------------")
                for key, data in scoped_data.items():
                    menu_item_string = "    %s (%s - %s):\t%s" % (
                        data.name.replace("_", "__"), key, data.value_type, data.value)
                    self.append_string_to_menu(popup_menu, menu_item_string)

                if input_output_data:
                    if isinstance(history_item, CallItem):
                        self.append_string_to_menu(popup_menu, "------------------------")
                        self.append_string_to_menu(popup_menu, "Input Data:")
                        self.append_string_to_menu(popup_menu, "------------------------")
                    else:
                        self.append_string_to_menu(popup_menu, "------------------------")
                        self.append_string_to_menu(popup_menu, "Output Data:")
                        self.append_string_to_menu(popup_menu, "------------------------")

                    for key, data in input_output_data.items():
                        menu_item_string = "    %s :\t%s" % (key.replace("_", "__"), data)
                        self.append_string_to_menu(popup_menu, menu_item_string)

                if state_reference:
                    if history_item.outcome:
                        self.append_string_to_menu(popup_menu, "------------------------")
                        final_outcome_menu_item_string = "Final outcome: " + str(history_item.outcome)
                        self.append_string_to_menu(popup_menu, final_outcome_menu_item_string)
                        self.append_string_to_menu(popup_menu, "------------------------")

                popup_menu.show()
                popup_menu.popup(None, None, None, None, event.get_button()[1], time)

            return True


Instruction:
Can you write a function in Python 3 where it
hands history item for tree iter and compensate if tree item is a dummy item

Response:
def get_history_item_for_tree_iter(self, child_tree_iter):
        """Hands history item for tree iter and compensate if tree item is a dummy item

        :param Gtk.TreeIter child_tree_iter: Tree iter of row
        :rtype rafcon.core.execution.execution_history.HistoryItem:
        :return history tree item:
        """
        history_item = self.history_tree_store[child_tree_iter][self.HISTORY_ITEM_STORAGE_ID]
        if history_item is None:  # is dummy item
            if self.history_tree_store.iter_n_children(child_tree_iter) > 0:
                child_iter = self.history_tree_store.iter_nth_child(child_tree_iter, 0)
                history_item = self.history_tree_store[child_iter][self.HISTORY_ITEM_STORAGE_ID]
            else:
                logger.debug("In a dummy history should be respective real call element.")
        return history_item


Instruction:
Can you tell what is the following Python 3 function doing
def _store_expansion_state(self):

        def store_tree_expansion(child_tree_iter, expansion_state):

            tree_item_path = self.history_tree_store.get_path(child_tree_iter)
            history_item = self.get_history_item_for_tree_iter(child_tree_iter)

            # store expansion state if tree item path is valid and expansion state was not stored already
            if tree_item_path is not None:
                # if first element of sub-tree has same history_item as the parent ignore it's expansion state
                if history_item not in expansion_state:
                    expansion_state[history_item] = self.history_tree.row_expanded(tree_item_path)

            for n in range(self.history_tree_store.iter_n_children(child_tree_iter)):
                child_iter = self.history_tree_store.iter_nth_child(child_tree_iter, n)
                store_tree_expansion(child_iter, expansion_state)

        root_iter = self.history_tree_store.get_iter_first()
        if not root_iter:
            return
        current_expansion_state = {}
        # this can be the case when the execution history tree is currently being deleted
        if not self.get_history_item_for_tree_iter(root_iter).state_reference:
            return
        state_machine = self.get_history_item_for_tree_iter(root_iter).state_reference.get_state_machine()
        self._expansion_state[state_machine.state_machine_id] = current_expansion_state
        while root_iter:
            store_tree_expansion(root_iter, current_expansion_state)
            root_iter = self.history_tree_store.iter_next(root_iter)

Response: Iterate recursively all tree items and store expansion state


Instruction:
Explain what the following Python 3 code does
def _restore_expansion_state(self):

        def restore_tree_expansion(child_tree_iter, expansion_state):
            tree_item_path = self.history_tree_store.get_path(child_tree_iter)
            history_item = self.get_history_item_for_tree_iter(child_tree_iter)

            # restore expansion state if tree item path is valid and expansion state was not stored already
            if tree_item_path and history_item in expansion_state:
                if expansion_state[history_item]:
                    self.history_tree.expand_to_path(tree_item_path)

            for n in range(self.history_tree_store.iter_n_children(child_tree_iter)):
                child_iter = self.history_tree_store.iter_nth_child(child_tree_iter, n)
                restore_tree_expansion(child_iter, expansion_state)

        root_iter = self.history_tree_store.get_iter_first()
        if not root_iter:
            return
        state_machine = self.get_history_item_for_tree_iter(root_iter).state_reference.get_state_machine()
        if state_machine.state_machine_id not in self._expansion_state:
            return
        while root_iter:
            restore_tree_expansion(root_iter, self._expansion_state[state_machine.state_machine_id])
            root_iter = self.history_tree_store.iter_next(root_iter)

Response: Iterate recursively all tree items and restore expansion state


Instruction:
Explain what the following Python 3 code does
def notification_selected_sm_changed(self, model, prop_name, info):
        selected_state_machine_id = self.model.selected_state_machine_id
        if selected_state_machine_id is None:
            return
        self.update()

Response: If a new state machine is selected make sure expansion state is stored and tree updated


Instruction:
Given the following Python 3 function, write the documentation
def notification_sm_changed(self, model, prop_name, info):
        for state_machine_id in list(self._expansion_state.keys()):
            if state_machine_id not in self.model.state_machines:
                del self._expansion_state[state_machine_id]

Response: Remove references to non - existing state machines