mirror of
				https://github.com/avatao-content/test-tutorial-framework
				synced 2025-11-04 02:42:56 +00:00 
			
		
		
		
	Move custom event handlers away
This commit is contained in:
		
				
					committed by
					
						
						therealkrispet
					
				
			
			
				
	
			
			
			
						parent
						
							d597e4e004
						
					
				
				
					commit
					417a848328
				
			
							
								
								
									
										100
									
								
								solvable/src/custom_event_handlers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								solvable/src/custom_event_handlers.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
import logging
 | 
			
		||||
from ast import literal_eval
 | 
			
		||||
 | 
			
		||||
from tfw.components import MessageSender, TerminalCommands
 | 
			
		||||
from tfw.builtins import EventHandler, FSMAwareEventHandler, TFWServerUplinkConnector
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TerminalCallbackEventHandler(EventHandler):
 | 
			
		||||
    """
 | 
			
		||||
    Logs commands executed in terminal to messages and invokes an
 | 
			
		||||
    additional callback function to handle special commands.
 | 
			
		||||
    !! Please remove from production code. !!
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, callback):
 | 
			
		||||
        self.callback = callback
 | 
			
		||||
        super().__init__(key)
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
        command = message['value']
 | 
			
		||||
        self.cenator(command)
 | 
			
		||||
        self.callback(command)
 | 
			
		||||
 | 
			
		||||
    def cenator(self, command):
 | 
			
		||||
        LOG.debug('User executed command: "%s"', command)
 | 
			
		||||
        MessageSender(self.server_connector).send('JOHN CENA', f'You\'ve executed "{command}"')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestCommands(TerminalCommands):
 | 
			
		||||
    """
 | 
			
		||||
    Some example commands useful for debugging.
 | 
			
		||||
    !! Please remove from production code !! and inherit your own
 | 
			
		||||
    class from TerminalCommands if you need to define custom
 | 
			
		||||
    commands in your challenge.
 | 
			
		||||
    """
 | 
			
		||||
    # pylint: disable=unused-argument, attribute-defined-outside-init, no-self-use
 | 
			
		||||
    def command_sendmessage(self, *args):
 | 
			
		||||
        """
 | 
			
		||||
        Insert TFW message template as first argument if executed without args.
 | 
			
		||||
 | 
			
		||||
        Evaluate first argumen as a dict and send it to the frontend.
 | 
			
		||||
        This is useful for playing around with frontend APIs.
 | 
			
		||||
        """
 | 
			
		||||
        if not args:
 | 
			
		||||
            message_template = """'{"key": "", "data": {"command": ""}}'"""
 | 
			
		||||
            TFWServerUplinkConnector().send_message({
 | 
			
		||||
                'key': 'shell',
 | 
			
		||||
                'data': {
 | 
			
		||||
                    'command': 'write',
 | 
			
		||||
                    'value': f'sendmessage {message_template}'
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        else:
 | 
			
		||||
            TFWServerUplinkConnector().send_message(literal_eval(args[0]))
 | 
			
		||||
 | 
			
		||||
    def command_seppuku_tfw(self, *args):
 | 
			
		||||
        """
 | 
			
		||||
        Restart tfw_server.py and event_handler_main.py.
 | 
			
		||||
        This can speed up development when combined with mounting
 | 
			
		||||
        volumes from host to container.
 | 
			
		||||
        """
 | 
			
		||||
        seppuku = (
 | 
			
		||||
            'nohup sh -c "supervisorctl restart tfwserver event_handler_main" &> /dev/null & '
 | 
			
		||||
            'clear && echo "Committed seppuku! :)" && sleep infinity'
 | 
			
		||||
        )
 | 
			
		||||
        uplink = TFWServerUplinkConnector()
 | 
			
		||||
        uplink.send_message({
 | 
			
		||||
            'key': 'shell',
 | 
			
		||||
            'data': {
 | 
			
		||||
                'command': 'write',
 | 
			
		||||
                'value': f'{seppuku}\n'
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        uplink.send_message({
 | 
			
		||||
            'key': 'dashboard',
 | 
			
		||||
            'data': {
 | 
			
		||||
                'command': 'reloadFrontend'
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MessageFSMStepsEventHandler(FSMAwareEventHandler):
 | 
			
		||||
    """
 | 
			
		||||
    This example EventHandler is capable of detecting FSM state.
 | 
			
		||||
    !! Please remove from production code !!
 | 
			
		||||
    """
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def handle_fsm_step(self, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        When the FSM steps this method is invoked.
 | 
			
		||||
        Receives a 'data' field from an fsm_update message as kwargs.
 | 
			
		||||
        """
 | 
			
		||||
        MessageSender(self.server_connector).send(
 | 
			
		||||
            'FSM info',
 | 
			
		||||
            f'FSM has stepped from state "{kwargs["last_event"]["from_state"]}" '
 | 
			
		||||
            f'to state "{kwargs["current_state"]}" in response to trigger "{kwargs["last_event"]["trigger"]}"'
 | 
			
		||||
        )
 | 
			
		||||
