def __init__(self, plugin_name): RT.logger.setLevel(logging.INFO) if __debug__: RT.register(self) super(GtkUI, self).__init__(plugin_name) self.initialized = False self.config = None self.store = LabelStore() self.last_updated = None self._tries = 0 self._calls = [] self._extensions = [] self._update_funcs = [] self._cleanup_funcs = []
class GtkUI(Gtk3PluginBase): # Section: Initialization def __init__(self, plugin_name): RT.logger.setLevel(logging.INFO) if __debug__: RT.register(self) super(GtkUI, self).__init__(plugin_name) self.initialized = False self.config = None self.store = LabelStore() self.last_updated = None self._tries = 0 self._calls = [] self._extensions = [] self._update_funcs = [] self._cleanup_funcs = [] def enable(self): log.info("Initializing %s...", self.__class__.__name__) self._poll_init() def _poll_init(self): client.labelplus.is_initialized().addCallback(self._check_init) def _check_init(self, result): log.debug("Waiting for core to be initialized...") if result == True: client.labelplus.get_label_updates_dict().addCallback( self._finish_init) else: twisted.internet.reactor.callLater(INIT_POLLING_INTERVAL, self._poll_init) def _finish_init(self, result): log.debug("Resuming initialization...") try: info = client.connection_info() self.daemon = "%s@%s:%s" % (info[2], info[0], info[1]) self._load_config() self._update_store(result) self.initialized = True self._load_extensions() log.info("%s initialized", self.__class__.__name__) except: log.error("Error initializing %s", self.__class__.__name__) raise twisted.internet.reactor.callLater(0, self._update_loop) def _load_extensions(self): log.info("Loading extensions...") for ext in EXTENSIONS: try: log.debug("Initializing %s", ext.__name__) instance = ext(self) self._extensions.append(instance) if __debug__: RT.register(instance, ext.__name__) log.info("%s initialized", ext.__name__) except: log.exception("Error initializing %s", ext.__name__) # Section: Deinitialization def disable(self): log.info("Deinitializing %s...", self.__class__.__name__) labelplus.common.cancel_calls(self._calls) self._run_cleanup_funcs() self._unload_extensions() self._update_funcs = [] self._close_config() self._destroy_store() self.initialized = False if __debug__: RT.report() log.info("%s deinitialized", self.__class__.__name__) def _run_cleanup_funcs(self): while self._cleanup_funcs: func = self._cleanup_funcs.pop() try: func() except: log.exception("Failed to run %s()", func.__name__) def _unload_extensions(self): log.info("Unloading extensions...") while self._extensions: ext = self._extensions.pop() try: ext.unload() log.info("%s deinitialized", ext.__class__.__name__) except: log.exception("Error deinitializing %s", ext.__class__.__name__) def _destroy_store(self): if self.store: self.store.destroy() self.store = None # Section: Public def get_extension(self, name): for ext in self._extensions: if ext.__class__.__name__ == name: return ext return None def register_update_func(self, func): if func not in self._update_funcs: self._update_funcs.append(func) def deregister_update_func(self, func): if func in self._update_funcs: self._update_funcs.remove(func) def register_cleanup_func(self, func): if func not in self._cleanup_funcs: self._cleanup_funcs.append(func) def deregister_cleanup_func(self, func): if func in self._cleanup_funcs: self._cleanup_funcs.remove(func) # Section: Config def _load_config(self): config = deluge.configmanager.ConfigManager(GTKUI_CONFIG) # Workaround for 0.2.19.x that didn't use header if config.config.get("version") == 2: labelplus.common.config.set_version(config, 2) labelplus.common.config.init_config( config, labelplus.gtkui.config.CONFIG_DEFAULTS, labelplus.gtkui.config.CONFIG_VERSION, labelplus.gtkui.config.convert.CONFIG_SPECS) self._update_daemon_config(config) self._normalize_config(config) self.config = config def _close_config(self): if self.config: if self.initialized: self.config.save() deluge.configmanager.close(GTKUI_CONFIG) def _update_daemon_config(self, config): saved_daemons = deluge.component.get( "ConnectionManager").hostlist.get_hosts_info() if not saved_daemons: config["daemon"] = {} else: daemons = ["%s@%s:%s" % (x[3], x[1], x[2]) for x in saved_daemons] # Remove daemons from config if not in ConnectionManager hosts for daemon in list(config["daemon"].keys()): if "@localhost:" in daemon or "@127.0.0.1:" in daemon: continue if daemon not in daemons and daemon != self.daemon: del config["daemon"][daemon] if self.daemon not in config["daemon"]: config["daemon"][self.daemon] = copy.deepcopy( labelplus.gtkui.config.DAEMON_DEFAULTS) def _normalize_config(self, config): labelplus.common.normalize_dict(config.config, labelplus.gtkui.config.CONFIG_DEFAULTS) labelplus.common.normalize_dict( config["common"], labelplus.gtkui.config.CONFIG_DEFAULTS["common"]) for daemon in config["daemon"]: labelplus.common.normalize_dict( config["daemon"][daemon], labelplus.gtkui.config.DAEMON_DEFAULTS) # Section: Update def _update_loop(self): def on_timeout(): log.error("%s: %s", STR_UPDATE, LabelPlusError(ERR_TIMED_OUT)) if self.initialized: self._tries += 1 if self._tries < MAX_TRIES: self._calls.append( twisted.internet.reactor.callLater( THROTTLED_INTERVAL, self._update_loop)) else: log.error("%s: %s", STR_UPDATE, LabelPlusError(ERR_MAX_RETRY)) def process_result(result): if isinstance(result, Failure): if failure.check(LabelPlusError): log.error("%s: %s", STR_UPDATE, LabelPlusError(result.value.message)) interval = THROTTLED_INTERVAL else: return result else: self._tries = 0 interval = UPDATE_INTERVAL self._update_store(result) if self.initialized: self._calls.append( twisted.internet.reactor.callLater(interval, self._update_loop)) labelplus.common.clean_calls(self._calls) if self.initialized: iso_time = serialize_datetime(self.last_updated) deferred = client.labelplus.get_label_updates_dict(iso_time) labelplus.common.deferred_timeout(deferred, REQUEST_TIMEOUT, on_timeout, process_result, process_result) def _update_store(self, result): if not result: return update = result log.debug("Update: Type: %s, Timestamp: %s", update['type'], update['timestamp']) self.last_updated = deserialize_datetime(update['timestamp']) self.store.update(update['data']) for func in list(self._update_funcs): try: func(self.store) except: log.exception("Failed to run %s()", func.__name__)
class GtkUI(GtkPluginBase): # Section: Initialization def __init__(self, plugin_name): RT.logger.setLevel(logging.INFO) if __debug__: RT.register(self) super(GtkUI, self).__init__(plugin_name) self.initialized = False self.config = None self.store = LabelStore() self.last_updated = None self._tries = 0 self._calls = [] self._extensions = [] self._update_funcs = [] self._cleanup_funcs = [] def enable(self): log.info("Initializing %s...", self.__class__.__name__) self._poll_init() def _poll_init(self): client.labelplus.is_initialized().addCallback(self._check_init) def _check_init(self, result): log.debug("Waiting for core to be initialized...") if result == True: client.labelplus.get_label_updates().addCallback(self._finish_init) else: twisted.internet.reactor.callLater(INIT_POLLING_INTERVAL, self._poll_init) def _finish_init(self, result): log.debug("Resuming initialization...") try: info = client.connection_info() self.daemon = "%s@%s:%s" % (info[2], info[0], info[1]) self._load_config() self._update_store(result) self.initialized = True self._load_extensions() log.info("%s initialized", self.__class__.__name__) except: log.error("Error initializing %s", self.__class__.__name__) raise twisted.internet.reactor.callLater(0, self._update_loop) def _load_extensions(self): log.info("Loading extensions...") for ext in EXTENSIONS: try: log.debug("Initializing %s", ext.__name__) instance = ext(self) self._extensions.append(instance) if __debug__: RT.register(instance, ext.__name__) log.info("%s initialized", ext.__name__) except: log.exception("Error initializing %s", ext.__name__) # Section: Deinitialization def disable(self): log.info("Deinitializing %s...", self.__class__.__name__) labelplus.common.cancel_calls(self._calls) self._run_cleanup_funcs() self._unload_extensions() self._update_funcs = [] self._close_config() self._destroy_store() self.initialized = False if __debug__: RT.report() log.info("%s deinitialized", self.__class__.__name__) def _run_cleanup_funcs(self): while self._cleanup_funcs: func = self._cleanup_funcs.pop() try: func() except: log.exception("Failed to run %s()", func.func_name) def _unload_extensions(self): log.info("Unloading extensions...") while self._extensions: ext = self._extensions.pop() try: ext.unload() log.info("%s deinitialized", ext.__class__.__name__) except: log.exception("Error deinitializing %s", ext.__class__.__name__) def _destroy_store(self): if self.store: self.store.destroy() self.store = None # Section: Public def get_extension(self, name): for ext in self._extensions: if ext.__class__.__name__ == name: return ext return None def register_update_func(self, func): if func not in self._update_funcs: self._update_funcs.append(func) def deregister_update_func(self, func): if func in self._update_funcs: self._update_funcs.remove(func) def register_cleanup_func(self, func): if func not in self._cleanup_funcs: self._cleanup_funcs.append(func) def deregister_cleanup_func(self, func): if func in self._cleanup_funcs: self._cleanup_funcs.remove(func) # Section: Config def _load_config(self): config = deluge.configmanager.ConfigManager(GTKUI_CONFIG) # Workaround for 0.2.19.x that didn't use header if config.config.get("version") == 2: labelplus.common.config.set_version(config, 2) labelplus.common.config.init_config(config, labelplus.gtkui.config.CONFIG_DEFAULTS, labelplus.gtkui.config.CONFIG_VERSION, labelplus.gtkui.config.convert.CONFIG_SPECS) self._update_daemon_config(config) self._normalize_config(config) self.config = config def _close_config(self): if self.config: if self.initialized: self.config.save() deluge.configmanager.close(GTKUI_CONFIG) def _update_daemon_config(self, config): saved_daemons = deluge.component.get("ConnectionManager").config["hosts"] if not saved_daemons: config["daemon"] = {} else: daemons = ["%s@%s:%s" % (x[3], x[1], x[2]) for x in saved_daemons] # Remove daemons from config if not in ConnectionManager hosts for daemon in config["daemon"].keys(): if "@localhost:" in daemon or "@127.0.0.1:" in daemon: continue if daemon not in daemons and daemon != self.daemon: del config["daemon"][daemon] if self.daemon not in config["daemon"]: config["daemon"][self.daemon] = copy.deepcopy( labelplus.gtkui.config.DAEMON_DEFAULTS) def _normalize_config(self, config): labelplus.common.normalize_dict(config.config, labelplus.gtkui.config.CONFIG_DEFAULTS) labelplus.common.normalize_dict(config["common"], labelplus.gtkui.config.CONFIG_DEFAULTS["common"]) for daemon in config["daemon"]: labelplus.common.normalize_dict(config["daemon"][daemon], labelplus.gtkui.config.DAEMON_DEFAULTS) # Section: Update def _update_loop(self): def on_timeout(): log.error("%s: %s", STR_UPDATE, LabelPlusError(ERR_TIMED_OUT)) if self.initialized: self._tries += 1 if self._tries < MAX_TRIES: self._calls.append(twisted.internet.reactor.callLater( THROTTLED_INTERVAL, self._update_loop)) else: log.error("%s: %s", STR_UPDATE, LabelPlusError(ERR_MAX_RETRY)) def process_result(result): if isinstance(result, Failure): if (isinstance(result.value, DelugeRPCError) and result.value.exception_type == "LabelPlusError"): log.error("%s: %s", STR_UPDATE, LabelPlusError(result.value.exception_msg)) interval = THROTTLED_INTERVAL else: return result else: self._tries = 0 interval = UPDATE_INTERVAL self._update_store(result) if self.initialized: self._calls.append(twisted.internet.reactor.callLater(interval, self._update_loop)) labelplus.common.clean_calls(self._calls) if self.initialized: pickled_time = cPickle.dumps(self.last_updated) deferred = client.labelplus.get_label_updates(pickled_time) labelplus.common.deferred_timeout(deferred, REQUEST_TIMEOUT, on_timeout, process_result, process_result) def _update_store(self, result): if not result: return update = cPickle.loads(result) log.debug("Update: Type: %s, Timestamp: %s", update.type, update.timestamp) self.last_updated = update.timestamp self.store.update(update.data) for func in list(self._update_funcs): try: func(self.store) except: log.exception("Failed to run %s()", func.func_name)