Created
January 1, 2010 20:36
-
-
Save dequis/267243 to your computer and use it in GitHub Desktop.
trimmed down PackageResource
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'''Handles plugin importing''' | |
import os | |
import sys | |
import logging | |
log = logging.getLogger('pluginmanager') | |
class PackageResource: | |
'''Handle various files that could be put in the package''' | |
def __init__(self, base_dir, directory): | |
self.path = os.path.join(base_dir, directory) | |
def get_resource_path(self, relative_path): | |
'''get the path to the required resource. | |
If you can, use get_resource. | |
@return the path if it exists or an empty string otherwise''' | |
abs_path = os.path.join(self.path, relative_path) | |
if os.path.exists(abs_path): | |
return abs_path | |
return '' | |
def get_resource(self, relative_path): | |
'''Opens a file. | |
@param relative_path A path starting from the package dir | |
@return a file object opening relative_path if it is possible, or None | |
''' | |
file_path = self.get_resource_path(relative_path) | |
if file_path: | |
try: | |
return open(file_path) | |
except IOError: | |
return | |
class PluginHandler: | |
'''Abstraction over a plugin. | |
Given a directory, will import the plugin.py file inside it and allows to control it. | |
It will provide the plugin several utilities to work on the package | |
''' | |
def __init__(self, base_dir, name, is_package=False): | |
'''@param directory The directory containing the package''' | |
self.name = os.path.basename(name.rstrip("/")) | |
if not is_package: | |
self.name = self.name.split(".")[0] | |
self.base_dir = base_dir | |
self._instance = None | |
self.is_package = is_package | |
self.module = None | |
self._do_import() | |
def _do_import(self): | |
'''Does the dirty stuff with __import__''' | |
old_syspath = sys.path[:] | |
try: | |
sys.path += ['.', self.base_dir] | |
self.module = __import__(self.name, globals(), None, ['plugin']) | |
if hasattr(self.module, 'plugin'): | |
self.module = self.module.plugin | |
except Exception, reason: | |
log.warning('error importing "%s": %s', self.name, reason) | |
self.module = None | |
finally: | |
sys.path = old_syspath | |
def instanciate(self): | |
'''Instanciate (if not already done).''' | |
if self._instance is not None: | |
return self._instance | |
try: | |
self._instance = self.module.Plugin() | |
except Exception, reason: | |
self._instance = None | |
log.warning('error creating instance for "%s": %s', self.name, reason) | |
else: | |
if self.is_package: | |
self._instance.resource = \ | |
PackageResource(self.base_dir, self.name) | |
return self._instance | |
def start(self): | |
'''Instanciate (if necessary) and starts the plugin. | |
@return False if something goes wrong, else True. | |
''' | |
inst = self.instanciate() | |
if not inst: | |
return False | |
try: | |
inst.category_register() | |
inst.start() | |
inst.extension_register() | |
inst._started = True | |
except Exception, reason: | |
log.warning('error starting "%s": %s', (self.name, reason)) | |
return False | |
return True | |
def stop(self): | |
'''If active, stop the plugin''' | |
if self.is_active(): | |
self._instance.stop() | |
self._instance._started = False | |
def is_active(self): | |
'''@return True if an instance exist and is started. False otherwise''' | |
if not self._instance: | |
return False | |
return self._instance.is_active() | |
class PluginManager: | |
'''Scan directories and manage plugins loading/unloading/control''' | |
def __init__(self): | |
self._plugins = {} #'name': Plugin/Package | |
def scan_directory(self, dir_): | |
'''Find plugins and packages inside dir_''' | |
for file in os.listdir(dir_): | |
path = os.path.join(dir_, file) | |
if file.startswith(".") or \ | |
not (os.path.isdir(path) or file.endswith('.py')): | |
continue | |
try: | |
mod = PluginHandler(dir_, file, os.path.isdir(file)) | |
self._plugins[mod.name] = mod | |
except Exception, reason: | |
log.warning('Exception while importing %s:\n%s', (file, reason)) | |
log.debug('Imported plugins: %s', ', '.join(self._plugins.keys())) | |
def plugin_start(self, name): | |
'''Starts a plugin. | |
@param name The name of the plugin. See plugin_base.PluginBase.name. | |
''' | |
if name not in self._plugins: | |
return False | |
log.info('starting plugin "%s"', name) | |
self._plugins[name].start() | |
return True | |
def plugin_stop(self, name): | |
'''Stops a plugin. | |
@param name The name of the plugin. See plugin_base.PluginBase.name. | |
''' | |
if name not in self._plugins: | |
return False | |
log.info('stopping plugin "%s"', name) | |
self._plugins[name].stop() | |
return True | |
def plugin_is_active(self, name): | |
'''Check if a plugin is active. | |
@param name The name of the plugin. See plugin_base.PluginBase.name. | |
@return True if loaded and active, else False. | |
''' | |
if not name in self._plugins: | |
return False | |
return self._plugins[name].is_active() | |
def get_plugins(self): | |
'''return the list of plugin names''' | |
return self._plugins.keys() | |
_instance = None | |
def get_pluginmanager(): | |
'''instance the pluginmanager, if needed. otherwise, return it''' | |
global _instance | |
if _instance: | |
return _instance | |
_instance = PluginManager() | |
return _instance |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment