Exemple #1
0
class MainWorker(QObject):

    kill_all        = Signal()
    

    max_grid_size   = 50
    max_grid_cnt    = 5
    config          = None # element configuration

    updateLogdate  = Signal(object)        # update displayed date string in stdin_reader
    updateConfig   = Signal(object)        # update configuration in execution operator
    startExec       = Signal(object)        # element-Id
    stopExec        = Signal(object)        # element-Id
    saveConfig      = Signal(object)        # configuration
    sysCommand      = Signal(object)        # Optional: Element Constructor / Destructor
    frontendCtrl    = Signal(object)
    queryStates     = Signal()              # Query the running states of elements
    startAll        = Signal(object)        # Start all elements: (config)
    stopAll         = Signal()              # Stop all elements
    killAll         = Signal()              # Kill all running processes

    def __init__(self, app):
        super(MainWorker, self).__init__()
        self.app = app

        # Setup command line arguments
        
        parser = argparse.ArgumentParser(description='Pythonic background daemon')
        # Debug output switch 
        parser.add_argument('-Ex', action='store_true', help='Interactive shell interface, Unix only')
        # Log level
        parser.add_argument('-v', action='store_true', help='Verbose output')

        self.args = parser.parse_args()

        # Set Log Level
        if self.args.v:
            log_level = logging.DEBUG
        else:
            log_level = logging.INFO

        # Instantiate the LogFileHandler
        self.logFileHandler = LogFileHandler(log_level)

        # Select multiprocessing spawn method
        mp.set_start_method('spawn')
        
        # Set working directory
        os.chdir(Path(__file__).parent.absolute())

        # Setup format
        locale.setlocale(locale.LC_TIME, '')

        # Instantiate WSGI Server
        self.wsgi_server = WSGI_Server(self)
        
        # Instantiate Execution Operator
        self.operator = Operator()
        self.operator.command.connect(self.forwardCmd)
        self.startExec.connect(self.operator.startExec)
        self.stopExec.connect(self.operator.stopExec)
        self.updateConfig.connect(self.operator.updateConfig)
        self.queryStates.connect(self.operator.getElementStates)
        self.startAll.connect(self.operator.startAll)
        self.stopAll.connect(self.operator.stopAll)
        self.killAll.connect(self.operator.killAll)
        

        # Instantiate Standard Input Reader (Unix only)
        if self.args.Ex:
            try:
                from stdin_reader import stdinReader
            except ImportError:
                from Pythonic.stdin_reader import stdinReader        
        
            self.stdinReader = stdinReader(self.operator.processHandles.items(), self.logFileHandler.log_date_str)
            self.stdinReader.quit_app.connect(self.exitApp)


        # Connect the logger
        if self.args.Ex:
            self.logFileHandler.updateLogdate.connect(self.stdinReader.updateLogDate)
               

        # Instantiate ToolboxLoader
        self.toolbox_loader = ToolboxLoader()
        self.toolbox_loader.tooldataLoaded.connect(self.forwardCmd)
        
        # Instantiate (Element)-EditorLoader

        self.editor_loader = EditorLoader()
        self.editor_loader.editorLoaded.connect(self.forwardCmd)
        
        # Instantiate ConfigWriter
        self.config_writer = ConfigWriter()
        self.config_writer.configSaved.connect(self.forwardCmd)
        self.saveConfig.connect(self.config_writer.saveConfig)

        # Instantiate ConfigLoader
        self.config_loader = ConfigLoader()
        self.config_loader.configLoaded.connect(self.configLoaded)

        # Instantiate System Command Executor
        self.exec_sys_cmd = ExecSysCMD()
        self.sysCommand.connect(self.exec_sys_cmd.execCommand)
            
    
    def exitApp(self):
        print('# Stopping all processes....')
        self.kill_all.emit()
        time.sleep(3) # wait for 1 seconds to kill all processes
        self.app.quit()
        os.kill(self.app.applicationPid(), signal.SIGTERM) # kill all related threads
    

    def start(self, args):

        
        reset_screen()    

        if self.args.Ex:
            reset_screen_dbg()    
            self.stdinReader.start() # call run() method in separate thread

        self.config = self.config_loader.loadConfigSync()


        self.wsgi_server.start()
        self.operator.start(self.config)

    def loadTools(self): # Multithreaded
        
        logging.debug('MainWorker::loadTools() called')
        self.toolbox_loader.start()

    def loadEditorConfig(self, address, typeName): # Multithreaded
        
        logging.debug('MainWorker::loadEditorConfig() called')
        self.editor_loader.startLoad(address, typeName)

    def forwardCmd(self, cmd):

        #logging.debug('MainWorker::forwardCmd() called')
        self.frontendCtrl.emit(cmd)

    def loadConfig(self): # Multithreaded
        
        logging.debug('MainWorker::loadConfig() called')
        self.config_loader.start()
           
    def configLoaded(self, config):

        self.config = config

        address = { 'target' : 'MainWindow'}
        
        cmd = { 'cmd'       : 'CurrentConfig',
                'address'   : address,
                'data'      : config }

        self.frontendCtrl.emit(cmd)

    def checkArgs(self, args):

        b_file_found = False
        grid_file = None

        for argument in args:
            if argument[0] == '-' or argument[0] == '--':
                print('Option found: {}'.format(argument))
            else:
                if not b_file_found:
                    b_file_found = True
                    grid_file = argument

        return grid_file
