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