Author: dmeyer
Date: Mon Apr 30 19:52:47 2007
New Revision: 9532

Modified:
   trunk/core/src/plugin.py
   trunk/ui/bin/freevo
   trunk/ui/src/mainmenu.py
   trunk/ui/src/menu/plugin.py
   trunk/ui/src/plugins/idlebar/plugin.py

Log:
rework internals of the plugin loader

Modified: trunk/core/src/plugin.py
==============================================================================
--- trunk/core/src/plugin.py    (original)
+++ trunk/core/src/plugin.py    Mon Apr 30 19:52:47 2007
@@ -42,9 +42,6 @@
 # get logging object
 log = logging.getLogger('plugin')
 
-#
-# Some basic plugins known to Freevo.
-#
 
 class Plugin(object):
     """
@@ -52,23 +49,32 @@
     """
 
     def __init__(self, name=''):
-        self._plugin_type = None
-        self._plugin_level  = 10
-        self._plugin_special = False
+        self._plugin_level = 10
+        self._plugin_media = None
 
 
     def plugin_activate(self, level):
+        """
+        Activate the plugin with given level
+        """
         pass
 
 
-    def plugin_register(self, name):
+    def plugin_set_name(self, name):
         """
         Register plugin with the given name. In most cases this is not needed
         because the plugin will always be registered by its own name.
         """
-        _loader.register(self, name)
+        _loader.names[name] = self
 
 
+    def plugin_media(self):
+        """
+        Return special media the plugin is valid in.
+        """
+        return self._plugin_media
+
+    
     def plugin_level(self):
         """
         Return plugin level.
@@ -80,67 +86,25 @@
     """
     Class for handling the different plugins.
     """
+
     def __init__(self):
-        """
-        Init the plugin loader.
-        """
-        # path where to search for plugins, will be set on init
-        self.path = None
-        # list of all plugins
-        self.plugins = []
-        self.loaded_plugins = []
-
-        # next id for a plugin
-        self.next_id = 0
-        # plugins sorted by type
-        self.types = {}
-        # plugins based on name
-        self.names = {}
-        # status of the plugin module
-        self.__initialized = False
+        self._plugin_list  = []
+        self._baseclasses  = []
+        self._plugin_names = {}
+        self._initialized  = False
 
 
     def activate(self, name, type=None, level=10, args=None):
         """
         Activate a plugin.
         """
-        self.next_id += 1
-
-        for p in self.plugins:
-            if not isinstance(name, Plugin) and p[0] == name and \
-                   p[1] == type and p[3] == args:
-                log.warning('duplicate plugin activation, ignoring:\n' + \
-                            '  <%s %s %s>' % (name, type, args))
-                return
-        if self.__initialized:
-            self.__load_plugin(name, type, level, args)
-            # sort plugins again
-            cmp_func = lambda l, o: cmp(l._plugin_level, o._plugin_level)
-            for key in self.types:
-                self.types[key].sort(cmp_func)
-        else:
-            self.plugins.append((name, type, level, args, self.next_id))
-        return self.next_id
-
-
-    def deactivate(self, id):
-        """
-        Remove a plugin from the list.
-        """
-        if self.__initialized:
-            return
-
-        if isinstance(id, int):
-            # remove by plugin id
-            for p in self.plugins:
-                if p[4] == id:
-                    self.plugins.remove(p)
-                    return
-        else:
-            # remove by name
-            for p in copy.copy(self.plugins):
-                if p[0] == id:
-                    self.plugins.remove(p)
+        if not self._initialized:
+            return self._plugin_list.append((name, type, level, args))
+        self.__load_plugin(name, type, level, args)
+        # sort plugins again
+        cmp_func = lambda l, o: cmp(l._plugin_level, o._plugin_level)
+        for c in self._baseclasses:
+            c.plugin_list.sort(cmp_func)
 
 
     def init(self, module, callback = None):
@@ -150,133 +114,121 @@
         plugin is loaded. If 'plugins' is given, only plugins with the given
         prefix are loaded.
         """
-        self.__initialized = True
+        self._initialized = True
         self.path = os.path.dirname(module.__file__)
         self.import_path = module.__name__
