Changeset 281

Show
Ignore:
Timestamp:
11/23/05 23:49:49 (3 years ago)
Author:
athomas
Message:
  • Modified the component architecture to allow extending the way extension points are returned.
  • Implemented a SelectedExtensionPoint, which returns a single user-selected implementation of a particular interface.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pycrash/trunk/crash/component.py

    r270 r281  
    2424class ComponentError(Exception): pass 
    2525 
    26 __all__ = ['Component', 'ComponentManager', 'ExtensionPoint', 'implements', 'Interface'] 
     26__all__ = ['Component', 'ComponentManager', 'ExtensionPoint', 'implements', 
     27    'SelectedExtensionPoint', 'Interface'] 
    2728 
    2829class Interface(object): 
     
    4748        return '<ExtensionPoint %s>' % self.interface.__name__ 
    4849 
     50    def __get__(self, instance, owner): 
     51        """If requesting an extension point member, return a list of components  
     52           that declare to implement the extension point interface."""  
     53        xtnpt = instance._extension_points.get(self.name) 
     54        extensions = ComponentMeta._registry.get(xtnpt.interface, []) 
     55        return [instance.compmgr[cls] for cls in extensions 
     56                if instance.compmgr[cls]] 
     57 
     58class SelectedExtensionPoint(ExtensionPoint): 
     59    """ Implementation of a 'singleton' extension point. Looks up the name of 
     60        the selected interface implementation to use by calling 
     61        ComponentManager.get_selected_implementation(interface), which should return 
     62        the class name of the selected component. Caches the selected implementation 
     63        for speed. """ 
     64    def __init__(self, interface): 
     65        ExtensionPoint.__init__(self, interface) 
     66        self._implementation = None 
     67 
     68    def __get__(self, instance, owner): 
     69        """ Return the selected interface implementation, or throw an exception if 
     70            not found. """ 
     71        if self._implementation: 
     72            return self._implementation 
     73        xtnpt = instance._extension_points.get(self.name) 
     74        extensions = ComponentMeta._registry.get(xtnpt.interface, []) 
     75        seek = instance.compmgr.get_selected_implementation(xtnpt.interface) 
     76        if seek: 
     77            for extension in extensions: 
     78                if extension.__name__ == seek: 
     79                    self._implementation = instance.compmgr[extension] 
     80                    return self._implementation 
     81            raise ComponentError("can't find selected interface '%s' named '%s'" % (xtnpt.interface.__name__, seek)) 
     82        else: 
     83            raise ComponentError("no component active for '%s' interface" % xtnpt.interface.__name__) 
    4984 
    5085class ComponentMeta(type): 
     
    65100            if isinstance(value, ExtensionPoint): 
    66101                xtnpts[key] = value 
    67                 del d[key] 
     102                d[key].name = key 
    68103 
    69104        new_class = type.__new__(cls, name, bases, d) 
     
    140175            return self 
    141176        return compmgr[cls] 
    142  
    143     def __getattr__(self, name): 
    144         """If requesting an extension point member, return a list of components 
    145         that declare to implement the extension point interface.""" 
    146         xtnpt = self._extension_points.get(name) 
    147         if xtnpt: 
    148             extensions = ComponentMeta._registry.get(xtnpt.interface, []) 
    149             return [self.compmgr[cls] for cls in extensions 
    150                     if self.compmgr[cls]] 
    151         raise AttributeError, name 
    152  
    153177 
    154178class ComponentManager(object):