@@ -1,118 +1,25 @@
 | 
			
		||||
import logging
 | 
			
		||||
from sys import stderr
 | 
			
		||||
from ast import literal_eval
 | 
			
		||||
from functools import partial
 | 
			
		||||
from signal import signal, SIGTERM, SIGINT
 | 
			
		||||
 | 
			
		||||
from tornado.ioloop import IOLoop
 | 
			
		||||
 | 
			
		||||
from tfw.fsm import YamlFSM
 | 
			
		||||
from tfw.builtins import EventHandler, FSMAwareEventHandler, TFWServerUplinkConnector
 | 
			
		||||
from tfw.builtins import EventHandler
 | 
			
		||||
from tfw.builtins import IdeEventHandler, TerminalEventHandler, FrontendEventHandler
 | 
			
		||||
from tfw.builtins import LogMonitoringEventHandler, ProcessManagingEventHandler
 | 
			
		||||
from tfw.builtins import DirectorySnapshottingEventHandler, FSMManagingEventHandler, MessageSender
 | 
			
		||||
from tfw.components import TerminalCommands
 | 
			
		||||
from tfw.builtins import DirectorySnapshottingEventHandler, FSMManagingEventHandler
 | 
			
		||||
from tfw.config import TFWENV
 | 
			
		||||
from tfw.logging import Log, Logger, LogFormatter, VerboseLogFormatter
 | 
			
		||||
from tao.config import TAOENV
 | 
			
		||||
 | 
			
		||||
from custom_event_handlers import MessageFSMStepsEventHandler
 | 
			
		||||