-        for name, type, level, args, number in self.plugins:
+        for name, type, level, args in self._plugin_list:
             kaa.notifier.step(False, True)
             if callback:
                 callback()
-            if isinstance(name, Plugin):
-                # plugin already an object
-                self.__load_plugin(name, type, level, args)
-                continue
             self.__load_plugin(name, type, level, args)
 
         # sort plugins
         cmp_func = lambda l, o: cmp(l._plugin_level, o._plugin_level)
-        for key in self.types:
-            self.types[key].sort(cmp_func)
-
-
-    def get(self, type=None):
-        """
-        Get the plugin list 'type' or all if type is None
-        """
-        if type == None:
-            return self.plugins
-        if not self.types.has_key(type):
-            self.types[type] = []
-        return self.types[type]
+        for c in self._baseclasses:
+            c.plugin_list.sort(cmp_func)
 
 
     def getbyname(self, name):
         """
         Get a plugin by it's name
         """
-        return self.names.get(name, None)
-
-
-    def register(self, plugin, name):
-        """
-        Register an object as a named plugin
-        """
-        self.names[name] = plugin
-
-
-    def __find_plugin_file(self, filename):
+        return self._plugin_names.get(name, None)
+    
+    
+    def register(self, plugin):
+        """
+        Register a plugin class
+        """
+        plugin.plugin_list = []
+        return self._baseclasses.append(plugin)
+    
+    
+    def _find_plugin_file(self, name):
         """
         Find the filename for the plugin and the python import statement.
         """
+        filename = name.replace('.', '/')
         full_filename = os.path.join(self.path, filename)
-
+    
         if os.path.isfile(full_filename + '.py'):
             return filename.replace('/', '.'), None
-
+    
         if os.path.isdir(full_filename):
             return filename.replace('/', '.'), None
-
+    
         full_filename = os.path.join(self.path, 'plugins', filename)
-
+    
         if os.path.isfile(full_filename + '.py'):
             return 'plugins.' + filename.replace('/', '.'), None
-
+    
         if os.path.isdir(full_filename):
             return 'plugins.' + filename.replace('/', '.'), None
-
-        if filename.find('/') > 0:
-            special = filename[:filename.find('/')]
-            filename = os.path.join(special, 'plugins',
-                                    filename[filename.find('/')+1:])
-            full_filename = os.path.join(self.path, filename)
-
-            if os.path.isfile(full_filename + '.py'):
-                return filename.replace('/', '.'), special
-
-            if os.path.isdir(full_filename):
-                return filename.replace('/', '.'), special
-
+    
+        if filename.find('/') == -1:
+            # unable to find plugin
+            return None, None
+    
+        special, filename = filename.split('/', 1)
+        filename = os.path.join(special, 'plugins', filename)
+        full_filename = os.path.join(self.path, filename)
+    
+        if os.path.isfile(full_filename + '.py'):
+            return filename.replace('/', '.'), special
+    
+        if os.path.isdir(full_filename):
+            return filename.replace('/', '.'), special
+    
+        # unable to find plugin
         return None, None
-
-
+    
+    
     def __load_plugin(self, name, type, level, args):
         """
         Load the plugin and add it to the lists
         """
-        # fallback
-        module  = name
-        object  = '%s.PluginInterface' % module
-        special = None
-
-        # locate the plugin:
-        files = []
-
         if not isinstance(name, Plugin):
-            module, special = self.__find_plugin_file(name.replace('.', '/'))
+
+            # -----------------------------------------------------
+            # locate plugin python file
+            # -----------------------------------------------------
+            
+            module, special = self._find_plugin_file(name)
             if module:
-                object = module + '.PluginInterface'
+                pclass = 'PluginInterface'
             elif name.find('.') > 0:
-                pname = name[:name.rfind('.')].replace('.', '/')
-                module, special = self.__find_plugin_file(pname)
+                pname = name[:name.rfind('.')]
+                module, special = self._find_plugin_file(pname)
                 if module:
-                    object = module + '.%s' % name[name.rfind('.')+1:]
+                    pclass = name[name.rfind('.')+1:]
                 else:
-                    log.critical('can\'t locate plugin %s' % name)
+                    log.critical('unable to locate plugin %s' % name)
                     return
             else:
