Changeset 1069


Ignore:
Timestamp:
01/28/09 19:19:07 (5 years ago)
Author:
wehart
Message:

Adding a SingletonPlugin? class, which treats subclasses as
singletons, which are automatically created and registered.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/pyutilib/plugin/core.py

    r1067 r1069  
    55# Adapted from Trac. 
    66# 
     7# TODO: support for abstract classes 
    78 
    89# -*- coding: utf-8 -*- 
     
    2627import types 
    2728 
    28 __all__ = ['Plugin', 'ExtensionPoint', 'implements', 'Interface', 
     29__all__ = ['Plugin', 'SingletonPlugin',  
     30           'ExtensionPoint', 'implements', 'Interface', 
    2931           'PluginError', 'registered_services', 'ServiceManager', 
    3032           'registered_extension_points', 'Plugins'] 
     
    4042    """Global data for this package""" 
    4143    def __init__(self): 
     44        self.singleton_services={} 
    4245        self.services=set() 
    4346        self.registry = {} 
     
    9396        # Construct the interface, passing in this extension 
    9497        # 
    95         property.__init__(self, self.extensions) 
    9698        self.interface = interface 
    9799        self.__doc__ = 'List of services that implement `%s`' % self.interface.__name__ 
     100        # 
     101        # The property class defines an iterator, which calls the 'extensions'  
     102        # method. 
     103        # 
     104        property.__init__(self, self.extensions) 
    98105 
    99106    def extensions(self, arg=None): 
     
    135142    def __new__(cls, name, bases, d): 
    136143        """Find all interfaces that need to be registered.""" 
    137         if not '__interfaces__' in d: 
    138             __interfaces__ = set() 
    139             registry = Plugins.registry 
    140             for interface in d.get('_implements', set()): 
     144        # 
     145        # Avoid cycling in the Python logic by hard-coding the behavior 
     146        # for the Plugin and SingletonPlugin classes. 
     147        # 
     148        if name == "Plugin": 
     149            d['__singleton__'] = False 
     150            return type.__new__(cls, name, bases, d) 
     151        if name == "SingletonPlugin": 
     152            d['__singleton__'] = True 
     153            return type.__new__(cls, name, bases, d) 
     154        # 
     155        # Find all interfaces that this plugin will support 
     156        # 
     157        __interfaces__ = set() 
     158        registry = Plugins.registry 
     159        for interface in d.get('_implements', set()): 
     160            __interfaces__.add(interface) 
     161        for base in [base for base in bases if hasattr(base, '_implements')]: 
     162            for interface in base._implements: 
    141163                __interfaces__.add(interface) 
    142             for base in [base for base in bases if hasattr(base, '_implements')]: 
    143                 for interface in base._implements: 
    144                     __interfaces__.add(interface) 
    145             d['__interfaces__'] = __interfaces__ 
    146         return type.__new__(cls, name, bases, d) 
     164        d['__interfaces__'] = __interfaces__ 
     165        # 
     166        # Create a boolean, which indicates whether this is 
     167        # a singleton class. 
     168        # 
     169        if True in [issubclass(x, SingletonPlugin) for x in bases]: 
     170            d['__singleton__'] = True 
     171        else: 
     172            d['__singleton__'] = False 
     173        new_class = type.__new__(cls, name, bases, d) 
     174        if d['__singleton__']: 
     175            # 
     176            # Here, we create an istance of a singleton class, which 
     177            # registers itself in Plugins.singleton_services 
     178            # 
     179            new_class.__new__(new_class) 
     180        return new_class 
    147181 
    148182 
     
    155189    __metaclass__ = PluginMeta 
    156190 
    157     def __init__(self,mngr=None): 
    158         #print "Plugin INIT",self 
    159         #if isinstance(self,ServiceManager): 
     191    def __new__(cls, *args, **kwargs): 
     192        """Plugin constructor""" 
     193        if issubclass(cls, ServiceManager): 
     194            # 
     195            # If this service is also a ServiceManager, just invoke that 
     196            # 
     197            self = super(Plugin, cls).__new__(cls) 
     198        else: 
     199            # 
     200            # The normal case where the service is not also a ServiceManager 
     201            # 
     202            if cls in Plugins.singleton_services: 
     203                return Plugins.singleton_services[cls] 
     204            self = super(Plugin, cls).__new__(cls) 
     205            if self.__singleton__: 
     206                Plugins.singleton_services[cls] = self 
     207                Plugins.default_manager.activate(self) 
     208            # 
     209            # Register instance in extension point registery 
     210            # 
     211            registry = Plugins.registry 
     212            for interface in self.__interfaces__: 
     213                registry.setdefault(interface, set()).add(self) 
     214        # 
     215        # Activate the Plugin in a ServiceManager, if it is provided 
     216        # 
     217        if len(args) == 0: 
     218            mngr=None 
     219        else: 
     220            mngr=args[0] 
    160221        if not mngr is None: 
    161222            self.manager = mngr 
     
    163224            self.manager = Plugins.default_manager 
    164225        self.manager.activate(self) 
    165  
    166     def __new__(cls, *args, **kwargs): 
    167         """Plugin constructor""" 
    168         # If this service is also a ServiceManager, just invoke that 
    169         if issubclass(cls, ServiceManager): 
    170             self = super(Plugin, cls).__new__(cls) 
    171             self.id=Plugins.next_id() 
    172             return self 
    173  
    174         #if len(args) == 0: 
    175             #raise PluginError, "Must specify ServiceManager when constructing a Plugin class" 
    176         # The normal case where the service is not also a ServiceManager 
    177         self = super(Plugin, cls).__new__(cls) 
    178         #if args[0] is None: 
    179             #self.manager = Plugins.default_manager 
    180         #else: 
    181             #self.manager = args[0] 
    182         #self.manager.activate(self) 
    183         # 
    184         # Register instance in extension point registery 
    185         # 
    186         registry = Plugins.registry 
    187         for interface in self.__interfaces__: 
    188             registry.setdefault(interface, set()).add(self) 
    189226        # 
    190227        # Set unique instance id value 
     
    217254 
    218255 
    219 implements = Plugin.implements 
     256class SingletonPlugin(Plugin): 
     257    pass 
    220258 
    221259 
     
    268306        return True 
    269307 
     308 
     309implements = Plugin.implements 
     310 
     311 
    270312Plugins.reset() 
  • trunk/test/plugin/unit/test_core.py

    r1066 r1069  
    6767 
    6868    def setUp(self): 
     69        Plugins.reset() 
     70 
     71    def tearDown(self): 
    6972        Plugins.reset() 
    7073 
     
    108111 
    109112    def setUp(self): 
     113        Plugins.reset() 
     114 
     115    def tearDown(self): 
    110116        Plugins.reset() 
    111117 
     
    192198        Plugins.reset() 
    193199 
     200    def tearDown(self): 
     201        Plugins.reset() 
     202 
    194203    def test_init(self): 
    195204        """Test the behavior of a plugin that is a service manager""" 
Note: See TracChangeset for help on using the changeset viewer.