from custom_event_handlers import TerminalCallbackEventHandler, TestCommands
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TerminalCallbackEventHandler(EventHandler):
 | 
			
		||||
    """
 | 
			
		||||
    Logs commands executed in terminal to messages and invokes an
 | 
			
		||||
    additional callback function to handle special commands.
 | 
			
		||||
    !! Please remove from production code. !!
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, key, callback):
 | 
			
		||||
        self.callback = callback
 | 
			
		||||
        super().__init__(key)
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
        command = message['value']
 | 
			
		||||
        self.cenator(command)
 | 
			
		||||
        self.callback(command)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def cenator(command):
 | 
			
		||||
        LOG.debug('User executed command: "%s"', command)
 | 
			
		||||
        MessageSender().send('JOHN CENA', f'You\'ve executed "{command}"')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestCommands(TerminalCommands):
 | 
			
		||||
    """
 | 
			
		||||
    Some example commands useful for debugging.
 | 
			
		||||
    !! Please remove from production code !! and inherit your own
 | 
			
		||||
    class from TerminalCommands if you need to define custom
 | 
			
		||||
    commands in your challenge.
 | 
			
		||||
    """
 | 
			
		||||
    # pylint: disable=unused-argument, attribute-defined-outside-init, no-self-use
 | 
			
		||||
    def command_sendmessage(self, *args):
 | 
			
		||||
        """
 | 
			
		||||
        Insert TFW message template as first argument if executed without args.
 | 
			
		||||
 | 
			
		||||
        Evaluate first argumen as a dict and send it to the frontend.
 | 
			
		||||
        This is useful for playing around with frontend APIs.
 | 
			
		||||
        """
 | 
			
		||||
        if not args:
 | 
			
		||||
            message_template = """'{"key": "", "data": {"command": ""}}'"""
 | 
			
		||||
            TFWServerUplinkConnector().send_message({
 | 
			
		||||
                'key': 'shell',
 | 
			
		||||
                'data': {
 | 
			
		||||
                    'command': 'write',
 | 
			
		||||
                    'value': f'sendmessage {message_template}'
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
        else:
 | 
			
		||||
            TFWServerUplinkConnector().send_message(literal_eval(args[0]))
 | 
			
		||||
 | 
			
		||||
    def command_seppuku_tfw(self, *args):
 | 
			
		||||
        """
 | 
			
		||||
        Restart tfw_server.py and event_handler_main.py.
 | 
			
		||||
        This can speed up development when combined with mounting
 | 
			
		||||
        volumes from host to container.
 | 
			
		||||
        """
 | 
			
		||||
        seppuku = (
 | 
			
		||||
            'nohup sh -c "supervisorctl restart tfwserver event_handler_main" &> /dev/null & '
 | 
			
		||||
            'clear && echo "Committed seppuku! :)" && sleep infinity'
 | 
			
		||||
        )
 | 
			
		||||
        uplink = TFWServerUplinkConnector()
 | 
			
		||||
        uplink.send_message({
 | 
			
		||||
            'key': 'shell',
 | 
			
		||||
            'data': {
 | 
			
		||||
                'command': 'write',
 | 
			
		||||
                'value': f'{seppuku}\n'
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        uplink.send_message({
 | 
			
		||||
            'key': 'dashboard',
 | 
			
		||||
            'data': {
 | 
			
		||||
                'command': 'reloadFrontend'
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MessageFSMStepsEventHandler(FSMAwareEventHandler):
 | 
			
		||||
    """
 | 
			
		||||
    This example EventHandler is capable of detecting FSM state.
 | 
			
		||||
    !! Please remove from production code !!
 | 
			
		||||
    """
 | 
			
		||||
    def handle_event(self, message):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def handle_fsm_step(self, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        When the FSM steps this method is invoked.
 | 
			
		||||
        Receives a 'data' field from an fsm_update message as kwargs.
 | 
			
		||||
        """
 | 
			
		||||
        MessageSender().send(
 | 
			
		||||
            'FSM info',
 | 
			
		||||
            f'FSM has stepped from state "{kwargs["last_event"]["from_state"]}" '
 | 
			
		||||
            f'to state "{kwargs["current_state"]}" in response to trigger "{kwargs["last_event"]["trigger"]}"'
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    # pylint: disable=unused-variable
 | 
			
		||||
    Logger([
 | 
			
		||||
@@ -165,7 +72,7 @@ def main():
 | 
			
		||||
        key='test'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def stop(*_): 
 | 
			
		||||
    def stop(*_):
 | 
			
		||||
        EventHandler.stop_all_instances()
 | 
			
		||||
        exit(0)
 | 
			
		||||
    signal(SIGTERM, stop)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,8 @@
 | 
			
		||||
from os.path import exists
 | 
			
		||||
 | 
			
		||||
from tfw.fsm import LinearFSM
 | 
			
		||||
from tfw.builtins import MessageSender
 | 
			
		||||
from tfw.components import MessageSender
 | 
			
		||||
from tfw.builtins import TFWServerUplinkConnector
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestFSM(LinearFSM):
 | 
			
		||||
@@ -11,7 +12,8 @@ class TestFSM(LinearFSM):
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__(6)
 | 
			
		||||
        self.message_sender = MessageSender()
 | 
			
		||||
        self.uplink = TFWServerUplinkConnector()
 | 
			
		||||
        self.message_sender = MessageSender(self.uplink)
 | 
			
		||||
        self.subscribe_predicate('step_3', self.step_3_allowed)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user