-                log.critical('can\'t locate plugin %s' % name)
+                log.critical('unable to locate plugin %s' % name)
                 return
 
-        try:
-            if not isinstance(name, Plugin):
-                object = '%s.%s' % (self.import_path, object)
+            # -----------------------------------------------------
+            # load plugin python file
+            # -----------------------------------------------------
+
+            try:
                 module = '%s.%s' % (self.import_path, module)
-                log.debug('loading %s as plugin %s' % (module, object))
+                log.debug('loading %s as plugin %s' % (module, pclass))
+                exec('from %s import %s as plugin_class' % (module, pclass))
 
-                exec('import %s' % module)
+                # create object
                 if not args:
-                    p = eval(object)()
+                    plugin = plugin_class()
                 elif isinstance(args, list) or isinstance(args, tuple):
-                    paramlist = 'args[0]'
-                    for i in range(1, len(args)):
-                        paramlist += ',args[%s]' % i
-                    p = eval('%s(%s)' % (object, paramlist))
+                    plugin = plugin_class(*args)
                 else:
-                    p = eval(object)(args)
+                    plugin = plugin_class(args)
 
-                if not hasattr(p, '_plugin_type'):
-                    if hasattr(p, 'reason'):
-                        reason = p.reason
+                # init failed
+                if not hasattr(plugin, '_plugin_level'):
+                    if hasattr(plugin, 'reason'):
+                        reason = plugin.reason
                     else:
                         reason = '''unknown
                         The plugin neither called __init__ nor set a reason why
@@ -284,40 +236,45 @@
                     log.warning('plugin %s deactivated\n  reason: %s' % \
                                 (name, reason))
                     return
-            else:
-                p = name
-
-            p._plugin_level = level
-
-            if type:
-                special = type
-
-            if p._plugin_type:
-                if p._plugin_special and special:
-                    key = p._plugin_type + '_' + special
-                else:
-                    key = p._plugin_type
+            except:
+                log.exception('failed to load plugin %s' % name)
+                return
+        else:
+            # name is a plugin object
+            plugin = name
+            special = None
 
-                if not self.types.has_key(key):
-                    self.types[key] = []
-                self.types[key].append(p)
 
-            self.names[name] = p
+        # -----------------------------------------------------
+        # configure and activate plugin object
+        # -----------------------------------------------------
 
-            p.plugin_activate(level)
-            self.loaded_plugins.append(p)
+        if type:
+            special = type
 
+        try:
+            plugin._plugin_level = level
+            plugin._plugin_media = special
+            plugin.plugin_activate(level)
         except:
-            log.exception('failed to load plugin %s' % name)
+            log.exception('failed to activate plugin %s' % name)
+            return
 
+        
+        # -----------------------------------------------------
+        # register plugin object
+        # -----------------------------------------------------
+
+        self._plugin_names[name] = plugin
+        for c in self._baseclasses:
+            if isinstance(plugin, c):
+                c.plugin_list.append(plugin)
 
 
 _loader = PluginLoader()
 
 # interface:
 activate = _loader.activate
-remove = _loader.deactivate
-deactivate = _loader.deactivate
 init = _loader.init
-get = _loader.get
+register = _loader.register
 getbyname = _loader.getbyname

Modified: trunk/ui/bin/freevo
==============================================================================
--- trunk/ui/bin/freevo (original)
+++ trunk/ui/bin/freevo Mon Apr 30 19:52:47 2007
@@ -126,12 +126,14 @@
     config.watch()
     
     # plugins is a list of known plugins
+    num_plugins = 0
     for p in freevo.ui.plugins:
         c = config
         for attr in p.split('.'):
             c = getattr(c, attr)
         if c.activate:
             p = p.replace('plugin.', '').replace('..', '.')
+            num_plugins += 1
             if isinstance(c.activate, bool):
                 freevo.plugin.activate(p)
             else:
@@ -295,8 +297,7 @@
     displays.create()
 
     # Fire up splashscreen and load the plugins
-    num = len(freevo.plugin.get(None))-1
-    splash = Splashscreen(_('Starting Freevo, please wait ...'), num)
+    splash = Splashscreen(_('Starting Freevo, please wait ...'), num_plugins-1)
 
     # load plugins
     freevo.plugin.init(freevo.ui, splash.progress)

Modified: trunk/ui/src/mainmenu.py
==============================================================================
--- trunk/ui/src/mainmenu.py    (original)
+++ trunk/ui/src/mainmenu.py    Mon Apr 30 19:52:47 2007
@@ -104,12 +104,6 @@
     """
     Plugin class for plugins to add something to the main menu
     """
-    def __init__(self, name=''):
-        plugin.Plugin.__init__(self, name)
-        self._plugin_type = 'mainmenu'
-        self._plugin_special = True
-
-
     def items(self, parent):
         """
         return the list of items for the main menu
@@ -117,13 +111,11 @@
         return []
 
 
-    def plugins(subtype=''):
+    def plugins(subtype=None):
         """
         Static function to return all MainMenuPlugins.
         """
-        if not subtype:
-            return plugin.get('mainmenu')
-        return plugin.get('mainmenu_%s' % subtype)
+        return [ x for x in MainMenuPlugin.plugin_list if x.plugin_media() == 
subtype ]
 
     plugins = staticmethod(plugins)
 
@@ -152,3 +144,6 @@
         because it is not bound to a menupage.
         """
         return self.menuw
+
+# register base class
+plugin.register(MainMenuPlugin)

Modified: trunk/ui/src/menu/plugin.py
==============================================================================
--- trunk/ui/src/menu/plugin.py (original)
+++ trunk/ui/src/menu/plugin.py Mon Apr 30 19:52:47 2007
@@ -44,12 +44,6 @@
     True, the event won't be passed to other eventhandlers and also not to
     the item itself.
     """
-    def __init__(self, name=''):
-        plugin.Plugin.__init__(self, name)
-        self._plugin_type = 'item'
-        self._plugin_special = True
-
-
     def actions(self, item):
         """
         return a list of actions to that item. Each action is type Action
@@ -68,11 +62,8 @@
         """
         Static function to return all ItemPlugins.
         """
-        plugins = plugin.get('item')[:]
-        if subtype:
-            plugins += plugin.get('item_%s' % subtype)
-        plugins.sort(lambda l, o: cmp(l._plugin_level, o._plugin_level))
-        return plugins
+        return [ x for x in ItemPlugin.plugin_list \
+                 if x.plugin_media() in (None, subtype) ]
 
     plugins = staticmethod(plugins)
 
@@ -86,11 +77,6 @@
     """
     mediatype = []
 
-    def __init__(self, name=''):
-        plugin.Plugin.__init__(self, name)
-        self._plugin_type = 'media'
-
-
     def suffix(self):
         """
         return the list of suffixes this class handles
@@ -135,11 +121,16 @@
         If mediatype is None, return all MediaPlugins.
         """
         if not mediatype:
-            return plugin.get('media')
+            return MediaPlugin.plugin_list
         ret = []
-        for p in plugin.get('media'):
+        for p in MediaPlugin.plugin_list:
             if not p.mediatype or mediatype in p.mediatype:
                 ret.append(p)
         return ret
 
     plugins = staticmethod(plugins)
+
+
+# register base class
+plugin.register(MediaPlugin)
+plugin.register(ItemPlugin)

Modified: trunk/ui/src/plugins/idlebar/plugin.py
==============================================================================
--- trunk/ui/src/plugins/idlebar/plugin.py      (original)
+++ trunk/ui/src/plugins/idlebar/plugin.py      Mon Apr 30 19:52:47 2007
@@ -34,7 +34,6 @@
 class IdleBarPlugin(plugin.Plugin):
     def __init__(self):
         plugin.Plugin.__init__(self)
-        self._plugin_type = 'idlebar'
         self.objects   = []
         self.NO_CHANGE = -1
         self.align     = 'left'
@@ -81,6 +80,9 @@
         """
         Static function to return all IdlebarPlugins.
         """
-        return plugin.get('idlebar')
+        return IdleBarPlugin.plugin_list
 
     plugins = staticmethod(plugins)
+
+
+plugin.register(IdleBarPlugin)

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to