def getPluginNameAndModuleFromStream(self, infoFileObject, candidate_infofile=None):
        """
        Extract the name and module of a plugin from the
        content of the info file that describes it and which
        is stored in ``infoFileObject``.

        .. note:: Prefer using ``_extractCorePluginInfo``
                  instead, whenever possible...

        .. warning:: ``infoFileObject`` must be a file-like object:
                     either an opened file for instance or a string
                     buffer wrapped in a StringIO instance as another
                     example.

        .. note:: ``candidate_infofile`` must be provided
                  whenever possible to get better error messages.

        Return a 3-uple with the name of the plugin, its
        module and the config_parser used to gather the core
        data *in a tuple*, if the required info could be
        localised, else return ``(None,None,None)``.

        .. note:: This is supposed to be used internally by subclasses
        	      and decorators.
        """
        # parse the information buffer to get info about the plugin
        config_parser = ConfigParser.SafeConfigParser()
        try:
            config_parser.readfp(infoFileObject)
        except Exception,e:
            log.error("Could not parse the plugin file '%s' (exception raised was '%s')" % (candidate_infofile,e))
            log.debug(traceback.format_exc())
            return (None, None, None, None)
	def setPluginInfoExtension(self, ext):
		"""
		DEPRECATED(>1.9): for backward compatibility. Directly configure the
		IPluginLocator instance instead !
		
		.. warning:: This will only work if the strategy "info_ext" is
		             active for locating plugins.
		"""
		try:
			self.getPluginLocator().setPluginInfoExtension(ext)
		except KeyError:
			log.error("Current plugin locator doesn't support setting the plugin info extension.")
Ejemplo n.º 3
0
    def install(self, directory, plugin_info_filename):
        """
		Giving the plugin's info file (e.g. ``myplugin.yapsy-plugin``),
		and the directory where it is located, get all the files that
		define the plugin and copy them into the correct directory.
		
		Return ``True`` if the installation is a success, ``False`` if
		it is a failure.
		"""
        # start collecting essential info about the new plugin
        plugin_info, config_parser = self._gatherCorePluginInfo(
            directory, plugin_info_filename)
        # now determine the path of the file to execute,
        # depending on wether the path indicated is a
        # directory or a file
        if not (os.path.exists(plugin_info.path)
                or os.path.exists(plugin_info.path + ".py")):
            log.warning("Could not find the plugin's implementation for %s." %
                        plugin_info.name)
            return False
        if os.path.isdir(plugin_info.path):
            try:
                shutil.copytree(
                    plugin_info.path,
                    os.path.join(self.install_dir,
                                 os.path.basename(plugin_info.path)))
                shutil.copy(os.path.join(directory, plugin_info_filename),
                            self.install_dir)
            except:
                log.error("Could not install plugin: %s." % plugin_info.name)
                return False
            else:
                return True
        elif os.path.isfile(plugin_info.path + ".py"):
            try:
                shutil.copy(plugin_info.path + ".py", self.install_dir)
                shutil.copy(os.path.join(directory, plugin_info_filename),
                            self.install_dir)
            except:
                log.error("Could not install plugin: %s." % plugin_info.name)
                return False
            else:
                return True
        else:
            return False
	def install(self, directory, plugin_info_filename):
		"""
		Giving the plugin's info file (e.g. ``myplugin.yapsy-plugin``),
		and the directory where it is located, get all the files that
		define the plugin and copy them into the correct directory.
		
		Return ``True`` if the installation is a success, ``False`` if
		it is a failure.
		"""
		# start collecting essential info about the new plugin
		plugin_info, config_parser = self._gatherCorePluginInfo(directory, plugin_info_filename)
		# now determine the path of the file to execute,
		# depending on wether the path indicated is a
		# directory or a file
		if not (os.path.exists(plugin_info.path) or os.path.exists(plugin_info.path+".py") ):
			log.warning("Could not find the plugin's implementation for %s." % plugin_info.name)
			return False
		if os.path.isdir(plugin_info.path):
			try:
				shutil.copytree(plugin_info.path,
								os.path.join(self.install_dir,os.path.basename(plugin_info.path)))
				shutil.copy(os.path.join(directory, plugin_info_filename),
							self.install_dir)
			except:
				log.error("Could not install plugin: %s." % plugin_info.name)
				return False
			else:
				return True
		elif os.path.isfile(plugin_info.path+".py"):
			try:
				shutil.copy(plugin_info.path+".py",
							self.install_dir)
				shutil.copy(os.path.join(directory, plugin_info_filename),
						   self.install_dir)
			except:
				log.error("Could not install plugin: %s." % plugin_info.name)
				return False
			else:
				return True
		else:
			return False
Ejemplo n.º 5
0
	def locatePlugins(self):
		"""
		Walk through the plugins' places and look for plugins.

		Return the candidates and number of plugins found.
		"""
# 		print "%s.locatePlugins" % self.__class__
		_candidates = []
		_discovered = {}
		for directory in map(os.path.abspath, self.plugins_places):
			# first of all, is it a directory :)
			if not os.path.isdir(directory):
				log.debug("%s skips %s (not a directory)" % (self.__class__.__name__, directory))
				continue
			if self.recursive:
				debug_txt_mode = "recursively"
				walk_iter = os.walk(directory)
			else:
				debug_txt_mode = "non-recursively"
				walk_iter = [(directory,[],os.listdir(directory))]				
			# iteratively walks through the directory
			log.debug("%s walks (%s) into directory: %s" % (self.__class__.__name__, debug_txt_mode, directory))
			for item in walk_iter:
				dirpath = item[0]
				for filename in item[2]:
					# print "testing candidate file %s" % filename
					for analyzer in self._analyzers:
						# print "... with analyzer %s" % analyzer.name
						# eliminate the obvious non plugin files
						if not analyzer.isValidPlugin(filename):
							log.debug("%s is not a valid plugin for strategy %s" % (filename, analyzer.name))
							continue
						candidate_infofile = os.path.join(dirpath, filename)
						if candidate_infofile in _discovered:
							log.debug("%s (with strategy %s) rejected because already discovered" % (candidate_infofile, analyzer.name))
							continue
						log.debug("%s found a candidate:\n    %s" % (self.__class__.__name__, candidate_infofile))