Exemple #2
0
class MainWorker(QObject):

    kill_all = Signal()

    log_level = logging.INFO
    formatter = logging.Formatter(
        fmt='%(asctime)s - %(levelname)s - %(message)s', datefmt='%H:%M:%S')

    max_grid_size = 50
    max_grid_cnt = 5
    config = None  # element configuration

    update_logdate = Signal(
        object)  # update displayed date string in stdin_reader
    startExec = Signal(object, object)  # element-Id, configuration
    stopExec = Signal(object)  # element-Id
    saveConfig = Signal(object)  # configuration
    sysCommand = Signal(object)  # Optional: Element Constructor / Destructor
    frontendCtrl = Signal(object)
    queryStates = Signal()  # Query the running states of elements
    startAll = Signal(object)  # Start all elements: (config)
    stopAll = Signal()  # Stop all elements
    killAll = Signal()  # Kill all running processes

    def __init__(self, app):
        super(MainWorker, self).__init__()
        self.app = app

        # Setup command line arguments
        parser = argparse.ArgumentParser(
            description='Pythonic background daemon')
        parser.add_argument('-Debug',
                            action='store_true',
                            help='Interactive shell intercace, Unix only')
        self.args = parser.parse_args()

        # Select multiprocessing spawn method
        mp.set_start_method('spawn')

        # Set working directory
        os.chdir(Path(__file__).parent.absolute())

        # Setup format
        locale.setlocale(locale.LC_TIME, '')

        # Instantiate WSGI Server
        self.wsgi_server = WSGI_Server(self)

        # Instantiate Execution Operator
        self.operator = Operator()
        self.operator.command.connect(self.forwardCmd)
        self.startExec.connect(self.operator.startExec)
        self.stopExec.connect(self.operator.stopExec)
        self.queryStates.connect(self.operator.getElementStates)
        self.startAll.connect(self.operator.startAll)
        self.stopAll.connect(self.operator.stopAll)
        self.killAll.connect(self.operator.killAll)

        # Instantiate Standard Input Reader (Unix only)
        if self.args.Debug:
            try:
                from stdin_reader import stdinReader
            except ImportError:
                from Pythonic.stdin_reader import stdinReader

            self.stdinReader = stdinReader(
                self.operator.processHandles.items())
            self.stdinReader.quit_app.connect(self.exitApp)

        # Instantiate ToolboxLoader
        self.toolbox_loader = ToolboxLoader()
        self.toolbox_loader.tooldataLoaded.connect(self.forwardCmd)

        # Instantiate (Element)-EditorLoader

        self.editor_loader = EditorLoader()
        self.editor_loader.editorLoaded.connect(self.forwardCmd)

        # Instantiate ConfigWriter
        self.config_writer = ConfigWriter()
        self.config_writer.configSaved.connect(self.forwardCmd)
        self.saveConfig.connect(self.config_writer.saveConfig)

        # Instantiate ConfigLoader
        self.config_loader = ConfigLoader()
        self.config_loader.tooldataLoaded.connect(self.forwardCmd)

        # Instantiate System Command Executor
        self.exec_sys_cmd = ExecSysCMD()
        self.sysCommand.connect(self.exec_sys_cmd.execCommand)

        # Connect the logger
        if self.args.Debug:
            self.update_logdate.connect(self.stdinReader.updateLogDate)

        self.logger = logging.getLogger()
        self.logger.setLevel(self.log_level)

        # Create home path (if not already existing)

        home_path = Path.home() / 'Pythonic'
        if not os.path.exists(home_path):
            os.makedirs(home_path)

        # Create log path (if not already existing)

        self.log_path = home_path / 'log'

        if not os.path.exists(self.log_path):
            os.makedirs(self.log_path)

        # Get current date
        self.log_date = datetime.datetime.now()
        # self.log_date is kept up to date in heartbeat (WebSocket rcv)

        # Create directory structure for logging
        log_date_str = self.log_date.strftime('%Y_%m_%d')

        file_path = '{}/{}.txt'.format(str(self.log_path), log_date_str)

        # Setup logger

        file_handler = logging.FileHandler(file_path)
        file_handler.setLevel(self.log_level)
        file_handler.setFormatter(self.formatter)

        self.logger.addHandler(file_handler)
        self.update_logdate.emit(
            log_date_str)  # forward log_date_str to instance of stdinReader

        # Create directory for executables

        executables_path = home_path / 'executables'

        if not os.path.exists(executables_path):
            os.makedirs(executables_path)

        # Create trash folder for deleted files
        # TODO

        # Append executables folder to module search path

        sys.path.append(str(executables_path))

        logging.debug('MainWorker::__init__() called')

    def exitApp(self):
        print('# Stopping all processes....')
        self.kill_all.emit()
        time.sleep(3)  # wait for 1 seconds to kill all processes
        self.app.quit()
        os.kill(self.app.applicationPid(),
                signal.SIGTERM)  # kill all related threads

    def update_logfile(self):

        now = datetime.datetime.now().date()
        if (now != self.log_date.date()):
            self.logger.removeHandler(self.logger.handlers[0])
            log_date_str = now.strftime('%Y_%m_%d')
            file_path = '{}/{}.txt'.format(str(self.log_path), log_date_str)
            file_handler = logging.FileHandler(file_path)
            file_handler.setLevel(self.log_level)
            file_handler.setFormatter(self.formatter)
            self.logger.addHandler(file_handler)
            self.log_date = datetime.datetime.now()
            self.update_logdate.emit(log_date_str)

    def start(self, args):

        logging.info('<#>DAEMON STARTED<#>')
        reset_screen()

        if self.args.Debug:
            reset_screen_dbg()
            self.stdinReader.start()  # call run() method in separate thread

        self.wsgi_server.start()
        self.operator.start()

    def loadTools(self):

        logging.debug('MainWorker::loadTools() called')
        self.toolbox_loader.start()

    def loadEditorConfig(self, address, typeName):

        logging.debug('MainWorker::loadEditorConfig() called')
        self.editor_loader.startLoad(address, typeName)

    def forwardCmd(self, cmd):

        #logging.debug('MainWorker::forwardCmd() called')
        self.frontendCtrl.emit(cmd)

    def loadConfig(self):

        logging.debug('MainWorker::loadConfig() called')
        self.config_loader.start()

    def checkArgs(self, args):

        b_file_found = False
        grid_file = None

        for argument in args:
            if argument[0] == '-' or argument[0] == '--':
                print('Option found: {}'.format(argument))
            else:
                if not b_file_found:
                    b_file_found = True
                    grid_file = argument

        return grid_file