class FysomRepeatedAfterEventCallbackTests(unittest.TestCase): def setUp(self): self.fired = [] def record_event(event): self.fired.append(event.msg) return 42 self.fsm = Fysom({ 'initial': 'notcalled', 'events': [ {'name': 'multiple', 'src': 'notcalled', 'dst': 'called'}, {'name': 'multiple', 'src': 'called', 'dst': 'called'}, ], 'callbacks': { 'onaftermultiple': record_event } }) def test_should_fire_onafter_event_repeatedly(self): self.fsm.multiple(msg="first") self.fsm.multiple(msg="second") self.assertEqual(self.fired, ["first", "second"])
class FysomEventWithStateCallbackTests(unittest.TestCase): def setUp(self): self.fired_nocalled_to_called = [] self.fired_called_to_called = [] def record_event_nocalled_to_called(event): self.fired_nocalled_to_called.append(event.msg) return 42 def record_event_called_to_called(event): self.fired_called_to_called.append(event.msg) return 42 self.fsm = Fysom({ 'initial': 'notcalled', 'events': [ {'name': 'multiple', 'src': 'notcalled', 'dst': 'called'}, {'name': 'multiple', 'src': 'called', 'dst': 'called'}, ], 'callbacks': { 'onaftermultiple_notcalled_called': record_event_nocalled_to_called, 'onaftermultiple_called_called': record_event_called_to_called } }) def test_should_fire_on_event(self): self.fsm.multiple(msg="first") self.fsm.multiple(msg="second") self.assertEqual(self.fired_nocalled_to_called, ["first"]) self.assertEqual(self.fired_called_to_called, ["second"])
def __init__(self, agent): logger.debug("Initializing host agent state machine") self.agent = agent self.fsm = Fysom({ "events": [("lookup", "*", "found"), ("announce", "found", "announced"), ("pending", "announced", "wait4init"), ("ready", "wait4init", "good2go")], "callbacks": { # Can add the following to debug # "onchangestate": self.print_state_change, "onlookup": self.lookup_agent_host, "onannounce": self.announce_sensor, "onpending": self.on_ready, "ongood2go": self.on_good2go } }) self.timer = threading.Timer(1, self.fsm.lookup) self.timer.daemon = True self.timer.name = self.THREAD_NAME # Only start the announce process when not in Test if not "INSTANA_TEST" in os.environ: self.timer.start()
def __init__(self, name, runner, references, config, **kwargs): """ Create a PrePostTask. @param str name: unique name of the task @param object runner: TaskRunner that manages this task @param dict references: contains references to all required modules @param dict config: configuration parameter dictionary """ _default_callbacks = {'onprerun': self._pre, 'onpostrun': self._post} _stateList = { 'initial': 'stopped', 'events': [{ 'name': 'prerun', 'src': 'stopped', 'dst': 'paused' }, { 'name': 'postrun', 'src': 'paused', 'dst': 'stopped' }], 'callbacks': _default_callbacks } if 'PyQt5' in sys.modules: super().__init__(cfg=_stateList, **kwargs) else: QtCore.QObject.__init__(self) Fysom.__init__(self, _stateList) self.lock = Mutex() self.name = name self.runner = runner self.ref = references self.config = config
def __init__(self, left_button=None, left_led=None, right_button=None, right_led=None, track=None, strawberry_factory=None, chocolate_factory=None): self.buttons_locked = False self.micro_lock = threading.Lock() self.pending_cookies = Queue.Queue() self.left_button = left_button self.left_button.register(self.button_pressed) self.left_led = left_led self.left_led.off() self.right_button = right_button self.right_button.register(self.button_pressed) self.right_led = right_led self.right_led.off() self.track = track self.strawberry_factory = strawberry_factory self.chocolate_factory = chocolate_factory self.evolution = Evolution() self._fsm = Fysom(initial='waiting', events=[('reproduce', 'waiting', 'waiting')], callbacks=[('on_state_waiting', self._unlock), ('onreproduce', self._reproduce)])
def create_voting_fsm(tracking_id, vote, broadcast_vote, spawn_yadtshell, fold, cleanup_fsm): fsm = Fysom({ 'initial': 'negotiating', 'events': [ {'name': 'call', 'src': 'negotiating', 'dst': 'negotiating'}, {'name': 'fold', 'src': 'negotiating', 'dst': 'finish'}, {'name': 'showdown', 'src': 'negotiating', 'dst': 'spawning'}, {'name': 'spawned', 'src': 'spawning', 'dst': 'finish'}, {'name': 'showdown', 'src': 'finish', 'dst': 'finish'} ], 'callbacks': { 'onnegotiating': broadcast_vote, 'onspawning': spawn_yadtshell, 'onfinish': cleanup_fsm, 'onfold': fold, } }) fsm.tracking_id = tracking_id fsm.vote = vote return fsm
def __init__(self, debuglevel=0, debugname='Log Service Base'): self.debuglevel = debuglevel self.debugname = debugname self._error_string = '' self.on_error_string_changed = [] # Log self._log_channel = Publish(debuglevel=debuglevel) self._log_channel.debugname = '%s - %s' % (self.debugname, 'log') # more efficient to reuse protobuf messages self._log_tx = Container() # callbacks self.on_state_changed = [] # fsm self._fsm = Fysom( { 'initial': 'down', 'events': [ {'name': 'connect', 'src': 'down', 'dst': 'up'}, {'name': 'disconnect', 'src': 'up', 'dst': 'down'}, ], } ) self._fsm.ondown = self._on_fsm_down self._fsm.onafterconnect = self._on_fsm_connect self._fsm.onup = self._on_fsm_up self._fsm.onafterdisconnect = self._on_fsm_disconnect
def test_pickling(self): fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ] }) pickled = dumps(fsm) assert pickled fsm = loads(pickled) self.assertTrue(isinstance(fsm, Fysom)) self.assertEquals('green', fsm.current) fsm.warn() pickled = dumps(fsm) assert pickled fsm = loads(pickled) self.assertEquals('yellow', fsm.current)
def test_if_src_not_specified_then_is_wildcard(self): fsm = Fysom({ 'initial': 'hungry', 'events': [{ 'name': 'eat', 'src': 'hungry', 'dst': 'satisfied' }, { 'name': 'eat', 'src': 'satisfied', 'dst': 'full' }, { 'name': 'eat', 'src': 'full', 'dst': 'sick' }, { 'name': 'rest', 'dst': 'hungry' }] }) fsm.eat() self.assertEqual(fsm.current, 'satisfied') fsm.rest() self.assertEqual(fsm.current, 'hungry') fsm.eat() fsm.eat() self.assertEqual(fsm.current, 'full') fsm.rest() self.assertEqual(fsm.current, 'hungry')
def __init__(self, callbacks_dict=None, interactive_callbacks=None): self.__NOT_IMPLEMENTED_ERROR = "Classes that inherit from KnittingPlugin should implment {0}" self.interactive_callbacks = {} if interactive_callbacks is None: self.register_interactive_callbacks({ "info": BaseKnittingPlugin.__interactive_info, "user_action": BaseKnittingPlugin.__interactive_info, "warning": BaseKnittingPlugin.__interactive_warn, "error": BaseKnittingPlugin.__interactive_error, "progress": BaseKnittingPlugin.__log_progress }) else: self.register_interactive_callbacks(interactive_callbacks) if callbacks_dict is None: callbacks_dict = { 'onknit': self.onknit, 'onconfigure': self.onconfigure, 'onfinish': self.onfinish, } Fysom.__init__(self, { 'initial': 'activated', 'events': [ # TODO: add more states for handling error management. {'name': 'configure', 'src': 'activated', 'dst': 'configured'}, {'name': 'configure', 'src': 'configured', 'dst': 'configured'}, {'name': 'configure', 'src': 'finished', 'dst': 'configured'}, {'name': 'configure', 'src': 'error', 'dst': 'configured'}, {'name': 'knit', 'src': 'configured', 'dst': 'knitting'}, {'name': 'finish', 'src': 'knitting', 'dst': 'finished'}, {'name': 'fail', 'src': 'knitting', 'dst': 'error'}], 'callbacks': callbacks_dict })
def test_onchangestate_should_fire_for_all_state_changes(self): def on_change_state(e): self.current_event = e fsm = Fysom({ 'initial': 'foo', 'events': [ {'name': 'footobar', 'src': 'foo', 'dst': 'bar'}, {'name': 'bartobaz', 'src': 'bar', 'dst': 'baz'}, ], 'callbacks': { 'onchangestate': on_change_state } }) fsm.footobar(id=123) self.assertEqual(self.current_event.event, 'footobar') self.assertEqual(self.current_event.src, 'foo') self.assertEqual(self.current_event.dst, 'bar') self.assertEqual(self.current_event.id, 123) self.assertTrue(self.current_event.fsm is fsm) fsm.bartobaz('positional', named_attribute='test') self.assertEqual(self.current_event.event, 'bartobaz') self.assertEqual(self.current_event.src, 'bar') self.assertEqual(self.current_event.dst, 'baz') self.assertEqual(self.current_event.named_attribute, 'test') self.assertEqual(self.current_event.args[0], 'positional') self.assertTrue(self.current_event.fsm is fsm)
def __init__(self, callbacks_dict=None, interactive_callbacks=None): """Interactive callbacks handle Plugin-Frontend interaction hooks.""" self.interactive_callbacks = {} # Are we running on CLI or knitlib web? # If no callbacks are registered, we set a CLI set as default. if interactive_callbacks is None: self.register_interactive_callbacks({ "blocking_user_action": BaseKnittingPlugin.__cli_blocking_action, "message": BaseKnittingPlugin.__cli_emit_message, "progress": BaseKnittingPlugin.__cli_log_progress }) else: self.register_interactive_callbacks(interactive_callbacks) # Fysom allows to set hooks before changing states, we set them here. if callbacks_dict is None: callbacks_dict = { 'onknit': self.onknit, 'onconfigure': self.onconfigure, 'onfinish': self.onfinish, } Fysom.__init__(self, { 'initial': 'activated', 'events': [ # TODO: add more states for handling error management. {'name': 'configure', 'src': 'activated', 'dst': 'configured'}, {'name': 'configure', 'src': 'configured', 'dst': 'configured'}, {'name': 'configure', 'src': 'finished', 'dst': 'configured'}, {'name': 'configure', 'src': 'error', 'dst': 'configured'}, {'name': 'knit', 'src': 'configured', 'dst': 'knitting'}, {'name': 'finish', 'src': 'knitting', 'dst': 'finished'}, {'name': 'finish', 'src': 'finished', 'dst': 'finished'}, {'name': 'fail', 'src': 'knitting', 'dst': 'error'}], 'callbacks': callbacks_dict })
def __init__(self): self._states = [] self._fsm = Fysom({ 'initial': 'green', 'events': [{ 'name': 'warn', 'src': 'green', 'dst': 'yellow' }, { 'name': 'panic', 'src': 'yellow', 'dst': 'red' }, { 'name': 'calm', 'src': 'red', 'dst': 'yellow' }, { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }], 'callbacks': { 'ongreen': self._on_green, 'onyellow': self._on_yellow, 'onred': self._on_red } })
def __init__(self, agent): package_version = 'unknown' try: package_version = pkg_resources.get_distribution('instana').version except pkg_resources.DistributionNotFound: pass logger.info("Stan is on the scene. Starting Instana instrumentation version: %s", package_version) logger.debug("initializing fsm") self.agent = agent self.fsm = Fysom({ "events": [ ("lookup", "*", "found"), ("announce", "found", "announced"), ("pending", "announced", "wait4init"), ("ready", "wait4init", "good2go")], "callbacks": { # Can add the following to debug # "onchangestate": self.print_state_change, "onlookup": self.lookup_agent_host, "onannounce": self.announce_sensor, "onpending": self.agent.start, "onready": self.on_ready}}) self.timer = t.Timer(5, self.fsm.lookup) self.timer.daemon = True self.timer.name = self.THREAD_NAME self.timer.start()
def __init__(self): self.electionTimerInterval=randint(6,10) #seconds timeout # self.electionTimerInterval=randint(2,5) #seconds timeout self.ns = NodeState() self.ownAddress = socket.gethostbyname(socket.gethostname()) self.leaderId = None print(self.ownAddress) self.serverState = Fysom({'initial': 'follower', 'events': [ ('startElection', 'follower', 'candidate'), ('discoverLeader', 'candidate', 'follower'), ('newTerm', 'candidate', 'follower'), ('startElection', 'candidate', 'candidate'), ('receivedMajority', 'candidate', 'leader'), ('discoverServerWithHigherTerm', 'leader', 'follower') ], 'callbacks': { 'onleader': self.become_leader, 'onstartElection': self.become_candidate, 'onleaveleader': self.stop_being_leader, 'onfollower': self.become_follower } }) self.nodeAddresses = [] # need to make sure all nodes are started up before populating the node list while len(self.nodeAddresses) < self.nodesInCluster: self.update_node_list() time.sleep(1) print(self.nodeAddresses) self.otherNodeAddresses = [ a for a in self.nodeAddresses if a != str(self.ownAddress)] print(self.otherNodeAddresses)
def __init__(self, fsm_table=setup_fsm.fsm_def.FSM_TABLE, options = None, logger_name=sys.modules['__main__'].__name__, logger_dir = '.'): """ Initialise function of the generator FSM :param fsm_table: Table defining the FSM :param options : A dictionary containing the necessary options :param : logger_name : the parent logger name :param fsm_table: Table defining the FSM """ callbacks = {'onbeforeallocate': self.onbeforeallocate, 'onnot_ready': self.onnot_ready, 'onbeforeconfigure': self.onbeforeconfigure, 'onstand_by': self.onstand_by, 'onbeforestart_run': self.onbeforestart_run, 'onready': self.onready, 'onbeforestart_trigger': self.onbeforestart_trigger, 'onrunning': self.onrunning, 'onbeforestop_trigger': self.onbeforestop_trigger, 'onbeforestop_run': self.onbeforestop_run, 'onbeforereset': self.onbeforereset, 'onbeforedeallocate': self.onbeforedeallocate} Fysom.__init__(self, cfg = fsm_table, callbacks = callbacks) # Set up the logger self.logger = logging.getLogger(logger_name + '.camserver_fsm') self.logger.info('\t-|--|> Append the CameraServerFSM to the setup') self.options = options self.logger_dir = logger_dir
def __init__(self, location, size, disease): self.state = Fysom({ 'initial': 'healthy', 'events': [ { 'name': 'get infected', 'src': 'healthy', 'dst': 'incubation' }, { 'name': 'finish incubation', 'src': 'incubation', 'dst': 'contagious' }, { 'name': 'die', 'src': 'contagious', 'dst': 'dead' }, { 'name': 'recover', 'src': 'contagious', 'dst': 'immune' }, ], }) self.incubation_duration = disease['incubation duration'] self.contagious_duration = disease['contagious duration'] self.color = colors[self.state.current] self.next_trigger = None self.neighbors = [] self.size = size self.x, self.y = location[0] * self.size, location[1] * self.size
def __init__(self, name, runner, references, config, **kwargs): """ Create a PrePostTask. @param str name: unique name of the task @param object runner: TaskRunner that manages this task @param dict references: contains references to all required modules @param dict config: configuration parameter dictionary """ _default_callbacks = {'onprerun': self._pre, 'onpostrun': self._post} _stateList = { 'initial': 'stopped', 'events': [ {'name': 'prerun', 'src': 'stopped', 'dst': 'paused'}, {'name': 'postrun', 'src': 'paused', 'dst': 'stopped'} ], 'callbacks': _default_callbacks } if 'PyQt5' in sys.modules: super().__init__(cfg=_stateList, **kwargs) else: QtCore.QObject.__init__(self) Fysom.__init__(self, _stateList) self.lock = Mutex() self.name = name self.runner = runner self.ref = references self.config = config
def setUp(self): self.fired_callbacks = [] self.fsm = Fysom({ 'initial': 'sleeping', 'events': [ {'name': 'foo', 'src': 'sleeping', 'dst': 'fooed'}, {'name': 'foo', 'src': 'fooed', 'dst': 'fooed'}, {'name': 'bar', 'src': 'fooed', 'dst': 'bared'}, {'name': 'bar', 'src': 'bared', 'dst': 'bared'}, {'name': 'baz', 'src': 'bared', 'dst': 'bazed'}, {'name': 'wait', 'src': 'sleeping', 'dst': 'waiting'} ], 'callbacks': { 'onfoo': self.on_foo, 'onbar': self.on_bar, 'onbaz': self.on_baz, 'onbeforefoo': self.before_foo, 'onbeforebar': self.before_bar, 'onbeforewait': self.before_wait, 'onenterfooed': self.on_enter_fooed, 'onenterbared': self.on_enter_bared, 'onreenterfooed': self.on_reenter_fooed, 'onreenterbared': self.on_reenter_bared, 'onleavesleeping': self.on_leave_sleeping, 'onleavefooed': self.on_leave_fooed } })
def setUp(self): self.fsm = Fysom({ 'initial': 'green', 'events': [{ 'name': 'warn', 'src': 'green', 'dst': 'yellow' }, { 'name': 'panic', 'src': 'yellow', 'dst': 'red' }, { 'name': 'calm', 'src': 'red', 'dst': 'yellow' }, { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }, { 'name': 'warm', 'src': 'green', 'dst': 'blue' }] })
def logon(self): self.psget = PasswordProtect(self.baseurl) self.logon_fsm = Fysom({ 'initial': { 'state': 'start' }, 'events': [{ 'name': 'userid', 'src': 'start', 'dst': 'username_sent' }, { 'name': 'password', 'src': 'username_sent', 'dst': 'password_sent' }, { 'name': 'logon', 'src': 'password_sent', 'dst': 'logged_on' }], 'final': 'logged_on', 'callbacks': { 'onuserid': self.send_userid, 'onpassword': self.send_password, 'onlogon': self.send_logon } }) self.logon_fsm.userid(html_id='userid') self.logon_fsm.password(html_id='password') self.logon_fsm.logon(html_id='logon')
def __init__(self, debuglevel=0, debugname='Halrcomp Subscribe'): self.debuglevel = debuglevel self.debugname = debugname self._error_string = '' self.on_error_string_changed = [] # ZeroMQ context = zmq.Context() context.linger = 0 self._context = context # pipe to signalize a shutdown self._shutdown = context.socket(zmq.PUSH) self._shutdown_uri = b'inproc://shutdown-%s' % str(uuid.uuid4()).encode() self._shutdown.bind(self._shutdown_uri) self._thread = None # socket worker tread self._tx_lock = threading.Lock() # lock for outgoing messages # Socket self.socket_uri = '' self._socket_topics = set() # more efficient to reuse protobuf messages self._socket_rx = Container() # Heartbeat self._heartbeat_lock = threading.Lock() self._heartbeat_interval = 2500 self._heartbeat_timer = None self._heartbeat_active = False self._heartbeat_liveness = 0 self._heartbeat_reset_liveness = 5 # callbacks self.on_socket_message_received = [] self.on_state_changed = [] # fsm self._fsm = Fysom( { 'initial': 'down', 'events': [ {'name': 'start', 'src': 'down', 'dst': 'trying'}, {'name': 'full_update_received', 'src': 'trying', 'dst': 'up'}, {'name': 'stop', 'src': 'trying', 'dst': 'down'}, {'name': 'heartbeat_timeout', 'src': 'up', 'dst': 'trying'}, {'name': 'heartbeat_tick', 'src': 'up', 'dst': 'up'}, {'name': 'any_msg_received', 'src': 'up', 'dst': 'up'}, {'name': 'stop', 'src': 'up', 'dst': 'down'}, ], } ) self._fsm.ondown = self._on_fsm_down self._fsm.onafterstart = self._on_fsm_start self._fsm.ontrying = self._on_fsm_trying self._fsm.onafterfull_update_received = self._on_fsm_full_update_received self._fsm.onafterstop = self._on_fsm_stop self._fsm.onup = self._on_fsm_up self._fsm.onafterheartbeat_timeout = self._on_fsm_heartbeat_timeout self._fsm.onafterheartbeat_tick = self._on_fsm_heartbeat_tick self._fsm.onafterany_msg_received = self._on_fsm_any_msg_received
def test_gc_should_not_break_callback(self): class MyTestObject(object): def __init__(self): self._states = [] self._fsm = None def warn(self): self._fsm.warn() def panic(self): self._fsm.panic() def calm(self): self._fsm.calm() def clear(self): self._fsm.clear() def _on_green(self, *args, **kwargs): self._states.append('green') def _on_yellow(self, *args, **kwargs): self._states.append('yellow') def _on_red(self, *args, **kwargs): self._states.append('red') obj = MyTestObject() fsm = Fysom({ 'initial': 'green', 'events': [{ 'name': 'warn', 'src': 'green', 'dst': 'yellow' }, { 'name': 'panic', 'src': 'yellow', 'dst': 'red' }, { 'name': 'calm', 'src': 'red', 'dst': 'yellow' }, { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }], 'callbacks': { 'ongreen': obj._on_green, 'onyellow': obj._on_yellow, 'onred': obj._on_red } }) obj._fsm = fsm obj.warn() obj.clear() del obj fsm.warn()
def test_init_kwargs_only(self): fsm = Fysom(initial='green', events=[('panic', 'green', 'red'), ('calm', 'red', 'green')]) self.assertEqual(fsm.current, "green") fsm.panic() self.assertEqual(fsm.current, "red") fsm.calm() self.assertEqual(fsm.current, "green")
def __init__(self, callbacks_dict): self.__NOT_IMPLEMENTED_ERROR = "Classes that inherit from KnittingPlugin should implment {0}" callbacks_dict = { 'onknit': self.onknit, #'onknitting': self.onknitting, 'onconfigure': self.onconfigure, 'onfinish': self.onfinish, } Fysom.__init__( self, { 'initial': 'activated', 'events': [ ## TODO: add more states for handling error management. { 'name': 'configure', 'src': 'activated', 'dst': 'configured' }, { 'name': 'configure', 'src': 'configured', 'dst': 'configured' }, { 'name': 'configure', 'src': 'finished', 'dst': 'configured' }, { 'name': 'configure', 'src': 'error', 'dst': 'configured' }, { 'name': 'knit', 'src': 'configured', 'dst': 'knitting' }, { 'name': 'finish', 'src': 'knitting', 'dst': 'finished' }, { 'name': 'fail', 'src': 'knittng', 'dst': 'error' } ], 'callbacks': callbacks_dict })
def test_never_finished_if_final_is_unspecified(self): fsm = Fysom({ 'initial': 'green', 'events': [{ 'name': 'warn', 'src': 'green', 'dst': 'yellow' }, { 'name': 'panic', 'src': 'yellow', 'dst': 'red' }, { 'name': 'calm', 'src': 'red', 'dst': 'yellow' }, { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }] }) self.assertFalse(fsm.is_finished()) fsm.warn() self.assertFalse(fsm.is_finished()) fsm.panic() self.assertFalse(fsm.is_finished())
def test_it_should_indicate_whether_fsm_in_finished_state(self): fsm = Fysom({ 'initial': 'green', 'final': 'red', 'events': [{ 'name': 'warn', 'src': 'green', 'dst': 'yellow' }, { 'name': 'panic', 'src': 'yellow', 'dst': 'red' }, { 'name': 'calm', 'src': 'red', 'dst': 'yellow' }, { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }] }) self.assertFalse(fsm.is_finished()) fsm.warn() self.assertFalse(fsm.is_finished()) fsm.panic() self.assertTrue(fsm.is_finished())
def __init__(self, debuglevel=0, debugname='Log Base'): self.debuglevel = debuglevel self.debugname = debugname self._error_string = '' self.on_error_string_changed = [] # Log self._log_channel = SimpleSubscribe(debuglevel=debuglevel) self._log_channel.debugname = '%s - %s' % (self.debugname, 'log') self._log_channel.on_state_changed.append( self._log_channel_state_changed) self._log_channel.on_socket_message_received.append( self._log_channel_message_received) # more efficient to reuse protobuf messages self._log_rx = Container() # callbacks self.on_log_message_received = [] self.on_state_changed = [] # fsm self._fsm = Fysom({ 'initial': 'down', 'events': [ { 'name': 'connect', 'src': 'down', 'dst': 'trying' }, { 'name': 'log_up', 'src': 'trying', 'dst': 'up' }, { 'name': 'disconnect', 'src': 'trying', 'dst': 'down' }, { 'name': 'disconnect', 'src': 'up', 'dst': 'down' }, ], }) self._fsm.ondown = self._on_fsm_down self._fsm.onafterconnect = self._on_fsm_connect self._fsm.ontrying = self._on_fsm_trying self._fsm.onafterlog_up = self._on_fsm_log_up self._fsm.onafterdisconnect = self._on_fsm_disconnect self._fsm.onup = self._on_fsm_up self._fsm.onleaveup = self._on_fsm_up_exit
def test_deferred_initial_state_should_be_none_then_state(self): fsm = Fysom({ 'initial': {'state': 'green', 'event': 'init', 'defer': True}, 'events': [ {'name': 'panic', 'src': 'green', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'green'}, ] }) self.assertEqual(fsm.current, 'none') fsm.init() self.assertEqual(fsm.current, 'green')
def test_kwargs_override_cfg(self): fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'panic', 'src': 'green', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'green'}, ]}, # override initial state and calm event initial='red', events=[('calm', 'red', 'black')]) self.assertEqual(fsm.current, "red") fsm.calm() self.assertEqual(fsm.current, "black")
class FysomAsynchronousStateTransitionTests(unittest.TestCase): def on_leave_foo(self, e): self.leave_foo_event = e return False def on_enter_bar(self, e): self.on_enter_bar_fired = True self.on_enter_bar_event = e def setUp(self): self.on_enter_bar_fired = False self.fsm = Fysom({ 'initial': 'foo', 'events': [ { 'name': 'footobar', 'src': 'foo', 'dst': 'bar' }, { 'name': 'bartobar', 'src': 'bar', 'dst': 'bar' }, ], 'callbacks': { 'onleavefoo': self.on_leave_foo, 'onenterbar': self.on_enter_bar, } }) def test_fsm_should_be_put_on_hold_when_onleave_state_returns_false(self): self.fsm.footobar(id=123) self.assertEqual(self.fsm.current, 'foo') self.assertTrue(hasattr(self, 'leave_foo_event'), 'Callback onleavefoo did not fire.') self.assertTrue(self.leave_foo_event is not None) self.assertEqual(self.leave_foo_event.id, 123) self.fsm.transition() self.assertEqual(self.fsm.current, 'bar') def test_onenter_state_should_not_fire_when_fsm_is_put_on_hold(self): self.fsm.footobar(id=123) self.assertFalse(self.on_enter_bar_fired) self.fsm.transition() self.assertTrue(self.on_enter_bar_fired) def test_should_raise_exception_upon_further_transitions_when_fsm_is_on_hold( self): self.fsm.footobar(id=123) self.assertRaises(FysomError, self.fsm.bartobar)
def test_goto(self): fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'panic', 'src': 'green', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ] }) self.assertRaises(MultiplePossibilitesFound, fsm.next) self.assertEqual('red', fsm.goto('panic'))
def __init__(self, plugin_id, current_state): Fysom.__init__(self, { 'initial': current_state, 'events': events, 'callbacks': { 'oninstall': self.install, 'oninitialize': self.initialize } }) self.plugin_id = plugin_id self.current_state = current_state self.onchangestate = self._onchangestate
def do_stem(self, word): fsm = Fysom(initial='start', events=self.events) i = len(word) - 1 j = len(word) while (True): if i <= 0: break v = word[i:j] # print v res = fsm.can(v) if (res): if v == 'i' and fsm.can(word[i - 1:j]): i = i - 1 continue fsm.trigger(v) if fsm.current == 'h': if word[i - 1:i] == 'i': i = i - 1 # skip i if word[i - 1:i] == 'n': # ning qushimchasi fsm.current = 'start' continue elif fsm.current == 'b': fsm.current = 'start' j = i i = i - 1 return word[:j]
def __init__(self, *args, **kwargs): logger.debug("PseudoDevice %s", kwargs) self.addr = kwargs.pop('addr', "0000") self.typemodule = kwargs.pop('typemodule', None) self.ser = kwargs.pop('ser', []) Fysom.__init__( self, { 'initial': 'idle', 'events': [ { 'name': 'evt_askident', 'dst': 'ukn', 'src': [ 'idle', ] }, { 'name': 'evt_giveident', 'dst': 'identified', 'src': [ 'idle', 'ukn', ] }, { 'name': 'evt_newvalue', 'dst': 'newvalue', 'src': [ 'identified', ] }, { 'name': 'evt_valueack', 'dst': 'identified', 'src': [ 'newvalue', ] }, ], "callbacks": { # 'onconnected': self.connected_state, 'onidentified': self.identified_state, 'onnewvalue': self.newvalue_state, # 'onidle': self.idle_state, } }) logger.debug('Module of type %s at address %s detected', self.typemodule, self.addr)
def do_stem(self, word): fsm = Fysom(initial='start', events=self.events) # FIXME: uncomment below and make sanitize functions support # both Python 2 and 3 versions # word = WordProcessor.sanitize(word) i = len(word) - 1 j = len(word) while (True): if i <= 0: break v = word[i:j] # print v res = fsm.can(v) if (res): if v == 'i' and fsm.can(word[i - 1:j]): i = i - 1 continue fsm.trigger(v) if fsm.current == 'h': if word[i - 1:i] == 'i': i = i - 1 # skip i if word[i - 1:i] == 'n': # ning qushimchasi fsm.current = 'start' continue elif fsm.current == 'b': fsm.current = 'start' j = i i = i - 1 return word[:j]
def __init__(self, name, runner, references, config, **kwargs): """ Create an Interruptable task. @param str name: unique task name @param object runner: reference to the TaskRunner managing this task @param dict references: a dictionary of all required modules @param dict config: configuration dictionary """ default_callbacks = { 'onrun': self._start, 'onpause': self._pause, 'onresume': self._resume, 'onfinish': self._finish } _stateDict = { 'initial': 'stopped', 'events': [ {'name': 'run', 'src': 'stopped', 'dst': 'starting'}, {'name': 'startingFinished', 'src': 'starting', 'dst': 'running'}, {'name': 'pause', 'src': 'running', 'dst': 'pausing'}, {'name': 'pausingFinished', 'src': 'pausing', 'dst': 'paused'}, {'name': 'finish', 'src': 'running', 'dst': 'finishing'}, {'name': 'finishingFinished', 'src': 'finishing', 'dst': 'stopped'}, {'name': 'resume', 'src': 'paused', 'dst': 'resuming'}, {'name': 'resumingFinished', 'src': 'resuming', 'dst': 'running'}, {'name': 'abort', 'src': 'pausing', 'dst': 'stopped'}, {'name': 'abort', 'src': 'starting', 'dst': 'stopped'}, {'name': 'abort', 'src': 'resuming', 'dst': 'stopped'} ], 'callbacks': default_callbacks } if 'PyQt5' in sys.modules: super().__init__(cfg=_stateDict, **kwargs) else: QtCore.QObject.__init__(self) Fysom.__init__(self, _stateDict) self.lock = Mutex() self.name = name self.interruptable = False self.success = False self.runner = runner self.ref = references self.config = config self.sigDoStart.connect(self._doStart, QtCore.Qt.QueuedConnection) self.sigDoPause.connect(self._doPause, QtCore.Qt.QueuedConnection) self.sigDoResume.connect(self._doResume, QtCore.Qt.QueuedConnection) self.sigDoFinish.connect(self._doFinish, QtCore.Qt.QueuedConnection) self.sigNextTaskStep.connect(self._doTaskStep, QtCore.Qt.QueuedConnection)
def test_gc_should_not_break_callback(self): class MyTestObject(object): def __init__(self): self._states = [] self._fsm = None def warn(self): self._fsm.warn() def panic(self): self._fsm.panic() def calm(self): self._fsm.calm() def clear(self): self._fsm.clear() def _on_green(self, *args, **kwargs): self._states.append('green') def _on_yellow(self, *args, **kwargs): self._states.append('yellow') def _on_red(self, *args, **kwargs): self._states.append('red') obj = MyTestObject() fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ], 'callbacks': { 'ongreen': obj._on_green, 'onyellow': obj._on_yellow, 'onred': obj._on_red } }) obj._fsm = fsm obj.warn() obj.clear() del obj fsm.warn()
def test_it_doesnt_break_with_unicode_literals(self): try: fsm = Fysom({ 'initial': 'green', 'final': 'red', 'events': [{ 'name': 'warn', 'src': 'green', 'dst': 'yellow' }, { 'name': 'panic', 'src': 'yellow', 'dst': 'red' }, { 'name': 'calm', 'src': 'red', 'dst': 'yellow' }, { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }] }) self.assertTrue(True) except TypeError: self.assertTrue(False)
def setUp(self): self.fired_nocalled_to_called = [] self.fired_called_to_called = [] def record_event_nocalled_to_called(event): self.fired_nocalled_to_called.append(event.msg) return 42 def record_event_called_to_called(event): self.fired_called_to_called.append(event.msg) return 42 def record_event_before_notcalled_to_called(event): return True def record_event_before_called_to_called(event): return False self.fsm = Fysom({ 'initial': 'notcalled', 'events': [ {'name': 'multiple', 'src': 'notcalled', 'dst': 'called'}, {'name': 'multiple', 'src': 'called', 'dst': 'called'}, ], 'callbacks': { 'onbeforemultiple_notcalled_called': record_event_before_notcalled_to_called, 'onaftermultiple_notcalled_called': record_event_nocalled_to_called, 'onbeforemultiple_called_called': record_event_before_called_to_called, 'onaftermultiple_called_called': record_event_called_to_called } })
def __init__(self, left_button=None, left_led=None, right_button=None, right_led=None, track=None, strawberry_factory=None, chocolate_factory=None): self.buttons_locked = False self.micro_lock = threading.Lock() self.pending_cookies = Queue.Queue() self.left_button = left_button self.left_button.register(self.button_pressed) self.left_led = left_led self.left_led.off() self.right_button = right_button self.right_button.register(self.button_pressed) self.right_led = right_led self.right_led.off() self.track = track self.strawberry_factory = strawberry_factory self.chocolate_factory = chocolate_factory self.evolution = Evolution() self._fsm = Fysom( initial='waiting', events=[('reproduce', 'waiting', 'waiting')], callbacks=[('on_state_waiting', self._unlock), ('onreproduce', self._reproduce)])
def __init__(self, cfg): from fysom import Fysom events = set([event['name'] for event in cfg['events']]) cfg['callbacks'] = self.collect_event_listeners( events, cfg['callbacks']) self.fsm = Fysom(cfg) self.attach_proxy_methods(self.fsm, events)
class FysomStateTests(unittest.TestCase): def setUp(self): self.fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ] }) def test_is_state_should_succeed_for_initial_state(self): self.assertTrue(self.fsm.isstate('green')) def test_identity_transition_should_not_be_allowed_by_default(self): self.assertFalse(self.fsm.can('clear')) self.assertTrue(self.fsm.cannot('clear')) def test_configured_transition_should_work(self): self.assertTrue(self.fsm.can('warn')) def test_transition_should_change_state(self): self.fsm.warn() self.assertTrue(self.fsm.isstate('yellow')) def test_should_raise_exception_when_state_transition_is_not_allowed(self): self.assertRaises(FysomError, self.fsm.panic) self.assertRaises(FysomError, self.fsm.calm) self.assertRaises(FysomError, self.fsm.clear)
def do_stem(self, word): fsm = Fysom(initial='start', events=self.events) # FIXME: uncomment below and make sanitize functions support # both Python 2 and 3 versions # word = WordProcessor.sanitize(word) i = len(word) - 1 j = len(word) while(True): if i <= 0: break v = word[i:j] # print v res = fsm.can(v) if (res): if v == 'i' and fsm.can(word[i-1:j]): i = i - 1 continue fsm.trigger(v) if fsm.current == 'h': if word[i-1:i] == 'i': i = i - 1 # skip i if word[i-1:i] == 'n': # ning qushimchasi fsm.current = 'start' continue elif fsm.current == 'b': fsm.current = 'start' j = i i = i - 1 return word[:j]
def test_no_possibility_for_goto(self): fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'panic', 'src': 'green', 'dst': 'red'}, # when call panic from green, we go to red, from red we # should go to yellow, but it is commented and we should # have a exception # {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ] }) self.assertRaises(MultiplePossibilitesFound, fsm.next) self.assertEqual('red', fsm.goto('panic')) self.assertRaises(NoPossibilityFound, fsm.goto, 'calm')
def __init__(self, display): self.display = display self.fsm = Fysom({ 'initial': 'start', 'events': [ {'name': 'up', 'src': 'credits', 'dst': 'start'}, {'name': 'up', 'src': 'start', 'dst': 'credits'}, {'name': 'down', 'src': 'start', 'dst': 'credits'}, {'name': 'down', 'src': 'credits', 'dst': 'start'}] }) self.player_controllers = [None, None]
def setUp(self): self.fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ] })
def test_tuples_as_trasition_spec(self): fsm = Fysom({ 'initial': 'green', 'events': [ # freely mix dicts and tuples {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, ('panic', 'yellow', 'red'), ('calm', 'red', 'yellow'), {'name': 'clear', 'src': 'yellow', 'dst': 'green'} ] }) fsm.warn() fsm.panic() self.assertEqual(fsm.current, 'red') fsm.calm() fsm.clear() self.assertEqual(fsm.current, 'green')
class FysomStateTests(unittest.TestCase): def setUp(self): self.fsm = Fysom({ 'initial': 'green', 'events': [ {'name': 'warn', 'src': 'green', 'dst': 'yellow'}, {'name': 'panic', 'src': 'yellow', 'dst': 'red'}, {'name': 'calm', 'src': 'red', 'dst': 'yellow'}, {'name': 'clear', 'src': 'yellow', 'dst': 'green'}, {'name': 'warm', 'src': 'green', 'dst': 'blue'} ] }) def test_is_state_should_succeed_for_initial_state(self): self.assertTrue(self.fsm.isstate('green')) def test_identity_transition_should_not_be_allowed_by_default(self): self.assertFalse(self.fsm.can('clear')) self.assertTrue(self.fsm.cannot('clear')) def test_configured_transition_should_work(self): self.assertTrue(self.fsm.can('warn')) def test_transition_should_change_state(self): self.fsm.warn() self.assertTrue(self.fsm.isstate('yellow')) def test_should_raise_exception_when_state_transition_is_not_allowed(self): self.assertRaises(FysomError, self.fsm.panic) self.assertRaises(FysomError, self.fsm.calm) self.assertRaises(FysomError, self.fsm.clear) def test_event_handler_has_name_and_docstring(self): self.assertEqual(self.fsm.warm.__name__, "warm", "Event handlers do not have appropriate name.") self.assertNotEqual(self.fsm.warm.__name__, None, "Docstring for event handler is None!") def test_trigger_should_trigger_the_event_handler(self): self.assertEqual(self.fsm.current, "green", "The initial state isn't the expected state.") self.fsm.trigger("warm") make_callable = lambda: self.fsm.trigger("unknowevent") self.assertRaises(FysomError, make_callable) self.assertEqual(self.fsm.current, "blue", "The initial state isn't the expected state.")
class FysomAsynchronousStateTransitionTests(unittest.TestCase): def on_leave_foo(self, e): self.leave_foo_event = e return False def on_enter_bar(self, e): self.on_enter_bar_fired = True self.on_enter_bar_event = e def setUp(self): self.on_enter_bar_fired = False self.fsm = Fysom({ 'initial': 'foo', 'events': [ {'name': 'footobar', 'src': 'foo', 'dst': 'bar'}, {'name': 'bartobar', 'src': 'bar', 'dst': 'bar'}, ], 'callbacks': { 'onleavefoo': self.on_leave_foo, 'onenterbar': self.on_enter_bar, } }) def test_fsm_should_be_put_on_hold_when_onleave_state_returns_false(self): self.fsm.footobar(id=123) self.assertEqual(self.fsm.current, 'foo') self.assertTrue(hasattr(self, 'leave_foo_event'), 'Callback onleavefoo did not fire.') self.assertTrue(self.leave_foo_event is not None) self.assertEqual(self.leave_foo_event.id, 123) self.fsm.transition() self.assertEqual(self.fsm.current, 'bar') def test_onenter_state_should_not_fire_when_fsm_is_put_on_hold(self): self.fsm.footobar(id=123) self.assertFalse(self.on_enter_bar_fired) self.fsm.transition() self.assertTrue(self.on_enter_bar_fired) def test_should_raise_exception_upon_further_transitions_when_fsm_is_on_hold(self): self.fsm.footobar(id=123) self.assertRaises(FysomError, self.fsm.bartobar)
class Trail: IDLE = 'idle' REGISTERED = 'registered' HOLD = 'hold' ACTIVE = 'active' def __init__(self, path=None): self.path = path self.store = Store() self._fsm = Fysom( initial=Trail.IDLE, events=[ ('register', Trail.IDLE, Trail.REGISTERED), ('prepare', Trail.REGISTERED, Trail.HOLD), ('activate', Trail.HOLD, Trail.ACTIVE), ('resolve', Trail.ACTIVE, Trail.IDLE), ('resolve', Trail.HOLD, Trail.IDLE), ('resolve', Trail.REGISTERED, Trail.IDLE)], callbacks=[ ('onbeforeregister', self._onbeforeregister), ('onregistered', self._registered), ('onidle', self._onidle)]) @property def status(self): return self._fsm.current def onchangestate(self, on_change): self._fsm.onchangestate = on_change def register(self): self._fsm.register() def prepare(self): self._fsm.prepare() def activate(self): self._fsm.activate() def resolve(self): self._fsm.resolve() def _onbeforeregister(self, e): self.store.register(self.path) def _registered(self, e): self.prepare() def _onidle(self, e): if e.src is not "none": self.store.unregister(self.path)
class FysomEventWithStateWithOnbeforeCallbackTests(unittest.TestCase): def setUp(self): self.fired_nocalled_to_called = [] self.fired_called_to_called = [] def record_event_nocalled_to_called(event): self.fired_nocalled_to_called.append(event.msg) return 42 def record_event_called_to_called(event): self.fired_called_to_called.append(event.msg) return 42 def record_event_before_notcalled_to_called(event): return True def record_event_before_called_to_called(event): return False self.fsm = Fysom({ 'initial': 'notcalled', 'events': [ {'name': 'multiple', 'src': 'notcalled', 'dst': 'called'}, {'name': 'multiple', 'src': 'called', 'dst': 'called'}, ], 'callbacks': { 'onbeforemultiple_notcalled_called': record_event_before_notcalled_to_called, 'onaftermultiple_notcalled_called': record_event_nocalled_to_called, 'onbeforemultiple_called_called': record_event_before_called_to_called, 'onaftermultiple_called_called': record_event_called_to_called } }) def test_onbefore_called_to_called_callbacks_raising_exceptions_should_not_be_eaten(self): self.fsm.multiple(msg="first") with self.assertRaises(Canceled): self.fsm.multiple(msg="second") self.assertEqual(self.fired_nocalled_to_called, ["first"]) self.assertEqual(self.fired_called_to_called, [])
def __init__(self, display): self.display = display self.offset = 0 self.fsm = Fysom({ 'initial': 'menu', 'events': [ {'name': 'start', 'src': 'menu', 'dst': 'game'}, {'name': 'finish', 'src': 'game', 'dst': 'menu'}, {'name': 'credits', 'src': 'menu', 'dst': 'credits'}, {'name': 'menu', 'src': 'credits', 'dst': 'menu'} ] }) self.fsm.onchangestate = Application.change_state self.commands = [] self.active_state = Menu(self.display)
def __init__(self): self.switch = False self.sm = Fysom({ 'initial': 'Lights off', 'events': [ {'name': 'toggle', 'src': 'lights_off', 'dst': 'lights_on'}, {'name': 'toggle', 'src': 'lights_on', 'dst': 'lights_off'}], 'callbacks': { 'on_Lights_on': self.lights_on, 'on_Lights_off': self.lights_off, } })