#						print candidate_infofile
						plugin_info = self._getInfoForPluginFromAnalyzer(analyzer, dirpath, filename)
						if plugin_info is None:
							log.warning("Plugin candidate '%s'  rejected by strategy '%s'" % (candidate_infofile, analyzer.name))
							break # we consider this was the good strategy to use for: it failed -> not a plugin -> don't try another strategy
						# now determine the path of the file to execute,
						# depending on wether the path indicated is a
						# directory or a file
#					print plugin_info.path
						# Remember all the files belonging to a discovered
						# plugin, so that strategies (if several in use) won't
						# collide
						if os.path.isdir(plugin_info.path):
							candidate_filepath = os.path.join(plugin_info.path, "__init__")
							# it is a package, adds all the files concerned
							for _file in os.listdir(plugin_info.path):
								if _file.endswith(".py"):
									self._discovered_plugins[os.path.join(plugin_info.path, _file)] = candidate_filepath
									_discovered[os.path.join(plugin_info.path, _file)] = candidate_filepath
						elif (plugin_info.path.endswith(".py") and os.path.isfile(plugin_info.path)) or os.path.isfile(plugin_info.path+".py"):
							candidate_filepath = plugin_info.path
							if candidate_filepath.endswith(".py"):
								candidate_filepath = candidate_filepath[:-3]
							# it is a file, adds it
							self._discovered_plugins[".".join((plugin_info.path, "py"))] = candidate_filepath
							_discovered[".".join((plugin_info.path, "py"))] = candidate_filepath
						else:
							log.error("Plugin candidate rejected: cannot find the file or directory module for '%s'" % (candidate_infofile))
							break
#					print candidate_filepath
						_candidates.append((candidate_infofile, candidate_filepath, plugin_info))
						# finally the candidate_infofile must not be discovered again
						_discovered[candidate_infofile] = candidate_filepath
						self._discovered_plugins[candidate_infofile] = candidate_filepath
