import pkg_resources

def build_plugin_manager_doc(self):
    self.__doc__ = []
    if self._brief:
        self.__doc__.append(self._brief)
        self.__doc__.append('')
    if self._details:
        self.__doc__.append(self._details)
        self.__doc__.append('')
    self.__doc__.append(":Available Implementations:")
    self.__doc__.extend(" - \'" + plugin.name + '\'' for plugin in pkg_resources.iter_entry_points(self._group))
    self.__doc__.extend(" - \'" + plugin + '\'' for plugin in self._cache)
    self.__doc__ = '\n'.join(self.__doc__)

class PluginManagerImplementationDescriptor(object):
    """A plugin plugin manager descriptor that returns and sets plugin_manager implementations
    """

    def __get__(self, obj, objtype):
        if hasattr(obj, '_plugin'):
            plugin = obj._plugin
            while plugin in obj._cache:
                plugin = obj._cache[plugin]
            if callable(plugin):
                return plugin
            else:
                return pkg_resources.iter_entry_points(obj._group, plugin).next().load()
        else:
            def __call__(self, *args, **kwargs):
                """No plugin selected"""
                raise NotImplementedError("An plugin must be selected using \'plugin\' field")
            return __call__

class PluginManagerIdentificationDescriptor(object):
    """
    """

    def __get__(self, obj, cls):
        if not hasattr(obj, '_plugin'):
            raise ValueError('\'plugin\' identification not setted')
        return obj._plugin

    def __set__(self, obj, plugin):
        obj._plugin = plugin
        build_plugin_manager_doc(obj)


class PluginManager(object):

    __call__ = PluginManagerImplementationDescriptor()

    plugin = PluginManagerIdentificationDescriptor()

    def __init__(self, group, brief="", details=""):
        """Create a plugin manager"""
        self._group = group
        self._brief = brief
        self._details = details
        self._cache = dict()
        build_plugin_manager_doc(self)

    def __iter__(self):
        for key in self._cache.keys():
            yield key
        for plugin in pkg_resources.iter_entry_points(self._group):
            yield plugin.name

    def __contains__(self, plugin):
        """
        """
        return plugin in self._cache or len(list(pkg_resources.iter_entry_points(self._group, plugin))) > 0

    def __getitem__(self, plugin):
        """
        """
        plugin, self.plugin = self.plugin, plugin
        plugin, self.plugin = self.__call__, plugin
        return plugin

    def __setitem__(self, plugin, implementation):
        if not isinstance(plugin, basestring):
            raise TypeError('\'plugin\' parameter must be a basestring instance')
        if callable(implementation):
            self._cache[plugin] = implementation
        elif isinstance(implementation, basestring):
            if implementation not in self:
                raise ValueError('\'implementation\' parameter must be an existing plugin')
            if plugin == implementation:
                raise ValueError('\'plugin\' and \'implementation\' parameters cannot have the same value')
            self._cache[plugin] = implementation
        else:
            raise TypeError('must be callable or a basestring instance')
        build_plugin_manager_doc(self)

@@ -19,576 +19,27 @@
 es%0A%0A
-def build_plugin_manager_doc(self):%0A    self.__doc__ = %5B%5D%0A    if self._brief:%0A        self.__doc__.append(self._brief)%0A        self.__doc__.append('')%0A    if self._details:%0A        self.__doc__.append(self._details)%0A        self.__doc__.append('')%0A    self.__doc__.append(%22:Available Implementations:%22)%0A    self.__doc__.extend(%22 - %5C'%22 + plugin.name + '%5C'' for plugin in pkg_resources.iter_entry_points(self._group))%0A    self.__doc__.extend(%22 - %5C'%22 + plugin + '%5C'' for plugin in self._cache)%0A    self.__doc__ = '%5Cn'.join(self.__doc__)%0A%0Aclass PluginManagerImplementation
+class PluginFunctor
 Desc
@@ -199,48 +199,8 @@
 e):%0A
-        if hasattr(obj, '_plugin'):%0A    
     
@@ -220,104 +220,15 @@
 obj.
-_
 plugin%0A
-            while plugin in obj._cache:%0A                plugin = obj._cache%5Bplugin%5D%0A    
     
@@ -238,30 +238,16 @@
  if 
-callable(
 plugin
-)
 :%0A
-    
     
@@ -265,121 +265,19 @@
 urn 
-plugin%0A            else:%0A                return pkg_resources.iter_entry_points(obj._group, plugin).next().load()
+obj%5Bplugin%5D
 %0A   
@@ -517,467 +517,54 @@
 ugin
-ManagerIdentificationDescriptor(object):%0A    %22%22%22%0A    %22%22%22%0A%0A    def __get__(self, obj, cls):%0A        if not hasattr(obj, '_plugin'):%0A            raise ValueError('%5C'plugin%5C' identification not setted')%0A        return obj._plugin%0A%0A    def __set__(self, obj, plugin):%0A        obj._plugin = plugin%0A        build_plugin_manager_doc(obj)%0A%0A%0Aclass PluginManager(object):%0A%0A    __call__ = PluginManagerImplementationDescriptor()%0A%0A    plugin = PluginManagerIdentification
+Functor(object):%0A%0A    __call__ = PluginFunctor
 Desc
@@ -784,47 +784,8 @@
 ct()
-%0A        build_plugin_manager_doc(self)
 %0A%0A  
@@ -1206,49 +1206,105 @@
     
+while 
 plugin
-,
+ in
  self.
-plugin = self.plugin, 
+_cache:%0A            plugin = obj._cache%5Bplugin%5D%0A        if callable(
 plugin
+):
 %0A   
@@ -1312,73 +1312,125 @@
     
-plugin, self.plugin = self.__call__, plugin%0A        return plugin
+    return plugin%0A        else:%0A            return pkg_resources.iter_entry_points(self._group, plugin).next().load()
 %0A%0A  
@@ -2170,43 +2170,929 @@
 e')%0A
+%0A
     
-    build_plugin_manager_doc(self)
+@property%0A    def __doc__(self):%0A        __doc__ = %5B%5D%0A        if self._brief:%0A            __doc__.append(self._brief)%0A            __doc__.append('')%0A        if self._details:%0A            __doc__.append(self._details)%0A            __doc__.append('')%0A        __doc__.append(%22:Available Implementations:%22)%0A        __doc__.extend(%22 - %5C'%22 + plugin.name + '%5C'' for plugin in pkg_resources.iter_entry_points(self._group))%0A        __doc__.extend(%22 - %5C'%22 + plugin + '%5C'' for plugin in self._cache)%0A        return '%5Cn'.join(__doc__)%0A%0A    @property%0A    def group(self):%0A        return self._group%0A%0A    @property%0A    def plugin(self):%0A        return getattr(self, '__plugin', None)%0A%0A    @plugin.setter%0A    def plugin(self, plugin):%0A        if not plugin in self:%0A            raise ValueError('%5C'plugin%5C' parameter should be one of ' + ', '.join('%5C'' + name + '%5C'' for plugin in self))%0A        else:%0A            self._plugin = plugin
 %0A

Improve health