[orca/orca-gnome3: 20/87] Pluglib reinserted



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]