def _execute(self, execute_inputs, execute_outputs, backward_execution=False): """Calls the custom execute function of the script.py of the state""" plugins.run_hook('pre_script') outcome_item = self._script.execute(self, execute_inputs, execute_outputs, backward_execution) plugins.run_hook('post_script') # 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")
def signal_handler(signal, frame): global _user_abort state_machine_execution_engine = core_singletons.state_machine_execution_engine core_singletons.shut_down_signal = signal logger.info("Shutting down ...") try: if not state_machine_execution_engine.finished_or_stopped(): state_machine_execution_engine.stop() state_machine_execution_engine.join( 3) # Wait max 3 sec for the execution to stop except Exception: logger.exception("Could not stop state machine") _user_abort = True # shutdown twisted correctly if reactor_required(): from twisted.internet import reactor if reactor.running: plugins.run_hook("pre_destruction") reactor.callFromThread(reactor.stop) logging.shutdown()
def prepare_destruction(self): """Saves current configuration of windows and panes to the runtime config file, before RAFCON is closed.""" plugins.run_hook("pre_destruction") logger.debug("Saving runtime config to {0}".format( global_runtime_config.config_file_path)) # store pane last positions for key, widget_name in constants.PANE_ID.items(): global_runtime_config.store_widget_properties( self.view[widget_name], key.replace('_POS', '')) # store hidden or undocked widget flags correctly -> make them independent for restoring for window_key in constants.UNDOCKABLE_WINDOW_KEYS: hidden = False if not global_runtime_config.get_config_value(window_key + "_WINDOW_UNDOCKED"): hidden = getattr(self, window_key.lower() + '_hidden') global_runtime_config.set_config_value(window_key + '_HIDDEN', hidden) global_runtime_config.save_configuration() # state-editor will relieve it's model => it won't observe the state machine manager any more self.get_controller('states_editor_ctrl').prepare_destruction( ) # avoid new state editor TODO tbd (deleted) rafcon.core.singleton.state_machine_manager.delete_all_state_machines() rafcon.core.singleton.library_manager.prepare_destruction() # Recursively destroys the main window self.destroy() from rafcon.gui.clipboard import global_clipboard global_clipboard.destroy() gui_singletons.main_window_controller = None
def stop_reactor_on_state_machine_finish(state_machine): """ Wait for a state machine to be finished and stops the reactor :param state_machine: the state machine to synchronize with """ wait_for_state_machine_finished(state_machine) from twisted.internet import reactor if reactor.running: plugins.run_hook("pre_destruction") reactor.callFromThread(reactor.stop)
def prepare_destruction(self): """Saves current configuration of windows and panes to the runtime config file, before RAFCON is closed.""" plugins.run_hook("pre_destruction") logger.debug("Saving runtime config to {0}".format( global_runtime_config.config_file_path)) # store pane last positions for key, widget_name in constants.PANE_ID.items(): global_runtime_config.store_widget_properties( self.view[widget_name], key.replace('_POS', '')) # store hidden or undocked widget flags correctly -> make them independent for restoring for window_key in constants.UNDOCKABLE_WINDOW_KEYS: hidden = False if not global_runtime_config.get_config_value(window_key + "_WINDOW_UNDOCKED"): hidden = getattr(self, window_key.lower() + '_hidden') global_runtime_config.set_config_value(window_key + '_HIDDEN', hidden) global_runtime_config.save_configuration() # state-editor will relieve it's model => it won't observe the state machine manager any more self.get_controller('states_editor_ctrl').prepare_destruction( ) # avoid new state editor TODO tbd (deleted) rafcon.core.singleton.state_machine_manager.delete_all_state_machines() rafcon.core.singleton.library_manager.prepare_destruction() # gtkmvc installs a global glade custom handler that holds a reference to the last created View class, # preventing it from being destructed. By installing a dummy callback handler, after all views have been # created, the old handler is being removed and with it the reference, allowing all Views to be destructed. # Gtk TODO: check if necessary and search for replacement # try: # from gtk import glade # def dummy(*args, **kwargs): # pass # glade.set_custom_handler(dummy) # except ImportError: # pass # Recursively destroys the main window self.destroy() from rafcon.gui.clipboard import global_clipboard global_clipboard.destroy() gui_singletons.main_window_controller = None
def __init__(self, root_state_name): self.consumers = dict() # Queue with infinite space self.execution_history_item_queue = Queue() self.condition = threading.Condition() self.interrupt = False self._consumers_exist = False self._file_system_consumer_exists = False if global_config.get_config_value("FILE_SYSTEM_EXECUTION_HISTORY_ENABLE", False): self.register_consumer(self.FILE_SYSTEM_CONSUMER_NAME, FileSystemConsumer(root_state_name)) self._file_system_consumer_exists = True plugins.run_hook("register_execution_history_consumer", self) # Only have one thread here that will call the notify function of each consumer # The advantage it that the consumer authors don't have to care about threading # and don't have to care about when an item is popped from the queue self.worker_thread = threading.Thread(target=self._feed_consumers) self.worker_thread.start()
def main(): register_signal_handlers(signal_handler) logger.info("initialize RAFCON ... ") pre_setup_plugins() setup_environment() logger.info("parse arguments ... ") parser = setup_argument_parser() user_input = parser.parse_args() if not user_input.state_machine_path: logger.error("You have to specify a valid state machine path") exit(-1) setup_configuration(user_input.config_path) post_setup_plugins(user_input) first_sm = None for sm_path in user_input.state_machine_path: sm = open_state_machine(sm_path) if first_sm is None: first_sm = sm if not user_input.remote: start_state_machine(first_sm, user_input.start_state_path) if reactor_required(): from twisted.internet import reactor # Blocking call, return when state machine execution finishes reactor.run() if not user_input.remote: wait_for_state_machine_finished(first_sm) else: while not _user_abort: time.sleep(1) logger.info("State machine execution finished!") plugins.run_hook("post_destruction") logging.shutdown()
def post_gui_destruction(): plugins.run_hook("post_destruction") if global_gui_config.get_config_value('AUTO_RECOVERY_LOCK_ENABLED'): rafcon.gui.models.auto_backup.remove_rafcon_instance_lock_file()
def register_view(self, view): super(MainWindowController, self).register_view(view) self.register_actions(self.shortcut_manager) self.view.get_top_widget().connect("key-press-event", self._on_key_press) self.view.get_top_widget().connect("key-release-event", self._on_key_release) # using helper function to connect functions to GUI elements to be able to access the handler id later on self.connect_button_to_function( 'main_window', "delete_event", self.get_controller('menu_bar_controller').on_quit_activate) # connect left bar, right bar and console hide buttons' signals to their corresponding methods self.connect_button_to_function('left_bar_hide_button', "clicked", self.on_left_bar_hide_clicked) self.connect_button_to_function('right_bar_hide_button', "clicked", self.on_right_bar_hide_clicked) self.connect_button_to_function('console_hide_button', "clicked", self.on_console_hide_clicked) # Connect left bar, right bar and console return buttons' signals to their corresponding methods self.connect_button_to_function('left_bar_return_button', "clicked", self.on_left_bar_return_clicked) self.connect_button_to_function('right_bar_return_button', "clicked", self.on_right_bar_return_clicked) self.connect_button_to_function('console_return_button', "clicked", self.on_console_return_clicked) # Connect undock buttons signals for window_key in constants.UNDOCKABLE_WINDOW_KEYS: self.connect_button_to_function( 'undock_{}_button'.format(window_key.lower()), "clicked", partial(self.undock_sidebar, window_key)) # Connect collapse button for trees self.connect_button_to_function('collapse_tree_button', "clicked", self.on_collapse_button_clicked) # Connect Shortcut buttons' signals to their corresponding methods self.connect_button_to_function('button_start_shortcut', "toggled", self.on_button_start_shortcut_toggled) self.connect_button_to_function('button_stop_shortcut', "clicked", self.on_button_stop_shortcut_clicked) self.connect_button_to_function('button_pause_shortcut', "toggled", self.on_button_pause_shortcut_toggled) self.connect_button_to_function( 'button_start_from_shortcut', "clicked", self.on_button_start_from_shortcut_clicked) self.connect_button_to_function('button_run_to_shortcut', "clicked", self.on_button_run_to_shortcut_clicked) self.connect_button_to_function( 'button_step_mode_shortcut', "toggled", self.on_button_step_mode_shortcut_toggled) self.connect_button_to_function( 'button_step_in_shortcut', "clicked", self.on_button_step_in_shortcut_clicked) self.connect_button_to_function( 'button_step_over_shortcut', "clicked", self.on_button_step_over_shortcut_clicked) self.connect_button_to_function( 'button_step_out_shortcut', "clicked", self.on_button_step_out_shortcut_clicked) self.connect_button_to_function( 'button_step_backward_shortcut', "clicked", self.on_button_step_backward_shortcut_clicked) view['upper_notebook'].connect('switch-page', self.on_notebook_tab_switch, view['upper_notebook_title'], view.left_bar_window, 'upper') view['lower_notebook'].connect('switch-page', self.on_notebook_tab_switch, view['lower_notebook_title'], view.left_bar_window, 'lower') view.get_top_widget().connect("configure-event", self.update_widget_runtime_config, "MAIN_WINDOW") view.left_bar_window.get_top_widget().connect( "configure-event", self.update_widget_runtime_config, "LEFT_BAR_WINDOW") view.right_bar_window.get_top_widget().connect( "configure-event", self.update_widget_runtime_config, "RIGHT_BAR_WINDOW") view.console_window.get_top_widget().connect( "configure-event", self.update_widget_runtime_config, "CONSOLE_WINDOW") # save pane positions in the runtime config on every change view['top_level_h_pane'].connect("button-release-event", self.update_widget_runtime_config, "LEFT_BAR_DOCKED") view['right_h_pane'].connect("button-release-event", self.update_widget_runtime_config, "RIGHT_BAR_DOCKED") view['central_v_pane'].connect("button-release-event", self.update_widget_runtime_config, "CONSOLE_DOCKED") # hide not usable buttons self.view['step_buttons'].hide() # Initializing Main Window Size & Position # secure un maximize in initial condition to restore correct position and size view.get_top_widget().unmaximize() gui_helper_label.set_window_size_and_position(view.get_top_widget(), 'MAIN') wait_for_gui() # Initializing Pane positions for config_id in constants.PANE_ID: self.set_pane_position(config_id) # set the hidden status of all bars for window_key in constants.UNDOCKABLE_WINDOW_KEYS: if global_runtime_config.get_config_value(window_key + '_HIDDEN'): func = getattr(self, 'on_{}_hide_clicked'.format(window_key.lower())) func(None) # restore undock state of bar windows if gui_config.get_config_value("RESTORE_UNDOCKED_SIDEBARS"): for window_key in constants.UNDOCKABLE_WINDOW_KEYS: if global_runtime_config.get_config_value(window_key + "_WINDOW_UNDOCKED"): self.undock_sidebar(window_key) # secure maximized state if global_runtime_config.get_config_value("MAIN_WINDOW_MAXIMIZED"): wait_for_gui() view.get_top_widget().maximize() # check for auto backups if gui_config.get_config_value( 'AUTO_BACKUP_ENABLED') and gui_config.get_config_value( 'AUTO_RECOVERY_CHECK'): import rafcon.gui.models.auto_backup as auto_backup auto_backup.check_for_crashed_rafcon_instances() plugins.run_hook("main_window_setup", self) wait_for_gui() # Ensure that the next message is being printed (needed for LN manager to detect finished startup) level = logger.level logger.setLevel(logging.INFO) logger.info("Ready") logger.setLevel(level)
def register_view(self, view): """Called when the View was registered Can be used e.g. to connect signals. Here, the destroy signal is connected to close the application """ super(StateEditorController, self).register_view(view) view.prepare_the_labels( ) # the preparation of the labels is done here to take into account plugin hook changes view['add_input_port_button'].connect('clicked', self.inputs_ctrl.on_add) view['add_output_port_button'].connect('clicked', self.outputs_ctrl.on_add) if isinstance(self.model, ContainerStateModel): view['add_scoped_variable_button'].connect('clicked', self.scopes_ctrl.on_add) view['remove_input_port_button'].connect('clicked', self.inputs_ctrl.on_remove) view['remove_output_port_button'].connect('clicked', self.outputs_ctrl.on_remove) if isinstance(self.model, ContainerStateModel): view['remove_scoped_variable_button'].connect( 'clicked', self.scopes_ctrl.on_remove) if isinstance( self.model, LibraryStateModel ) or self.model.state.get_next_upper_library_root_state(): view['add_input_port_button'].set_sensitive(False) view['remove_input_port_button'].set_sensitive(False) view['add_output_port_button'].set_sensitive(False) view['remove_output_port_button'].set_sensitive(False) view['add_scoped_variable_button'].set_sensitive(False) view['remove_scoped_variable_button'].set_sensitive(False) view.inputs_view.show() view.outputs_view.show() view.scopes_view.show() view.outcomes_view.show() view.transitions_view.show() view.data_flows_view.show() # show scoped variables if show content is enabled -> if disabled the tab stays and indicates a container state if isinstance(self.model, LibraryStateModel) and not self.model.show_content(): view.scopes_view.hide() view.linkage_overview.scope_view.hide() # Container states do not have a source editor and library states does not show there source code # Thus, for those states we do not have to add the source controller and can hide the source code tab # logger.info("init state: {0}".format(model)) lib_with_and_ES_as_root = isinstance(self.model, LibraryStateModel) and \ not isinstance(self.model.state_copy, ContainerStateModel) if not isinstance(self.model, ContainerStateModel) and not isinstance(self.model, LibraryStateModel) or \ lib_with_and_ES_as_root: view.source_view.show() if isinstance(self.model, LibraryStateModel) and not self.model.show_content(): view.remove_source_tab() view.remove_scoped_variables_tab() else: view.scopes_view.show() if isinstance(self.model, LibraryStateModel) and \ (not self.model.show_content() or not isinstance(self.model.state_copy, ContainerStateModel)): view.remove_scoped_variables_tab() view.remove_source_tab() if global_gui_config.get_config_value("SEMANTIC_DATA_MODE", False): view.bring_tab_to_the_top('Semantic Data') else: if isinstance(self.model.state, LibraryState): view.bring_tab_to_the_top('Description') else: view.bring_tab_to_the_top('Linkage Overview') if isinstance(self.model, ContainerStateModel): self.scopes_ctrl.reload_scoped_variables_list_store() plugins.run_hook("post_state_editor_register_view", self)
def main(optional_args=None): register_signal_handlers(signal_handler) logger.info("initialize RAFCON ... ") pre_setup_plugins() setup_environment() logger.info("parse arguments ... ") parser = setup_argument_parser() if optional_args: user_input = parser.parse_args(optional_args) else: user_input = parser.parse_args() if not user_input.state_machine_path: logger.error("You have to specify a valid state machine path") exit(-1) if user_input.memory_profiling: tracemalloc.start() memory_profiling_args = { 'memory_profiling_path': user_input.memory_profiling_path, 'memory_profiling_interval': user_input.memory_profiling_interval, 'memory_profiling_print': user_input.memory_profiling_print, 'stop': False, } memory_profiling_thread = threading.Thread(target=profiling.memory_profiling, args=(memory_profiling_args,)) memory_profiling_thread.start() setup_configuration(user_input.config_path) post_setup_plugins(user_input) first_sm = None for sm_path in user_input.state_machine_path: sm = open_state_machine(sm_path) if first_sm is None: first_sm = sm if not user_input.remote: start_state_machine(first_sm, user_input.start_state_path) if reactor_required(): from twisted.internet import reactor # Blocking call, return when state machine execution finishes reactor.run() if not user_input.remote: wait_for_state_machine_finished(first_sm) else: while not _user_abort: time.sleep(1) logger.info("State machine execution finished!") plugins.run_hook("post_destruction") logging.shutdown() if user_input.memory_profiling: memory_profiling_args['stop'] = True memory_profiling_thread.join()