Changeset 161

Show
Ignore:
Timestamp:
14.04.2008 17:37:47 (9 months ago)
Author:
poillubo
Message:

* plugins can fail to load
* plugin dependencies are cleaned up when a plugin fails to load
* no more delay in the drawing of a submenu
* put the XMapWindow back in ShowPos?.start_window

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/pycawm/menu.py

    r159 r161  
    162162        self.current = self.get_indice(pointer.win_x, pointer.win_y) 
    163163        self.fill_window_pixmap() 
     164        self.window.map() 
    164165        self.draw_menu() 
    165         self.window.map() 
    166166        self.window.set_wm_state(state=Xutil.NormalState, icon=0) 
    167167        self.grabbed = False 
     
    809809 
    810810    @classmethod 
    811     def add_plugin(cls, wm, plugin, params=dict(), name=None, force=False): 
     811    def add_plugin(cls, wm, plugin, params=dict(), name=None, **kwargs): 
    812812        plugin_name = name if name is not None else plugin.__name__ 
    813813        cls.elements[plugin_name] = \ 
    814814            (('Add ' + plugin_name, Menu.python, 
    815               (lambda plugin=plugin, params=params, name=name, force=force
    816                wm.add_plugin(plugin, params, name=name, force=force)))) 
     815              (lambda plugin=plugin, params=params, name=name
     816               wm.add_plugin(plugin, params=params, name=name)))) 
    817817 
    818818    @classmethod 
  • trunk/pycawm/plugins/__init__.py

    r159 r161  
    1818#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
    1919 
    20 # generic base plugin 
    21 from plugin import Plugin 
     20# generic base plugin and plugin exception 
     21from plugin import Plugin, PycaPluginError 
    2222 
    2323# specific plugins 
  • trunk/pycawm/plugins/musicactionbuttonbox.py

    r159 r161  
    2727 
    2828from pycawm.button import Button 
    29 from pycawm.plugins import ActionButtonBox 
     29from pycawm.plugins import ActionButtonBox, PycaPluginError 
    3030 
    3131 
     
    6868    def __init__(self, wm, player, play_img='plop.png', next_img='plop.png', 
    6969                 volume_step=10, x=0, y=0): 
     70        if player not in MusicActionButtonBox.players: 
     71            raise PycaPluginError('%s is not in the available players!' % 
     72                                  player) 
    7073        self.player = player 
    7174        self.volume_step = volume_step 
  • trunk/pycawm/plugins/plugin.py

    r145 r161  
    2323    raise ImportError('plugin module needs at least Python 2.5!') 
    2424 
     25class PycaPluginError(Exception): 
     26    def __init__(self, msg): 
     27        self.msg = msg 
     28 
    2529class Plugin(object): 
    2630    conflicts = list() 
  • trunk/pycawm/plugins/showpos.py

    r160 r161  
    7878            self.end_window(force=True) 
    7979        self.client = client 
     80        self.window.map() 
    8081 
    8182    def end_window(self, *args, **kwargs): 
     
    9192                height = extents.overall_ascent + extents.overall_descent + 10 
    9293                width = extents.overall_width + 10 
    93                 self.window.map() 
    9494                self.window.configure(width=width, height=height, 
    9595                                      stack_mode=X.Above) 
  • trunk/pycawm/pycawm.py

    r160 r161  
    4646                  is_strict_subclass) 
    4747from patterns import DictWrapper 
    48 from plugins import Plugin 
     48from plugins import Plugin, PycaPluginError 
    4949from wrappers import DisplayWrapper 
    5050import focuses 
     
    294294        self.display.sync() 
    295295 
    296     def add_plugin(self, plugin, params=dict(), name=None, force=False): 
     296    def add_plugin(self, plugin, params=dict(), name=None, 
     297                   load_deps=True, force=False): 
    297298        def build_deps_and_confs(plug): 
    298             for dep in plug.depends: 
     299            for conf in plug.conflicts: 
     300                confs.append(conf) 
     301            for dep, dep_params in plug.depends.items(): 
    299302                if isinstance(dep, tuple): 
    300303                    deps.append(dep[1]) 
    301304                else: 
    302305                    deps.append(dep.__name__) 
    303             for conf in plug.conflicts: 
    304                 confs.append(conf) 
    305             for dep in plug.depends: 
    306306                build_deps_and_confs(dep[0] if isinstance(dep, tuple) else dep) 
     307                if load_deps: 
     308                    deps_to_load.append((dep, dep_params)) 
     309 
     310        def cleanup_deps(): 
     311            if not load_deps: 
     312                return 
     313            print 'cleaning up old dependencies...' 
     314            for name, inst in reversed(deps_loaded): 
     315                print ('removed plugin named %s, instance: %s' % (name, inst)) 
     316                self.remove_plugin(name, inst) 
    307317 
    308318        if not plugin.runnable: 
    309319            print "%s is not a runnable plugin!" % plugin 
    310             return 
    311  
     320            return None 
     321 
     322        plugin_inst = None 
    312323        plugin_name = name if name is not None else plugin.__name__ 
    313324 
    314325        if not force and plugin_name in self.plugins: 
    315326            print '%s is already loaded!' % plugin_name 
    316             return 
     327            return None 
    317328 
    318329        # current plugin has a conflict with an already loaded one? 
     
    321332                print ("%s which conflicts with %s is already loaded!" % 
    322333                       (plug_name, plugin_name)) 
    323                 return 
     334                return None 
    324335 
    325336        # already loaded plugin has a conflict with current one? 
     
    329340                    print ("%s which conflicts with %s is already loaded!" % 
    330341                           (plug_name, plugin_name)) 
    331                     return 
    332  
     342                    return None 
     343 
     344        confs = list() 
    333345        deps = list() 
    334         confs = list() 
     346        if load_deps: 
     347            deps_to_load = list() 
    335348        build_deps_and_confs(plugin) 
    336349     
    337         # last check: conflict in a plugin dependency? 
     350        # conflict in a plugin dependency? 
    338351        for conf_name in confs: 
    339352            if conf_name in deps: 
    340353                print ("there is a conflict with %s in the dependencies of %s!" 
    341354                       % (conf_name, plugin_name)) 
    342                 return 
    343  
    344         for dep, dep_params in plugin.depends.items(): 
    345             if isinstance(dep, tuple): 
    346                 self.add_plugin(dep[0], dep_params, name=dep[1]) 
    347             else: 
    348                 self.add_plugin(dep, dep_params) 
    349  
    350         self.plugins.setdefault(plugin_name, 
    351                                 list()).append(plugin(self, **params)) 
     355                return None 
     356 
     357        if load_deps: 
     358            deps_loaded = list() 
     359            for dep, dep_params in deps_to_load: 
     360                if isinstance(dep, tuple): 
     361                    dep_class, dep_name = dep 
     362                else: 
     363                    dep_class = dep 
     364                    dep_name = dep.__name__ 
     365                inst = self.add_plugin(dep_class, 
     366                                       **dict(name=dep_name, 
     367                                              params=dep_params, 
     368                                              load_deps=False)) 
     369 
     370                if inst is None: 
     371                    # one dependency has failed to load, do the clean up 
     372                    print ('cannot load dependency %s for %s plugin.' % 
     373                           (dep_name, plugin_name)) 
     374                    cleanup_deps() 
     375                    return None 
     376                deps_loaded.append((dep_name, inst)) 
     377        else: 
     378            # make sure all the dependencies are loaded 
     379            for dep in deps: 
     380                if dep not in self.plugins: 
     381                    print 'no %s plugin here for %s!' % (dep, plugin_name) 
     382                    return None 
     383 
     384        try: 
     385            plugin_inst = plugin(self, **params) 
     386        except TypeError: 
     387            print 'cannot load %s plugin: bad parameters?' % plugin_name 
     388            cleanup_deps() 
     389        except PycaPluginError, exc: 
     390            print 'cannot load %s plugin: %s' % (plugin_name, exc.msg) 
     391            cleanup_deps() 
     392        else: 
     393            self.plugins.setdefault(plugin_name, list()).append(plugin_inst) 
     394 
     395        return plugin_inst 
    352396 
    353397    def remove_plugin(self, plugin_name, plugin, remove_deps=False, warn=True):