#						print "%s found by strategy %s" % (candidate_filepath, analyzer.name)
		return _candidates, len(_candidates)
	def loadPlugins(self, callback=None):
		"""
		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")

		processed_plugins = []
		for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
			# make sure to attribute a unique module name to the one
			# that is about to be loaded
			plugin_module_name_template = NormalizePluginNameForModuleName("yapsy_loaded_plugin_" + plugin_info.name) + "_%d"
			for plugin_name_suffix in range(len(sys.modules)):
				plugin_module_name =  plugin_module_name_template % plugin_name_suffix
				if plugin_module_name not in sys.modules:
					break
			
			# tolerance on the presence (or not) of the py extensions
			if candidate_filepath.endswith(".py"):
				candidate_filepath = candidate_filepath[:-3]
			# if a callback exists, call it before attempting to load
			# the plugin so that a message can be displayed to the
			# user
			if callback is not None:
				callback(plugin_info)
			# cover the case when the __init__ of a package has been
			# explicitely indicated
			if "__init__" in  os.path.basename(candidate_filepath):
				candidate_filepath = os.path.dirname(candidate_filepath)
			try:
				# use imp to correctly load the plugin as a module
				if os.path.isdir(candidate_filepath):
					candidate_module = imp.load_module(plugin_module_name,None,candidate_filepath,("py","r",imp.PKG_DIRECTORY))
				else:
					with open(candidate_filepath+".py","r") as plugin_file:
						candidate_module = imp.load_module(plugin_module_name,plugin_file,candidate_filepath+".py",("py","r",imp.PY_SOURCE))
			except Exception:
				exc_info = sys.exc_info()
				log.error("Unable to import plugin: %s" % candidate_filepath, exc_info=exc_info)
				plugin_info.error = exc_info
				processed_plugins.append(plugin_info)
				continue
			processed_plugins.append(plugin_info)
			if "__init__" in  os.path.basename(candidate_filepath):
				sys.path.remove(plugin_info.path)
			# now try to find and initialise the first subclass of the correct plugin interface
			for element in (getattr(candidate_module,name) for name in dir(candidate_module)):
				plugin_info_reference = None
				for category_name in self.categories_interfaces:
					try:
						is_correct_subclass = issubclass(element, self.categories_interfaces[category_name])
					except Exception:
						continue
					if is_correct_subclass and element is not self.categories_interfaces[category_name]:
							current_category = category_name
							if candidate_infofile not in self._category_file_mapping[current_category]:
								# we found a new plugin: initialise it and search for the next one
								if not plugin_info_reference:
									try:
										plugin_info.plugin_object = self.instanciateElement(element)
										plugin_info_reference = plugin_info
									except Exception:
										exc_info = sys.exc_info()
										log.error("Unable to create plugin object: %s" % candidate_filepath, exc_info=exc_info)
										plugin_info.error = exc_info
										break # If it didn't work once it wont again
								plugin_info.categories.append(current_category)
								self.category_mapping[current_category].append(plugin_info_reference)
								self._category_file_mapping[current_category].append(candidate_infofile)
		# Remove candidates list since we don't need them any more and
		# don't need to take up the space
		delattr(self, '_candidates')
		return processed_plugins
Ejemplo n.º 7
0
    def loadPlugins(self, callback=None, callback_after=None):
        """
		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``.

		You can specify 2 callbacks: callback, and callback_after. If either of these are passed a function, (in the case of callback), it will get called before each plugin load attempt and (for callback_after), after each 
		attempt.  The ``plugin_info`` instance is passed as an argument to
		each callback. This is meant to facilitate code that needs to run for each plugin, such as adding the directory it resides in to sys.path (so imports of other files in the plugin's directory work correctly). You can use callback_after to remove anything you added to the path.
		"""
        # 		print "%s.loadPlugins" % self.__class__
        if not hasattr(self, '_candidates'):
            raise ValueError("locatePlugins must be called before loadPlugins")

        processed_plugins = []
        for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
            # make sure to attribute a unique module name to the one
            # that is about to be loaded
            plugin_module_name_template = NormalizePluginNameForModuleName(
                "yapsy_loaded_plugin_" + plugin_info.name) + "_%d"
            for plugin_name_suffix in range(len(sys.modules)):
                plugin_module_name = plugin_module_name_template % plugin_name_suffix
                if plugin_module_name not in sys.modules:
                    break

            # tolerance on the presence (or not) of the py extensions
            if candidate_filepath.endswith(".py"):
                candidate_filepath = candidate_filepath[:-3]
            # if a callback exists, call it before attempting to load
            # the plugin so that a message can be displayed to the
            # user
            if callback is not None:
                callback(plugin_info)
            # cover the case when the __init__ of a package has been
            # explicitely indicated
            if "__init__" in os.path.basename(candidate_filepath):
                candidate_filepath = os.path.dirname(candidate_filepath)
            try:
                candidate_module = PluginManager._importModule(
                    plugin_module_name, candidate_filepath)
            except Exception:
                exc_info = sys.exc_info()
                log.error("Unable to import plugin: %s" % candidate_filepath,
                          exc_info=exc_info)
                plugin_info.error = exc_info
                processed_plugins.append(plugin_info)
                continue

            processed_plugins.append(plugin_info)
            if "__init__" in os.path.basename(candidate_filepath):
                sys.path.remove(plugin_info.path)
            # now try to find and initialise the first subclass of the correct plugin interface
            last_failed_attempt_message = None
            for element, element_name in ((getattr(candidate_module,
                                                   name), name)
                                          for name in dir(candidate_module)):
                plugin_info_reference = None
                for category_name in self.categories_interfaces:
                    try:
                        is_correct_subclass = issubclass(
                            element, self.categories_interfaces[category_name])
                    except Exception:
                        exc_info = sys.exc_info()
                        log.debug(
                            "correct subclass tests failed for: %s in %s" %
                            (element_name, candidate_filepath),
                            exc_info=exc_info)
                        continue
                    if is_correct_subclass and element is not self.categories_interfaces[
                            category_name]:
                        current_category = category_name
                        if candidate_infofile not in self._category_file_mapping[
                                current_category]:
                            # we found a new plugin: initialise it and search for the next one
                            if not plugin_info_reference:
                                try:
                                    plugin_info.plugin_object = self.instanciateElementWithImportInfo(
                                        element, element_name,
                                        plugin_module_name, candidate_filepath)
                                    plugin_info_reference = plugin_info
                                except Exception:
                                    exc_info = sys.exc_info()
                                    last_failed_attempt_message = "Unable to create plugin object: %s" % candidate_filepath
                                    log.debug(last_failed_attempt_message,
                                              exc_info=exc_info)
                                    plugin_info.error = exc_info
                                    break  # If it didn't work once it wont again
                                else:
                                    last_failed_attempt_message = None
                            plugin_info.categories.append(current_category)
                            self.category_mapping[current_category].append(
                                plugin_info_reference)
                            self._category_file_mapping[
                                current_category].append(candidate_infofile)
                            #Everything is loaded and instantiated for this plugin now
                            if callback_after is not None:
                                callback_after(plugin_info)
            else:
                if last_failed_attempt_message:
                    log.error(last_failed_attempt_message,
                              exc_info=plugin_info.error)

        # Remove candidates list since we don't need them any more and
        # don't need to take up the space
        delattr(self, '_candidates')
        return processed_plugins
Ejemplo n.º 8
0
	def locatePlugins(self):
		"""
		Walk through the plugins' places and look for plugins.

		Return the candidates and number of plugins found.
		"""
# 		print "%s.locatePlugins" % self.__class__
		_candidates = []
		_discovered = {}
		for directory in map(os.path.abspath, self.plugins_places):
			# first of all, is it a directory :)
			if not os.path.isdir(directory):
				log.debug("%s skips %s (not a directory)" % (self.__class__.__name__, directory))
				continue
			if self.recursive:
				debug_txt_mode = "recursively"
				walk_iter = os.walk(directory)
			else:
				debug_txt_mode = "non-recursively"
				walk_iter = [(directory,[],os.listdir(directory))]				
			# iteratively walks through the directory
			log.debug("%s walks (%s) into directory: %s" % (self.__class__.__name__, debug_txt_mode, directory))
			for item in walk_iter:
				dirpath = item[0]
				for filename in item[2]:
					# print "testing candidate file %s" % filename
					for analyzer in self._analyzers:
						# print "... with analyzer %s" % analyzer.name
						# eliminate the obvious non plugin files
						if not analyzer.isValidPlugin(filename):
							log.debug("%s is not a valid plugin for strategy %s" % (filename, analyzer.name))
							continue
						candidate_infofile = os.path.join(dirpath, filename)
						if candidate_infofile in _discovered:
							log.debug("%s (with strategy %s) rejected because already discovered" % (candidate_infofile, analyzer.name))
							continue
						log.debug("%s found a candidate:\n    %s" % (self.__class__.__name__, candidate_infofile))
#						print candidate_infofile
						plugin_info = self._getInfoForPluginFromAnalyzer(analyzer, dirpath, filename)
						if plugin_info is None:
							log.warning("Plugin candidate '%s'  rejected by strategy '%s'" % (candidate_infofile, analyzer.name))
							break # we consider this was the good strategy to use for: it failed -> not a plugin -> don't try another strategy
						# now determine the path of the file to execute,
						# depending on wether the path indicated is a
						# directory or a file
#					print plugin_info.path
						# Remember all the files belonging to a discovered
						# plugin, so that strategies (if several in use) won't
						# collide
						if os.path.isdir(plugin_info.path):
							candidate_filepath = os.path.join(plugin_info.path, "__init__")
							# it is a package, adds all the files concerned
							for _file in os.listdir(plugin_info.path):
								if _file.endswith(".py"):
									self._discovered_plugins[os.path.join(plugin_info.path, _file)] = candidate_filepath
									_discovered[os.path.join(plugin_info.path, _file)] = candidate_filepath
						elif (plugin_info.path.endswith(".py") and os.path.isfile(plugin_info.path)) or os.path.isfile(plugin_info.path+".py"):
							candidate_filepath = plugin_info.path
							if candidate_filepath.endswith(".py"):
								candidate_filepath = candidate_filepath[:-3]
							# it is a file, adds it
							self._discovered_plugins[".".join((plugin_info.path, "py"))] = candidate_filepath
							_discovered[".".join((plugin_info.path, "py"))] = candidate_filepath
						else:
							log.error("Plugin candidate rejected: cannot find the file or directory module for '%s'" % (candidate_infofile))
							break
#					print candidate_filepath
						_candidates.append((candidate_infofile, candidate_filepath, plugin_info))
						# finally the candidate_infofile must not be discovered again
						_discovered[candidate_infofile] = candidate_filepath
						self._discovered_plugins[candidate_infofile] = candidate_filepath
#						print "%s found by strategy %s" % (candidate_filepath, analyzer.name)
		return _candidates, len(_candidates)
	def installFromZIP(self, plugin_ZIP_filename):
		"""
		Giving the plugin's zip file (e.g. ``myplugin.zip``), check
		that their is a valid info file in it and correct all the
		plugin files into the correct directory.
		
		.. warning:: Only available for python 2.6 and later.
		
		Return ``True`` if the installation is a success, ``False`` if
		it is a failure.
		"""
		if not os.path.isfile(plugin_ZIP_filename):
			log.warning("Could not find the plugin's zip file at '%s'." % plugin_ZIP_filename)
			return False
		try:
			candidateZipFile = zipfile.ZipFile(plugin_ZIP_filename)
			first_bad_file = candidateZipFile.testzip()
			if first_bad_file:
				raise Exception("Corrupted ZIP with first bad file '%s'" % first_bad_file)
		except Exception as e:
			log.warning("Invalid zip file '%s' (error: %s)." % (plugin_ZIP_filename,e))
			return False
		zipContent = candidateZipFile.namelist()
		log.info("Investigating the content of a zip file containing: '%s'" % zipContent)
		log.info("Sanity checks on zip's contained files (looking for hazardous path symbols).")	
		# check absence of root path and ".." shortcut that would
		# send the file oustide the desired directory
		for containedFileName in zipContent:
			# WARNING: the sanity checks below are certainly not
			# exhaustive (maybe we could do something a bit smarter by
			# using os.path.expanduser, os.path.expandvars and
			# os.path.normpath)
			if containedFileName.startswith("/"):
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') starts with '/'" % containedFileName)
				return False
			if containedFileName.startswith(r"\\") or containedFileName.startswith("//"):
				log.warning(r"Unsecure zip file, rejected because one of its file paths ('%s') starts with '\\'" % containedFileName)
				return False
			if os.path.splitdrive(containedFileName)[0]:
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') starts with a drive letter" % containedFileName)
				return False
			if os.path.isabs(containedFileName):
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') is absolute" % containedFileName)
				return False
			pathComponent = os.path.split(containedFileName)
			if ".." in pathComponent:
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') contains '..'" % containedFileName)	
				return False
			if "~" in pathComponent:
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') contains '~'" % containedFileName)	
				return False
		infoFileCandidates = [filename for filename in zipContent if os.path.dirname(filename)==""]
		if not infoFileCandidates:
			log.warning("Zip file structure seems wrong in '%s', no info file found." % plugin_ZIP_filename)
			return False
		isValid = False
		log.info("Looking for the zipped plugin's info file among '%s'" % infoFileCandidates)
		for infoFileName in infoFileCandidates:
			infoFile = candidateZipFile.read(infoFileName)
			log.info("Assuming the zipped plugin info file to be '%s'" % infoFileName)
			pluginName,moduleName,_ = self._getPluginNameAndModuleFromStream(StringIO(str(infoFile,encoding="utf-8")))
			if moduleName is None:
					continue
			log.info("Checking existence of the expected module '%s' in the zip file" % moduleName)
			if moduleName in zipContent or os.path.join(moduleName,"__init__.py") in zipContent:
				isValid = True
				break
		if not isValid:
			log.warning("Zip file structure seems wrong in '%s', "
							"could not match info file with the implementation of plugin '%s'." % (plugin_ZIP_filename,pluginName))
			return False
		else:
			try:
				candidateZipFile.extractall(self.install_dir)
				return True
			except Exception as e:
				log.error("Could not install plugin '%s' from zip file '%s' (exception: '%s')." % (pluginName,plugin_ZIP_filename,e))
				return False
Ejemplo n.º 10
0
	def loadPlugins(self, callback=None):
		"""
		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.

		Return a list of processed ``plugin_info`` instances. For
		any plugins which were not loaded, the ``error`` attribute will
		be populated with a (type, value, traceback) tuple, from
		sys.exc_info().
		"""
# 		print "%s.loadPlugins" % self.__class__		
		if not hasattr(self, '_candidates'):
			raise ValueError("locatePlugins must be called before loadPlugins")

		processed_plugins = []
		for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
			# if a callback exists, call it before attempting to load
			# the plugin so that a message can be displayed to the
			# user
			if callback is not None:
				callback(plugin_info)
			# now execute the file and get its content into a
			# specific dictionnary
			candidate_globals = {"__file__":candidate_filepath+".py"}
			if "__init__" in  os.path.basename(candidate_filepath):
				sys.path.append(plugin_info.path)				
			try:
				candidateMainFile = open(candidate_filepath+".py","r")	
				exec(candidateMainFile,candidate_globals)
				processed_plugins.append(plugin_info)
			except Exception:
				log.error("Unable to execute the code in plugin: %s" % candidate_filepath, exc_info=True)
				if "__init__" in  os.path.basename(candidate_filepath):
					sys.path.remove(plugin_info.path)
				plugin_info.error = sys.exc_info()
				processed_plugins.append(plugin_info)
				continue
			
			if "__init__" in  os.path.basename(candidate_filepath):
				sys.path.remove(plugin_info.path)
			# now try to find and initialise the first subclass of the correct plugin interface
			for element in candidate_globals.itervalues():
				current_category = None
				for category_name in self.categories_interfaces:
					try:
						is_correct_subclass = issubclass(element, self.categories_interfaces[category_name])
					except:
						continue
					if is_correct_subclass:
						if element is not self.categories_interfaces[category_name]:
							current_category = category_name
							break
				if current_category is not None:
					if not (candidate_infofile in self._category_file_mapping[current_category]): 
						# we found a new plugin: initialise it and search for the next one
						plugin_info.plugin_object = element()
						plugin_info.category = current_category
						self.category_mapping[current_category].append(plugin_info)
						self._category_file_mapping[current_category].append(candidate_infofile)
						current_category = None
					break

			if not (plugin_info.plugin_object or plugin_info.error):
				log.warning('No plubin object found for "%s": it may not do anything! Check that the plugin '
						+ 'extends IPlugin, and if there is an __init__ file that it imports '
						+ 'the class which extends IPlugin.', plugin_info.name)

		# Remove candidates list since we don't need them any more and
		# don't need to take up the space
		delattr(self, '_candidates')
		return processed_plugins
Ejemplo n.º 11
0
    def loadPlugins(self, callback=None):
        if not hasattr(self, '_candidates'):
            raise ValueError("locatePlugins must be called before loadPlugins")

        sys.path.extend(self.getPluginLocator().plugins_places)

        processed_plugins = []
        for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
            # make sure to attribute a unique module name to the one
            # that is about to be loaded
            plugin_module_name_template = NormalizePluginNameForModuleName(
                "yapsy_loaded_plugin_" + plugin_info.name) + "_%d"
            for plugin_name_suffix in range(len(sys.modules)):
                plugin_module_name = plugin_module_name_template % plugin_name_suffix
                if plugin_module_name not in sys.modules:
                    break

            # tolerance on the presence (or not) of the py extensions
            if candidate_filepath.endswith(".py"):
                candidate_filepath = candidate_filepath[:-3]
            # if a callback exists, call it before attempting to load
            # the plugin so that a message can be displayed to the
            # user
            if callback is not None:
                callback(plugin_info)
            # cover the case when the __init__ of a package has been
            # explicitly indicated
            if "__init__" in os.path.basename(candidate_filepath):
                candidate_filepath = os.path.dirname(candidate_filepath)
            try:
                # use imp to correctly load the plugin as a module
                if os.path.isdir(candidate_filepath):
                    candidate_module = imp.load_module(
                        plugin_module_name, None, candidate_filepath,
                        ("py", "r", imp.PKG_DIRECTORY))
                else:
                    with open(candidate_filepath + ".py", "r") as plugin_file:
                        candidate_module = imp.load_module(
                            plugin_module_name, plugin_file,
                            candidate_filepath + ".py",
                            ("py", "r", imp.PY_SOURCE))
            except Exception:
                exc_info = sys.exc_info()
                log.error("Unable to import plugin: %s" % candidate_filepath,
                          exc_info=exc_info)
                plugin_info.error = exc_info
                processed_plugins.append(plugin_info)
                continue
            processed_plugins.append(plugin_info)
            if "__init__" in os.path.basename(candidate_filepath):
                sys.path.remove(plugin_info.path)
            # now try to find and initialise the first subclass of the correct plugin interface
            for element in (getattr(candidate_module, name)
                            for name in dir(candidate_module)):
                plugin_info_reference = None
                for category_name in self.categories_interfaces:
                    try:
                        is_correct_subclass = issubclass(
                            element, self.categories_interfaces[category_name])
                    except Exception:
                        continue
                    if is_correct_subclass and element is not self.categories_interfaces[
                            category_name]:
                        current_category = category_name
                        if candidate_infofile not in self._category_file_mapping[
                                current_category]:
                            # we found a new plugin: initialise it and search for the next one
                            plugins = self.config.get('plugins', {})
                            plugin_mode = plugins.get('mode', 'blacklist')
                            if plugin_mode == 'whitelist' and plugin_info.name not in plugins.get(
                                    current_category, []):
                                break
                            elif plugin_mode == 'blacklist' and plugin_info.name in plugins.get(
                                    current_category, []):
                                break
                            if not plugin_info_reference:
                                try:
                                    plugin_constructer_args = self.config.get(
                                        'plugin_config',
                                        {}).get(current_category,
                                                {}).get(plugin_info.name, {})
                                    if isinstance(plugin_constructer_args,
                                                  (list, set)):
                                        plugin_info.plugin_object = element(
                                            *plugin_constructer_args)
                                    elif isinstance(plugin_constructer_args,
                                                    dict):
                                        plugin_info.plugin_object = element(
                                            **plugin_constructer_args)
                                    else:
                                        plugin_info.plugin_object = element()
                                    plugin_info_reference = plugin_info
                                except Exception:
                                    exc_info = sys.exc_info()
                                    log.error(
                                        "Unable to create plugin object: {}".
                                        format(candidate_filepath),
                                        exc_info=exc_info)
                                    plugin_info.error = exc_info
                                    break  # If it didn't work once it wont again
                            plugin_info.categories.append(current_category)
                            self.category_mapping[current_category].append(
                                plugin_info_reference)
                            self._category_file_mapping[
                                current_category].append(candidate_infofile)
        # Remove candidates list since we don't need them any more and
        # don't need to take up the space
        delattr(self, '_candidates')

        # Sort Plugins
        for category_name, plugin_infos in self.category_mapping.items():
            plugin_names = self.config.get('plugin_order',
                                           {}).get(category_name, [])
            plugin_rankings = {
                plugin_name: plugin_ranking
                for plugin_name, plugin_ranking in zip(
                    plugin_names, range(0, len(plugin_names)))
            }
            plugin_infos.sort(key=lambda plugin_info: plugin_rankings.get(
                plugin_info.name,
                len(plugin_names) + 1))

        return processed_plugins
Ejemplo n.º 12
0
    def installFromZIP(self, plugin_ZIP_filename):
        """
		Giving the plugin's zip file (e.g. ``myplugin.zip``), check
		that their is a valid info file in it and correct all the
		plugin files into the correct directory.
		
		.. warning:: Only available for python 2.6 and later.
		
		Return ``True`` if the installation is a success, ``False`` if
		it is a failure.
		"""
        if sys.version_info < (2, 6):
            raise NotImplementedError(
                "Installing fom a ZIP file is only supported for Python2.6 and later."
            )
        if not os.path.isfile(plugin_ZIP_filename):
            log.warning("Could not find the plugin's zip file at '%s'." %
                        plugin_ZIP_filename)
            return False
        candidateZipFile = zipfile.ZipFile(plugin_ZIP_filename)
        if candidateZipFile.testzip() is not None:
            log.warning("Corruption detected in Zip file '%s'." %
                        plugin_ZIP_filename)
            return False
        zipContent = candidateZipFile.namelist()
        log.info("Investigating the content of a zip file containing: '%s'" %
                 zipContent)
        log.info(
            "Sanity checks on zip's contained files (looking for hazardous path symbols)."
        )
        # check absence of root path and ".." shortcut that would
        # send the file oustide the desired directory
        for containedFileName in zipContent:
            # WARNING: the sanity checks below are certainly not
            # exhaustive (maybe we could do something a bit smarter by
            # using os.path.expanduser, os.path.expandvars and
            # os.path.normpath)
            if containedFileName.startswith("/"):
                log.warning(
                    "Unsecure zip file, rejected because one of its file paths ('%s') starts with '/'"
                    % containedFileName)
                return False
            if containedFileName.startswith(
                    r"\\") or containedFileName.startswith("//"):
                log.warning(
                    r"Unsecure zip file, rejected because one of its file paths ('%s') starts with '\\'"
                    % containedFileName)
                return False
            if os.path.splitdrive(containedFileName)[0]:
                log.warning(
                    "Unsecure zip file, rejected because one of its file paths ('%s') starts with a drive letter"
                    % containedFileName)
                return False
            if os.path.isabs(containedFileName):
                log.warning(
                    "Unsecure zip file, rejected because one of its file paths ('%s') is absolute"
                    % containedFileName)
                return False
            pathComponent = os.path.split(containedFileName)
            if ".." in pathComponent:
                log.warning(
                    "Unsecure zip file, rejected because one of its file paths ('%s') contains '..'"
                    % containedFileName)
                return False
            if "~" in pathComponent:
                log.warning(
                    "Unsecure zip file, rejected because one of its file paths ('%s') contains '~'"
                    % containedFileName)
                return False
        infoFileCandidates = [
            filename for filename in zipContent
            if os.path.dirname(filename) == ""
        ]
        if not infoFileCandidates:
            log.warning(
                "Zip file structure seems wrong in '%s', no info file found." %
                plugin_ZIP_filename)
            return False
        isValid = False
        log.info("Looking for the zipped plugin's info file among '%s'" %
                 infoFileCandidates)
        for infoFileName in infoFileCandidates:
            infoFile = candidateZipFile.read(infoFileName)
            log.info("Assuming the zipped plugin info file to be '%s'" %
                     infoFileName)
            pluginName, moduleName, _ = self._getPluginNameAndModuleFromStream(
                StringIO.StringIO(infoFile))
            if moduleName is None:
                continue
            log.info(
                "Checking existence of the expected module '%s' in the zip file"
                % moduleName)
            if moduleName in zipContent or os.path.join(
                    moduleName, "__init__.py") in zipContent:
                isValid = True
                break
        if not isValid:
            log.warning(
                "Zip file structure seems wrong in '%s', "
                "could not match info file with the implementation of plugin '%s'."
                % (plugin_ZIP_filename, pluginName))
            return False
        else:
            try:
                candidateZipFile.extractall(self.install_dir)
                return True
            except Exception, e:
                log.error(
                    "Could not install plugin '%s' from zip file '%s' (exception: '%s')."
                    % (pluginName, plugin_ZIP_filename, e))
                return False
Ejemplo n.º 13
0
	def loadPlugins(self, callback=None):
		"""
		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")

		processed_plugins = []
		for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
			# tolerance on the presence (or not) of the py extensions
			if candidate_filepath.endswith(".py"):
				candidate_filepath = candidate_filepath[:-3]
			# if a callback exists, call it before attempting to load
			# the plugin so that a message can be displayed to the
			# user
			if callback is not None:
				callback(plugin_info)
			# now execute the file and get its content into a
			# specific dictionnary
			candidate_globals = {"__file__":candidate_filepath+".py"}
			if "__init__" in  os.path.basename(candidate_filepath):
				sys.path.append(plugin_info.path)				
			try:
				candidateMainFile = open(candidate_filepath+".py","r")	
				exec(candidateMainFile,candidate_globals)
			except Exception:
				exc_info = sys.exc_info()
				log.error("Unable to execute the code in plugin: %s" % candidate_filepath, exc_info=exc_info)
				if "__init__" in  os.path.basename(candidate_filepath):
					sys.path.remove(plugin_info.path)
				plugin_info.error = exc_info
				processed_plugins.append(plugin_info)
				continue
			
			processed_plugins.append(plugin_info)
			if "__init__" in  os.path.basename(candidate_filepath):
				sys.path.remove(plugin_info.path)
			# now try to find and initialise the first subclass of the correct plugin interface
			for element in candidate_globals.itervalues():
				plugin_info_reference = None
				for category_name in self.categories_interfaces:
					try:
						is_correct_subclass = issubclass(element, self.categories_interfaces[category_name])
					except TypeError:
						continue
					if is_correct_subclass and element is not self.categories_interfaces[category_name]:
							current_category = category_name
							if candidate_infofile not in self._category_file_mapping[current_category]:
								# we found a new plugin: initialise it and search for the next one
								if not plugin_info_reference:
									plugin_info.plugin_object = element()
									plugin_info_reference = plugin_info
								plugin_info.categories.append(current_category)
								self.category_mapping[current_category].append(plugin_info_reference)
								self._category_file_mapping[current_category].append(candidate_infofile)
		# Remove candidates list since we don't need them any more and
		# don't need to take up the space
		delattr(self, '_candidates')
		return processed_plugins
Ejemplo n.º 14
0
    def loadPlugins(self, callback=None):
        if not hasattr(self, '_candidates'):
            raise ValueError("locatePlugins must be called before loadPlugins")

        sys.path.extend(self.getPluginLocator().plugins_places)

        processed_plugins = []
        for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
            # make sure to attribute a unique module name to the one
            # that is about to be loaded
            plugin_module_name_template = NormalizePluginNameForModuleName(
                    "yapsy_loaded_plugin_" + plugin_info.name) + "_%d"
            for plugin_name_suffix in range(len(sys.modules)):
                plugin_module_name = plugin_module_name_template % plugin_name_suffix
                if plugin_module_name not in sys.modules:
                    break

            # tolerance on the presence (or not) of the py extensions
            if candidate_filepath.endswith(".py"):
                candidate_filepath = candidate_filepath[:-3]
            # if a callback exists, call it before attempting to load
            # the plugin so that a message can be displayed to the
            # user
            if callback is not None:
                callback(plugin_info)
            # cover the case when the __init__ of a package has been
            # explicitly indicated
            if "__init__" in os.path.basename(candidate_filepath):
                candidate_filepath = os.path.dirname(candidate_filepath)
            try:
                # use imp to correctly load the plugin as a module
                if os.path.isdir(candidate_filepath):
                    candidate_module = imp.load_module(plugin_module_name, None,
                                                       candidate_filepath, (
                                                           "py", "r",
                                                           imp.PKG_DIRECTORY))
                else:
                    with open(candidate_filepath + ".py", "r") as plugin_file:
                        candidate_module = imp.load_module(plugin_module_name,
                                                           plugin_file,
                                                           candidate_filepath + ".py",
                                                           ("py", "r",
                                                            imp.PY_SOURCE))
            except Exception:
                exc_info = sys.exc_info()
                log.error("Unable to import plugin: %s" % candidate_filepath,
                          exc_info=exc_info)
                plugin_info.error = exc_info
                processed_plugins.append(plugin_info)
                continue
            processed_plugins.append(plugin_info)
            if "__init__" in os.path.basename(candidate_filepath):
                sys.path.remove(plugin_info.path)
            # now try to find and initialise the first subclass of the correct plugin interface
            for element in (getattr(candidate_module, name) for name in dir(candidate_module)):
                plugin_info_reference = None
                for category_name in self.categories_interfaces:
                    try:
                        is_correct_subclass = issubclass(element, self.categories_interfaces[category_name])
                    except Exception:
                        continue
                    if is_correct_subclass and element is not self.categories_interfaces[category_name]:
                        current_category = category_name
                        if candidate_infofile not in self._category_file_mapping[current_category]:
                            # we found a new plugin: initialise it and search for the next one
                            plugins = self.config.get('plugins', {})
                            plugin_mode = plugins.get('mode', 'blacklist')
                            if plugin_mode == 'whitelist' and plugin_info.name not in plugins.get(current_category, []):
                                break
                            elif plugin_mode == 'blacklist' and plugin_info.name in plugins.get(current_category, []):
                                break
                            if not plugin_info_reference:
                                try:
                                    plugin_constructer_args = self.config.get('plugin_config', {}).get(current_category, {}).get(plugin_info.name, {})
                                    if isinstance(plugin_constructer_args, (list, set)):
                                        plugin_info.plugin_object = element(*plugin_constructer_args)
                                    elif isinstance(plugin_constructer_args, dict):
                                        plugin_info.plugin_object = element(**plugin_constructer_args)
                                    else:
                                        plugin_info.plugin_object = element()
                                    plugin_info_reference = plugin_info
                                except Exception:
                                    exc_info = sys.exc_info()
                                    log.error("Unable to create plugin object: {}".format(candidate_filepath), exc_info=exc_info)
                                    plugin_info.error = exc_info
                                    break  # If it didn't work once it wont again
                            plugin_info.categories.append(current_category)
                            self.category_mapping[current_category].append(
                                    plugin_info_reference)
                            self._category_file_mapping[
                                current_category].append(candidate_infofile)
        # Remove candidates list since we don't need them any more and
        # don't need to take up the space
        delattr(self, '_candidates')

        # Sort Plugins
        for category_name, plugin_infos in self.category_mapping.items():
            plugin_names = self.config.get('plugin_order', {}).get(category_name, [])
            plugin_rankings = {
                plugin_name: plugin_ranking
                for plugin_name, plugin_ranking
                in zip(plugin_names, range(0, len(plugin_names)))
            }
            plugin_infos.sort(key=lambda plugin_info: plugin_rankings.get(plugin_info.name, len(plugin_names)+1))

        return processed_plugins
Ejemplo n.º 15
0
class AutoInstallPluginManager(PluginManagerDecorator):
	"""
	A plugin manager that also manages the installation of the plugin
	files into the appropriate directory.
	"""


	def __init__(self,
				 plugin_install_dir=None,
				 decorated_manager=None,
				 # The following args will only be used if we need to
				 # create a default PluginManager
				 categories_filter={"Default":IPlugin}, 
				 directories_list=None, 
				 plugin_info_ext="yapsy-plugin"):
		"""
		Create the plugin manager and set up the directory where to
		install new plugins.

		Arguments
		
	        ``plugin_install_dir``
		    The directory where new plugins to be installed will be copied.

		.. warning:: If ``plugin_install_dir`` does not correspond to
		             an element of the ``directories_list``, it is
		             appended to the later.
			
		"""
		# Create the base decorator class
		PluginManagerDecorator.__init__(self,
										decorated_manager,
										categories_filter,
										directories_list,
										plugin_info_ext)
		# set the directory for new plugins
		self.plugins_places=[]
		self.setInstallDir(plugin_install_dir)

	def setInstallDir(self,plugin_install_dir):
		"""
		Set the directory where to install new plugins.
		"""
		if not (plugin_install_dir in self.plugins_places):
			self.plugins_places.append(plugin_install_dir)
		self.install_dir = plugin_install_dir

	def getInstallDir(self):
		"""
		Return the directory where new plugins should be installed.
		"""
		return self.install_dir

	def install(self, directory, plugin_info_filename):
		"""
		Giving the plugin's info file (e.g. ``myplugin.yapsy-plugin``),
		and the directory where it is located, get all the files that
		define the plugin and copy them into the correct directory.
		
		Return ``True`` if the installation is a success, ``False`` if
		it is a failure.
		"""
		# start collecting essential info about the new plugin
		plugin_info, config_parser = self._gatherCorePluginInfo(directory, plugin_info_filename)
		# now determine the path of the file to execute,
		# depending on wether the path indicated is a
		# directory or a file
		if not (os.path.exists(plugin_info.path) or os.path.exists(plugin_info.path+".py") ):
			log.warning("Could not find the plugin's implementation for %s." % plugin_info.name)
			return False
		if os.path.isdir(plugin_info.path):
			try:
				shutil.copytree(plugin_info.path,
								os.path.join(self.install_dir,os.path.basename(plugin_info.path)))
				shutil.copy(os.path.join(directory, plugin_info_filename),
							self.install_dir)
			except:
				log.error("Could not install plugin: %s." % plugin_info.name)
				return False
			else:
				return True
		elif os.path.isfile(plugin_info.path+".py"):
			try:
				shutil.copy(plugin_info.path+".py",
							self.install_dir)
				shutil.copy(os.path.join(directory, plugin_info_filename),
						   self.install_dir)
			except:
				log.error("Could not install plugin: %s." % plugin_info.name)
				return False
			else:
				return True
		else:
			return False
		
		
	def installFromZIP(self, plugin_ZIP_filename):
		"""
		Giving the plugin's zip file (e.g. ``myplugin.zip``), check
		that their is a valid info file in it and correct all the
		plugin files into the correct directory.
		
		.. warning:: Only available for python 2.6 and later.
		
		Return ``True`` if the installation is a success, ``False`` if
		it is a failure.
		"""
		if sys.version_info < (2, 6):
			raise NotImplementedError("Installing fom a ZIP file is only supported for Python2.6 and later.")
		if not os.path.isfile(plugin_ZIP_filename):
			log.warning("Could not find the plugin's zip file at '%s'." % plugin_ZIP_filename)
			return False
		try:
			candidateZipFile = zipfile.ZipFile(plugin_ZIP_filename)
			first_bad_file = candidateZipFile.testzip()
			if first_bad_file:
				raise Exception("Corrupted ZIP with first bad file '%s'" % first_bad_file)
		except Exception,e:
			log.warning("Invalid zip file '%s' (error: %s)." % (plugin_ZIP_filename,e))
			return False
		zipContent = candidateZipFile.namelist()
		log.info("Investigating the content of a zip file containing: '%s'" % zipContent)
		log.info("Sanity checks on zip's contained files (looking for hazardous path symbols).")	
		# check absence of root path and ".." shortcut that would
		# send the file oustide the desired directory
		for containedFileName in zipContent:
			# WARNING: the sanity checks below are certainly not
			# exhaustive (maybe we could do something a bit smarter by
			# using os.path.expanduser, os.path.expandvars and
			# os.path.normpath)
			if containedFileName.startswith("/"):
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') starts with '/'" % containedFileName)
				return False
			if containedFileName.startswith(r"\\") or containedFileName.startswith("//"):
				log.warning(r"Unsecure zip file, rejected because one of its file paths ('%s') starts with '\\'" % containedFileName)
				return False
			if os.path.splitdrive(containedFileName)[0]:
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') starts with a drive letter" % containedFileName)
				return False
			if os.path.isabs(containedFileName):
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') is absolute" % containedFileName)
				return False
			pathComponent = os.path.split(containedFileName)
			if ".." in pathComponent:
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') contains '..'" % containedFileName)	
				return False
			if "~" in pathComponent:
				log.warning("Unsecure zip file, rejected because one of its file paths ('%s') contains '~'" % containedFileName)	
				return False
		infoFileCandidates = [filename for filename in zipContent if os.path.dirname(filename)==""]
		if not infoFileCandidates:
			log.warning("Zip file structure seems wrong in '%s', no info file found." % plugin_ZIP_filename)
			return False
		isValid = False
		log.info("Looking for the zipped plugin's info file among '%s'" % infoFileCandidates)
		for infoFileName in infoFileCandidates:
			infoFile = candidateZipFile.read(infoFileName)
			log.info("Assuming the zipped plugin info file to be '%s'" % infoFileName)
			pluginName,moduleName,_ = self._getPluginNameAndModuleFromStream(StringIO.StringIO(infoFile))
			if moduleName is None:
					continue
			log.info("Checking existence of the expected module '%s' in the zip file" % moduleName)
			if moduleName in zipContent or os.path.join(moduleName,"__init__.py") in zipContent:
				isValid = True
				break
		if not isValid:
			log.warning("Zip file structure seems wrong in '%s', "
							"could not match info file with the implementation of plugin '%s'." % (plugin_ZIP_filename,pluginName))
			return False
		else:
			try:
				candidateZipFile.extractall(self.install_dir)
				return True
			except Exception,e:
				log.error("Could not install plugin '%s' from zip file '%s' (exception: '%s')." % (pluginName,plugin_ZIP_filename,e))
				return False
Ejemplo n.º 16
0
    def loadPlugins(self, callback=None):
        """
		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")

        processed_plugins = []
        for candidate_infofile, candidate_filepath, plugin_info in self._candidates:
            # tolerance on the presence (or not) of the py extensions
            if candidate_filepath.endswith(".py"):
                candidate_filepath = candidate_filepath[:-3]
            # if a callback exists, call it before attempting to load
            # the plugin so that a message can be displayed to the
            # user
            if callback is not None:
                callback(plugin_info)
            # now execute the file and get its content into a
            # specific dictionnary
            candidate_globals = {"__file__": candidate_filepath + ".py"}
            if "__init__" in os.path.basename(candidate_filepath):
                sys.path.append(plugin_info.path)
            try:
                candidateMainFile = open(candidate_filepath + ".py", "r")
                exec(candidateMainFile, candidate_globals)
            except Exception:
                exc_info = sys.exc_info()
                log.error("Unable to execute the code in plugin: %s" %
                          candidate_filepath,
                          exc_info=exc_info)
                if "__init__" in os.path.basename(candidate_filepath):
                    sys.path.remove(plugin_info.path)
                plugin_info.error = exc_info
                processed_plugins.append(plugin_info)
                continue

            processed_plugins.append(plugin_info)
            if "__init__" in os.path.basename(candidate_filepath):
                sys.path.remove(plugin_info.path)
            # now try to find and initialise the first subclass of the correct plugin interface
            for element in candidate_globals.itervalues():
                plugin_info_reference = None
                for category_name in self.categories_interfaces:
                    try:
                        is_correct_subclass = issubclass(
                            element, self.categories_interfaces[category_name])
                    except TypeError:
                        continue
                    if is_correct_subclass and element is not self.categories_interfaces[
                            category_name]:
                        current_category = category_name
                        if candidate_infofile not in self._category_file_mapping[
                                current_category]:
                            # we found a new plugin: initialise it and search for the next one
                            if not plugin_info_reference:
                                plugin_info.plugin_object = element()
                                plugin_info_reference = plugin_info
                            plugin_info.categories.append(current_category)
                            self.category_mapping[current_category].append(
                                plugin_info_reference)
                            self._category_file_mapping[
                                current_category].append(candidate_infofile)
        # Remove candidates list since we don't need them any more and
        # don't need to take up the space
        delattr(self, '_candidates')
        return processed_plugins