#!/usr/bin/env python #-*- coding: utf-8 -*- # impra/app.py # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # software : ImpraStorage # version : 1.01 # date : 2014 # licence : GPLv3.0 # author : a-Sansara <[a-sansara]at[clochardprod]dot[net]> # copyright : pluie.org # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # This file is part of ImpraStorage. # # ImpraStorage is free software (free as in speech) : you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the License, # or (at your option) any later version. # # ImpraStorage is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License # along with ImpraStorage. If not, see . # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~ module app ~~ from psr.sys import Sys, Io, Const, init from psr.log import Log from psr.mproc import Manager from kirmah.ui import IdleObject from impra import conf from impra.core import ImpraStorage, ImpraConf from psr.imap import BadHostException, BadLoginException from gi.repository.GObject import threads_init, GObject, idle_add, SIGNAL_RUN_LAST, TYPE_NONE, TYPE_STRING, TYPE_INT, TYPE_FLOAT, TYPE_BOOLEAN from gi.repository.Gtk import STOCK_MEDIA_PAUSE, STOCK_NEW, STOCK_SAVE, STOCK_REFRESH, STOCK_REMOVE, STOCK_PROPERTIES, STOCK_EDIT, STOCK_DIALOG_INFO, STOCK_CLOSE from threading import Thread, current_thread, enumerate as thread_enum # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~ class CliThread ~~ class ImpraThread(Thread, IdleObject): """""" __gsignals__ = { # signal type signal return signal args 'completed' : ( SIGNAL_RUN_LAST , TYPE_NONE , ()), 'interrupted' : ( SIGNAL_RUN_LAST , TYPE_NONE , ()), 'progress' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_FLOAT,)), 'fileget' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN, TYPE_STRING )), 'fileremoved' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN, TYPE_STRING )), 'fileadded' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN, TYPE_STRING)), 'fileinfos' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN,)), 'fileedited' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN,)), 'indexrefreshed' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN,)), 'needconfig' : ( SIGNAL_RUN_LAST , TYPE_NONE , ()), 'filesearch' : ( SIGNAL_RUN_LAST , TYPE_NONE , ()), 'fileaddretry' : ( SIGNAL_RUN_LAST , TYPE_NONE , (TYPE_BOOLEAN, TYPE_STRING)), 'hasaddretry' : ( SIGNAL_RUN_LAST , TYPE_NONE , ()) } TASK_WAIT = 0 TASK_ADD = 1 TASK_GET = 2 TASK_REFRESH = 3 TASK_REMOVE = 4 TASK_INFOS = 5 TASK_EDIT = 6 TASK_ADD_RETRY = 7 TASK_EXIT = 8 K_SIGNAL_NAME = 0 K_SIGNAL_BIND = 1 K_SIGNAL_DATA = 2 TASK_LABEL = ['wait','add','get','refresh','remove','infos','edit','add-retry','exit'] TASK_STOCK = [STOCK_MEDIA_PAUSE, STOCK_NEW, STOCK_SAVE, STOCK_REFRESH, STOCK_REMOVE, STOCK_PROPERTIES, STOCK_EDIT, STOCK_DIALOG_INFO, STOCK_CLOSE] @Log(Const.LOG_DEBUG) def __init__(self, evtStop, taskQueue, condition, conf, name='ImpraThread', instce=None): Thread.__init__(self) IdleObject.__init__(self) self.setName(name) self.cancelled = False self.evtStop = evtStop self.taskQueue = taskQueue self.condition = condition self.conf = conf self.impst = instce print(' INIT THREAD '+name) print(self.impst) @Log(Const.LOG_DEBUG) def connect_signals(self, signals, usrData=None): """""" for signal in signals: self.connect(signal[self.K_SIGNAL_NAME], signal[self.K_SIGNAL_BIND], signal[self.K_SIGNAL_DATA] if len(signal)>self.K_SIGNAL_DATA else usrData) @Log(Const.LOG_DEBUG) def run(self): """""" self.cancelled = False self.evtStop.clear() Sys.g.THREAD_CLI = self Sys.g.GUI = True Sys.g.GUI_PRINT_STDOUT = True done = False self.can_retry = True init(conf.PRG_NAME, Sys.g.DEBUG, loglvl=Const.LOG_APP) try : if self.impst is None : label = ' [[ INIT IMPRASTORAGE ]] ' label = ' '+'~'*((Const.LINE_SEP_LEN-len(label))//2-1)+label+'~'*((Const.LINE_SEP_LEN-len(label))//2-1)+' ' Sys.pwlog([(Const.LINE_SEP_CHAR*Const.LINE_SEP_LEN , Const.CLZ_0 , True), (label.ljust(Const.LINE_SEP_LEN, ' ') , Const.CLZ_INIT , True), (Const.LINE_SEP_CHAR*Const.LINE_SEP_LEN , Const.CLZ_0 , True)]) self.impst = ImpraStorage(self.conf) done = True except Exception as e : self.emit('needconfig') raise e self.emit('indexrefreshed', done) if done : while not self.evtStop.is_set() or not self.cancelled: with self.condition : self.condition.wait_for(lambda : not self.taskQueue.empty(), 2) if self.can_retry and self.impst.hasBackupAddMap(): self.emit('hasaddretry') self.can_retry = False if not self.taskQueue.empty(): task, params, idtask = self.taskQueue.get_nowait() label = ' [[ TASK '+str(idtask)+' : '+self.TASK_LABEL[task].upper()+' ]] ' label = ' '+'>'*((Const.LINE_SEP_LEN-len(label))//2-1)+label+'<'*((Const.LINE_SEP_LEN-len(label))//2-1)+' ' Sys.pwlog([(Const.LINE_SEP_CHAR*Const.LINE_SEP_LEN , Const.CLZ_0 , True), (label.ljust(Const.LINE_SEP_LEN, ' ') , Const.CLZ_ACTION, True), (Const.LINE_SEP_CHAR*Const.LINE_SEP_LEN , Const.CLZ_0 , True)]) try: if task is self.TASK_WAIT : print('wait') Sys.sleep(params) elif task is self.TASK_GET: #~ mg = Manager(self.taskGet, 1, None, Sys.g.MPEVENT, uid=params) #~ mg.run() #~ self.emit('fileget', True, '') #~ Thread(target=self.taskGet, name='impra-1', kwargs={'uid':params}).start() print(params) self.taskGet(params) elif task is self.TASK_ADD: self.taskAdd(params) elif task is self.TASK_ADD_RETRY: self.taskAddRetry(params) elif task is self.TASK_REFRESH: self.taskRefresh(params) elif task is self.TASK_INFOS: self.taskInfos(params) elif task is self.TASK_REMOVE: self.taskRemove(params) elif task is self.TASK_EDIT: self.taskEdit(params) self.taskQueue.task_done() except self.impst.SocketError() as e : Sys.pwarn((('ImpraThread.run : ',(str(e),Sys.CLZ_WARN_PARAM), ' !'),)) self.impst.reconnect() except Exception as e: print(type(e)) Sys.pwarn((('ImpraThread.run : ',(str(e),Sys.CLZ_WARN_PARAM), ' !'),)) else : """""" Sys.sleep(0.5) self.emit('completed') def taskGet(self, uid): """""" done, p = self.impst.getFile(uid) self.emit('fileget', done, p) def taskAdd(self, params): """""" fromPath, label, catg = params done, p = self.impst.addFile(fromPath, label, catg) self.emit('fileadded', done, p) self.emit('indexrefreshed', done) def taskAddRetry(self, params=None): done, p = self.impst.sendFile(self.impst.getBackupAddMap(), True) self.emit('fileadded', done, p) self.emit('indexrefreshed', done) self.can_retry = True def taskRefresh(self, noparam=None): """""" self.emit('progress',10) self.impst.idxu.get(True) self.emit('indexrefreshed', True) def taskInfos(self, uid): """""" self.impst.getInfo(uid) self.emit('fileinfos', True) def taskRemove(self, uid): """""" done, p = self.impst.removeFile(uid) self.emit('fileremoved', done, p) self.emit('indexrefreshed', done) def taskEdit(self, params): """""" key, label, catg = params done = self.impst.editFile(key, label, catg) self.emit('fileedited', done) self.emit('indexrefreshed', done) @Log(Const.LOG_NEVER) def progress(self, value): """""" #~ print('progress '+str(value)) self.emit('progress', value) @Log(Const.LOG_NEVER) def cancel(self): """ Threads in python are not cancellable, so we implement our own cancellation logic """ self.cancelled = True self.evtStop.set() @Log(Const.LOG_NEVER) def stop(self): """""" if self.isAlive(): self.cancel() if current_thread().getName()==self.getName(): try: self.emit('interrupted') Sys.thread_exit() except RuntimeError as e : print(str(self.getName()) + ' COULD NOT BE TERMINATED') raise e