def _instantiate_plugin(self): if not self._instantiate_queue.empty(): type_name, entrypoint, plugin_class = self._instantiate_queue.get() # if this plugin was already instantiated earlier, skip it; mark done if self.type_mapping[type_name].get(entrypoint.name, None) is None: # inject the entrypoint name into the class plugin_class._name = entrypoint.name success = False # ... and instantiate it (as long as its supposed to be singleton) try: if getattr(plugin_class, "is_singleton", False): msg.logMessage(f"Instantiating {entrypoint.name} plugin object.", level=msg.INFO) with load_timer() as elapsed: self.type_mapping[type_name][entrypoint.name] = plugin_class() msg.logMessage( f"{int(elapsed() * 1000)} ms elapsed while instantiating {entrypoint.name}", level=msg.INFO ) else: self.type_mapping[type_name][entrypoint.name] = plugin_class success = True except (Exception, SystemError) as ex: msg.logMessage( f"Unable to instantiate {entrypoint.name} plugin from module: {entrypoint.module_name}", msg.ERROR ) msg.logError(ex) msg.notifyMessage(repr(ex), title=f'An error occurred while starting the "{entrypoint.name}" plugin.') if success: msg.logMessage(f"Successfully collected {entrypoint.name} plugin.", level=msg.INFO) msg.showProgress(self._progress_count(), maxval=self._entrypoint_count()) self._notify(Filters.UPDATE) # mark it as completed self._instantiate_queue.task_done() # If this was the last plugin if self._load_queue.empty() and self._instantiate_queue.empty() and self.state in [State.INSTANTIATING, State.READY]: self.state = State.READY msg.logMessage("Plugin collection completed!") msg.hideProgress() self._notify(Filters.COMPLETE) if not self.state == State.READY: # if we haven't reached the last task, but there's nothing queued threads.invoke_as_event(self._instantiate_plugin) # return to the event loop, but come back soon
def loadPlugins(self): """ Load the candidate plugins that have been identified through a previous call to locatePlugins. For each plugin candidate look for its category, load it and store it in the appropriate slot of the ``category_mapping``. If a callback function is specified, call it before every load attempt. The ``plugin_info`` instance is passed as an argument to the callback. """ # print "%s.loadPlugins" % self.__class__ if not hasattr(self, "_candidates"): raise ValueError("locatePlugins must be called before loadPlugins") self.processed_plugins = [] self.loadqueue.extend(self._candidates) initial_len = len(self.loadqueue) for candidate_infofile, candidate_filepath, plugin_info in iter( self.loadqueue.popleft, (None, None, None)): # yield a message can be displayed to the user yield plugin_info self.load_marked_plugin(candidate_infofile=candidate_infofile, candidate_filepath=candidate_filepath, plugin_info=plugin_info) msg.showProgress(initial_len - len(self.loadqueue), maxval=initial_len) if not len(self.loadqueue): break # Remove candidates list since we don't need them any more and # don't need to take up the space delattr(self, "_candidates") # Load entry points self.load_entry_point_plugins() return self.processed_plugins
def _instantiate_plugin(self, instantiate_task_request: PluginTask=None): """ Instantiate a single plugin by request or from the queue. This is typically invoked by an event, and will re-post an event to the event queue to repeat until the task queue is emptied. """ instantiate_task = None if instantiate_task_request or not self._instantiate_queue.empty(): if instantiate_task_request: instantiate_task = instantiate_task_request else: instantiate_task = self._instantiate_queue.get() entrypoint = instantiate_task.entry_point type_name = instantiate_task.type_name plugin_class = instantiate_task.plugin_class # if this plugin was already instantiated earlier, skip it; mark done; also skips if the group isn't active if self.type_mapping.get(type_name, {entrypoint.name: True}).get(entrypoint.name, None) is None: instantiate_task.status = Status.Instantiating # inject the entrypoint name into the class plugin_class._name = entrypoint.name # ... and instantiate it (as long as its supposed to be singleton) plugin_object = plugin_class try: if getattr(plugin_class, "is_singleton", False): msg.logMessage(f"Instantiating {entrypoint.name} plugin object.", level=msg.INFO) with load_timer() as elapsed: self.type_mapping[type_name][entrypoint.name] = plugin_object = plugin_class() msg.logMessage( f"{int(elapsed() * 1000)} ms elapsed while instantiating {entrypoint.name}", level=msg.INFO ) else: self.type_mapping[type_name][entrypoint.name] = plugin_class except (Exception, SystemError) as ex: msg.logMessage( f"Unable to instantiate {entrypoint.name} plugin from module: {entrypoint.module_name}", msg.ERROR ) msg.logError(ex) msg.notifyMessage(repr(ex), title=f'An error occurred while starting the "{entrypoint.name}" plugin.') instantiate_task.status = Status.FailedInstantiate else: # inject useful info into plugin plugin_object._entrypoint_name = entrypoint.name plugin_object._plugin_type = type_name msg.logMessage(f"Successfully collected {entrypoint.name} plugin.", level=msg.INFO) self._notify(Filters.UPDATE) msg.showProgress(self._progress_count(), maxval=self._task_count()) # mark it as completed if instantiate_task_request is None: self._instantiate_queue.task_done() instantiate_task.status = Status.Success # If this was the last plugin if self._load_queue.empty() and self._instantiate_queue.empty(): msg.logMessage("Plugin collection completed!") msg.hideProgress() self._notify(Filters.COMPLETE) self.instantiating = False self._tasks.clear() elif instantiate_task_request is None: # if we haven't reached the last task, but there's nothing queued threads.invoke_as_event(self._instantiate_plugin) # return to the event loop, but come back soon