[orca/orca-gnome3: 20/87] Pluglib reinserted
- From: Alejandro Leiva <aleiva src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca/orca-gnome3: 20/87] Pluglib reinserted
- Date: Fri, 1 Apr 2011 11:14:29 +0000 (UTC)
commit 18e6b128b55b547ab72c3800c20efd4501731abd
Author: José Ignacio �lvarez Ruiz <jialvarez emergya es>
Date: Tue Mar 8 13:54:42 2011 +0100
Pluglib reinserted
src/orca/pluglib/__init__.py | 26 +++
src/orca/pluglib/__init__.pyo | Bin 0 -> 645 bytes
src/orca/pluglib/interfaces.py | 323 +++++++++++++++++++++++++++++++++++++++
src/orca/pluglib/interfaces.pyo | Bin 0 -> 14786 bytes
src/orca/pluglib/manager.py | 236 ++++++++++++++++++++++++++++
src/orca/pluglib/manager.pyo | Bin 0 -> 7365 bytes
6 files changed, 585 insertions(+), 0 deletions(-)
---
diff --git a/src/orca/pluglib/__init__.py b/src/orca/pluglib/__init__.py
new file mode 100644
index 0000000..0e1f6e3
--- /dev/null
+++ b/src/orca/pluglib/__init__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2010, J. Félix Ontañón <felixonta gmail com>
+
+# This file is part of Pluglib.
+
+# Pluglib is free software: 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.
+
+# Pluglib 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 Pluglib. If not, see <http://www.gnu.org/licenses/>.
+
+import interfaces
+
+def verify_conf_dialog(plugin_class):
+ return issubclass(plugin_class, interfaces.IConfigureDialog)
+
+def verify_configurable(plugin_obj):
+ return isinstance(plugin_obj, interfaces.IConfigureDialog)
diff --git a/src/orca/pluglib/__init__.pyo b/src/orca/pluglib/__init__.pyo
new file mode 100644
index 0000000..e01fe77
Binary files /dev/null and b/src/orca/pluglib/__init__.pyo differ
diff --git a/src/orca/pluglib/interfaces.py b/src/orca/pluglib/interfaces.py
new file mode 100644
index 0000000..b383d8e
--- /dev/null
+++ b/src/orca/pluglib/interfaces.py
@@ -0,0 +1,323 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2010, J. Félix Ontañón <felixonta gmail com>
+# Copyright (C) 2011, J. Ignacio Ã?lvarez <neonigma gmail com>
+
+# This file is part of Pluglib.
+
+# Pluglib is free software: 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.
+
+# Pluglib 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 Pluglib. If not, see <http://www.gnu.org/licenses/>.
+
+import exceptions
+import abc
+
+class IPlugin(object):
+ """Every plugin must implement this interface"""
+
+ __metaclass__ = abc.ABCMeta
+
+ ############### ATTRIBS ################
+
+ def name_getter(self):
+ """ You must implement this method in your class """
+
+ def name_setter(self, new_name):
+ """ You must implement this method in your class """
+
+ # Name of the plugin
+ name = abc.abstractproperty(name_getter, name_setter)
+
+
+ def description_getter(self):
+ """ You must implement this method in your class """
+
+ def description_setter(self, new_description):
+ """ You must implement this method in your class """
+
+ # Description of the plugin's behaviour
+ description = abc.abstractproperty(description_getter, description_setter)
+
+
+ def version_getter(self):
+ """ You must implement this method in your class """
+
+ def version_setter(self, new_version):
+ """ You must implement this method in your class """
+
+ # Version of the plugin
+ version = abc.abstractproperty(version_getter, version_setter)
+
+
+ def authors_getter(self):
+ """ You must implement this method in your class """
+
+ def authors_setter(self, new_authors):
+ """ You must implement this method in your class """
+
+ # Authors of the plugin, separated by comma
+ authors = abc.abstractproperty(authors_getter, authors_setter)
+
+ def website_getter(self):
+ """ You must implement this method in your class """
+
+ def website_setter(self, new_website):
+ """ You must implement this method in your class """
+
+ # Website of the plugin
+ website = abc.abstractproperty(website_getter, website_setter)
+
+ def icon_getter(self):
+ """ You must implement this method in your class """
+
+ def icon_setter(self, new_icon):
+ """ You must implement this method in your class """
+
+ # Icon for the plugin manager
+ icon = abc.abstractproperty(icon_getter, icon_setter)
+
+
+class IPluginManager(object):
+ """Every plugin manager must implement this interface"""
+
+ __metaclass__ = abc.ABCMeta
+
+ ############### ATTRIBS ################
+
+ def plugin_paths_getter(self):
+ """ You must implement this method in your class """
+
+ def plugin_paths_setter(self, new_plugin_paths):
+ """ You must implement this method in your class """
+
+ # List of path that may contain plugins
+ plugin_paths = abc.abstractproperty(plugin_paths_getter, plugin_paths_setter)
+
+ def plugins_getter(self):
+ """ You must implement this method in your class """
+
+ def plugins_setter(self, new_plugins):
+ """ You must implement this method in your class """
+
+ # Set of managed plugins
+ plugins = abc.abstractproperty(plugin_paths_getter, plugin_paths_setter)
+
+ ############## METHODS #################
+
+ @abc.abstractmethod
+ def scan_plugins():
+ """Scan plugin paths looking for plugins"""
+
+ @abc.abstractmethod
+ def enable_plugin(plugin):
+ """Perform the process of plugin activation"""
+
+ @abc.abstractmethod
+ def disable_plugin(plugin):
+ """Perform the process of plugin deactivation"""
+
+ @abc.abstractmethod
+ def get_plugins():
+ """Return the list of managed plugins"""
+
+ @abc.abstractmethod
+ def is_plugin_enabled(plugin):
+ """Return if plugin was enabled"""
+
+class IConfigurable(object):
+ """Allows user customize of settings"""
+
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def load ():
+ """Load last option values"""
+
+ @abc.abstractmethod
+ def save():
+ """Save current option values"""
+
+class IConfigureDialog(IConfigurable):
+ """Allow user customize of settings thru configure dialog"""
+
+ __metaclass__ = abc.ABCMeta
+
+ def load ():
+ """Load last option values"""
+
+ def save():
+ """Save current option values"""
+
+ @abc.abstractmethod
+ def configure_dialog(parent):
+ """Display preferences dialog"""
+
+class ICommand(object):
+ """Allows to operate with commands plugins"""
+
+ __metaclass__ = abc.ABCMeta
+
+ def command_name_getter(self):
+ """ You must implement this method in your class """
+
+ def command_name_setter(self, new_commands):
+ """ You must implement this method in your class """
+
+ # Set of managed plugins
+ command_name = abc.abstractproperty(command_name_getter, command_name_setter)
+
+ ############## METHODS #################
+
+ @abc.abstractmethod
+ def get_command(command_name):
+ """Return a command in this environment"""
+
+class IPresenter(object):
+ """Allows to operate with presentation plugins"""
+
+ __metaclass__ = abc.ABCMeta
+
+ ############## METHODS #################
+
+ def presentMessage(self, fullMessage, briefMessage=None, voice=None):
+ """Convenience method to speak a message and 'flash' it in braille.
+
+ Arguments:
+ - fullMessage: This can be a string or a list. This will be presented
+ as the message for users whose flash or message verbosity level is
+ verbose.
+ - briefMessage: This can be a string or a list. This will be presented
+ as the message for users whose flash or message verbosity level is
+ brief. Note that providing no briefMessage will result in the full
+ message being used for either. Callers wishing to present nothing as
+ the briefMessage should set briefMessage to an empty string.
+ - voice: The voice to use when speaking this message. By default, the
+ "system" voice will be used.
+ """
+
+ print "Called presentMessage..."
+
+ if not fullMessage:
+ return
+
+ if briefMessage is None:
+ briefMessage = fullMessage
+
+ if _settingsManager.getSetting('enableSpeech'):
+ if _settingsManager.getSetting('messageVerbosityLevel') \
+ == settings.VERBOSITY_LEVEL_BRIEF:
+ message = briefMessage
+ else:
+ message = fullMessage
+ if message:
+ voice = voice or self.voices.get(settings.SYSTEM_VOICE)
+ speech.speak(message, voice)
+
+ if (_settingsManager.getSetting('enableBraille') \
+ or _settingsManager.getSetting('enableBrailleMonitor')) \
+ and _settingsManager.getSetting('enableFlashMessages'):
+ if _settingsManager.getSetting('flashVerbosityLevel') \
+ == settings.VERBOSITY_LEVEL_BRIEF:
+ message = briefMessage
+ else:
+ message = fullMessage
+ if not message:
+ return
+
+ if isinstance(message[0], list):
+ message = message[0]
+ if isinstance(message, list):
+ message = filter(lambda i: isinstance(i, str), message)
+ message = " ".join(message)
+
+ if _settingsManager.getSetting('flashIsPersistent'):
+ duration = -1
+ else:
+ duration = _settingsManager.getSetting('brailleFlashTime')
+
+ braille.displayMessage(message, flashTime=duration)
+
+class IDependenciesChecker(object):
+ """Allows to check for dependencies before run"""
+
+ __metaclass__ = abc.ABCMeta
+
+ ############## ATTRIBS ##############
+
+ def check_err_getter(self):
+ """ You must implement this method in your class """
+
+ def check_err_setter(self, new_plugins):
+ """ You must implement this method in your class """
+
+ # Message if dependencies was not satisfied
+ check_err = abc.abstractproperty(check_err_getter, check_err_setter)
+
+ ############## METHODS ##############
+
+ @abc.abstractmethod
+ def check_dependencies():
+ """Check for dependencies"""
+
+class IDependenciesResolver(IDependenciesChecker):
+ """Resolves not satisfied dependencies"""
+
+ __metaclass__ = abc.ABCMeta
+
+ ############## ATTRIBS ##############
+
+ def check_err_getter(self):
+ """ You must implement this method in your class """
+
+ def check_err_setter(self, new_plugins):
+ """ You must implement this method in your class """
+
+ # Message if dependencies was not satisfied
+ check_err = abc.abstractproperty(check_err_getter, check_err_setter)
+
+ def check_dependencies():
+ """Check for dependencies"""
+
+ @abc.abstractmethod
+ def resolve_dependencies():
+ """Performs the process of installing dependencies"""
+
+class ISignaller(IPluginManager):
+
+ __metaclass__ = abc.ABCMeta
+
+ def signals_getter(self):
+ """ You must implement this method in your class """
+
+ def signals_setter(self, new_plugins):
+ """ You must implement this method in your class """
+
+ # List of signals
+ signals = abc.abstractproperty(signals_getter, signals_setter)
+
+ @abc.abstractmethod
+ def emit(signal, data):
+ """Emit a signal with data"""
+
+ @abc.abstractmethod
+ def connect(signal, method):
+ """Add a signal handler"""
+
+ @abc.abstractmethod
+ def disconnect(signal, method):
+ """Remove a signal handler"""
+
+class PluginError(exceptions.Exception):
+ pass
+
+class PluginManagerError(exceptions.Exception):
+ pass
diff --git a/src/orca/pluglib/interfaces.pyo b/src/orca/pluglib/interfaces.pyo
new file mode 100644
index 0000000..754c9c6
Binary files /dev/null and b/src/orca/pluglib/interfaces.pyo differ
diff --git a/src/orca/pluglib/manager.py b/src/orca/pluglib/manager.py
new file mode 100644
index 0000000..4b27d6c
--- /dev/null
+++ b/src/orca/pluglib/manager.py
@@ -0,0 +1,236 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2010, J. Félix Ontañón <felixonta gmail com>
+# Copyright (C) 2011, J. Ignacio Ã?lvarez <neonigma gmail com>
+
+# This file is part of Pluglib.
+
+# Pluglib is free software: 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.
+
+# Pluglib 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 Pluglib. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+import exceptions
+import glob
+import imp
+import inspect
+import abc
+import orca.store_config as store_config
+
+from orca.pluglib.interfaces import *
+
+class ModulePluginManager(IPluginManager):
+ """A plugin manager that handles with python modules"""
+
+ def __init__(self, plugin_paths=['baseplugins']):
+
+ self.plugin_paths = plugin_paths
+ if not type(self.plugin_paths) is list:
+ self.plugin_paths = [self.plugin_paths]
+
+ #{'plugin_name': {'class': plugin_class, 'object': plugin_object,
+ # 'type': plugin_type, 'registered':, if_registered}
+ self.plugins = {}
+
+ self.store_conf = store_config.StoreConfig()
+ self.plugins_conf = self.store_conf.getPlugins()
+
+ def inspect_plugin_module(self, module_name, path):
+ plugins = {}
+
+ if self.plugins_conf:
+ plugin_exists = module_name in self.plugins_conf['plugins']
+ else:
+ plugin_exists = False
+
+ # plugin don't exists in conf or don't have any plugins
+ if plugin_exists == False or not self.plugins_conf:
+ try:
+ modfile, name, desc = imp.find_module(module_name, [path])
+ # the idea is not repeat this load unnecessarily
+ module = imp.load_module(module_name, modfile, name, desc)
+ try:
+ active = self.plugins_conf[module_name]['active'] \
+ if self.plugins_conf and module_name in self.plugins_conf \
+ else False
+
+ registered = self.plugins_conf[module_name]['registered'] \
+ if self.plugins_conf and module_name in self.plugins_conf \
+ else True
+
+ plugins.update([(module_name, {'class': klass, 'object': None, 'name': name,
+ 'active': active, 'type': None, 'registered': registered,
+ 'path': path})
+
+ for (name, klass) in inspect.getmembers(module, inspect.isclass)
+ if issubclass(klass, IPlugin) and name != "IPlugin"])
+
+ print "Importing new module: " + str(module_name)
+ except LookupError, e:
+ raise PluginManagerError, 'Update dictionary fails in %s: %s' % (name, e)
+
+ # ADD PLUGIN!
+ # pass name, module_name and registered or not
+ self.store_conf.addPlugin(name, registered, module_name, path)
+
+ # update plugins container
+ #self.plugins_conf = self.store_conf.getPlugins()
+
+ except Exception, e:
+ raise PluginManagerError, 'Cannot load module %s: %s' % \
+ (name, e)
+ finally:
+ if modfile:
+ modfile.close()
+
+ return plugins
+
+ def scan_more_plugins(self):
+ print "Scanning plugins..."
+ # CHECK BASEPLUGINS FOR MORE PLUGINS
+ new_plugins = {}
+ for path in self.plugin_paths:
+ if not path in sys.path:
+ sys.path.insert(0, path)
+ for module in [os.path.basename(os.path.splitext(x)[0])
+ for x in glob.glob(os.path.join(path, '[!_]*.py'))]:
+ new_plugins.update(self.inspect_plugin_module(module, path))
+
+ new_plugins.update(self.plugins)
+ self.plugins = new_plugins
+
+ def load_class_in_plugin(self, dict_plugins, module_name, path):
+ modfile, name, desc = imp.find_module(module_name, path)
+
+ # the idea is not repeat this load unnecessarily
+ module = imp.load_module(module_name, modfile, name, desc)
+
+ for (the_name, klass) in inspect.getmembers(module, inspect.isclass):
+ if issubclass(klass, IPlugin) and the_name != "IPlugin":
+ klass_update = {'class': klass}
+ object_update = {'object': None}
+ type_update = {'type': 'Generic'}
+ dict_plugins.update(type_update)
+ dict_plugins.update(klass_update)
+ dict_plugins.update(object_update)
+ if issubclass(klass, ICommand) and the_name != "ICommand":
+ type_update = {'type': 'Command'}
+ dict_plugins.update(type_update)
+
+ def scan_plugins(self):
+ self.scan_more_plugins()
+
+ # LOAD FROM STORE_CONF
+ if self.plugins_conf:
+ self.plugins = self.plugins_conf.copy()
+
+ load_plugins = self.plugins['plugins'];
+
+ for module_name, data in load_plugins.iteritems():
+ if load_plugins[module_name]['active'] == True:
+ try:
+ self.load_class_in_plugin(load_plugins[module_name],
+ module_name, [load_plugins[module_name]['path']])
+
+ plugin_class = load_plugins[module_name]['class']
+ plugin_object = plugin_class()
+ if isinstance(plugin_object, IConfigurable):
+ plugin_object.load()
+
+ load_plugins[module_name]['object'] = plugin_object
+ print "Starting existent module: " + str(module_name)
+ except Exception, e:
+ raise PluginManagerError, 'Cannot load module %s: %s' % \
+ (module_name, e)
+ else:
+ load_plugins[module_name].update({'class': None})
+ load_plugins[module_name].update({'object': None})
+
+ self.plugins = load_plugins
+
+ def enable_plugin(self, plugin_name):
+ enabling_plugins = self.store_conf.getPluginByName(plugin_name)
+ enabling_plugins['active'] = True
+ self.store_conf.updatePlugin({plugin_name: enabling_plugins})
+
+ if self.plugins:
+ self.load_class_in_plugin(self.plugins[plugin_name], plugin_name,
+ [self.plugins[plugin_name]['path']])
+
+ plugin_class = self.plugins[plugin_name]['class']
+
+ if issubclass(plugin_class, IDependenciesChecker) \
+ and not plugin_class.check_dependencies():
+ raise PluginManagerError, 'Cannot satisfy dependencies for %s: %s' % \
+ (plugin_name, plugin_class.check_err)
+
+ plugin_object = plugin_class()
+ if isinstance(plugin_object, IConfigurable):
+ plugin_object.load()
+
+ self.plugins[plugin_name]['object'] = plugin_object
+
+ def disable_plugin(self, plugin_name):
+ disabling_plugins = self.store_conf.getPluginByName(plugin_name)
+ disabling_plugins['active'] = False
+ self.store_conf.updatePlugin({plugin_name: disabling_plugins})
+
+ if self.is_plugin_enabled(plugin_name):
+ plugin_object = self.plugins[plugin_name]['object']
+ if isinstance(plugin_object, IConfigurable):
+ plugin_object.save()
+ self.plugins[plugin_name]['object'] = None
+
+ print "Unloaded module " + str(plugin_name)
+
+ del (plugin_name)
+
+ def get_plugins(self):
+ return [(plugin_name, plugin['class'],
+ plugin['type'], plugin['registered'], plugin['name'])
+ for (plugin_name, plugin) in self.plugins.items()]
+
+ def is_plugin_loaded(self, plugin_name):
+ if self.plugins.has_key(plugin_name):
+ return self.plugins[plugin_name]['object'] is not None
+ else:
+ raise PluginManagerError, 'No plugin named %s' % plugin_name
+
+ def is_plugin_enabled(self, plugin_name):
+ check_plugin = self.store_conf.getPluginByName(plugin_name)
+ return check_plugin['active']
+
+ _plugin_paths = None
+
+ def plugin_paths_getter(self):
+ return self._plugin_paths
+
+ def plugin_paths_setter(self, new_plugin_paths):
+ self._plugin_paths = new_plugin_paths
+
+ plugin_paths = property(plugin_paths_getter, plugin_paths_setter)
+
+ _plugins = None
+
+ def plugins_getter(self):
+ return self._plugins
+
+ def plugins_setter(self, new_plugins):
+ self._plugins = new_plugins
+
+ plugins = property(plugins_getter, plugins_setter)
+
+# Register implementation
+IPluginManager.register(ModulePluginManager)
+
+plugmanager = ModulePluginManager()
diff --git a/src/orca/pluglib/manager.pyo b/src/orca/pluglib/manager.pyo
new file mode 100644
index 0000000..6674a7d
Binary files /dev/null and b/src/orca/pluglib/manager.pyo differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]