:mod:`dip.plugins`
==================
.. module:: dip.plugins

The :mod:`dip.plugins` module implements the infrastructure for
encapsulating application :term:`plugins<plugin>`.


:class:`ExtensionPoint`
-----------------------
.. class:: ExtensionPoint

    Base class: :class:`~dip.model.Model`

    The ExtensionPoint class is the default implementation of an
    :term:`extension point`.

    .. method:: ExtensionPoint.bind(obj, name)

        Bind an attribute of an object to the extension point and update it
        with all contributions made so far.
        
        :param obj:
            is the object containing the attribute to bind to.
        :param name:
            is the name of the attribute to bind to.

    .. method:: ExtensionPoint.contribute(contribution)

        Contribute an object to all bound attributes.
        
        :param contribution:
            is the object to contribute.


:class:`IExtensionPoint`
------------------------
.. class:: IExtensionPoint

    Base class: :class:`~dip.model.Interface`

    The IExtensionPoint interface defines the API of an
    :term:`extension point`.

    .. attribute:: contributions = List()

        The list of contributions made.

    .. attribute:: id = Str()

        The identifier of the extension point.

    .. method:: IExtensionPoint.bind(obj, name)

        Bind an attribute of an object to the extension point and update it
        with all contributions made so far.
        
        :param obj:
            is the object containing the attribute to bind to.
        :param name:
            is the name of the attribute to bind to.

    .. method:: IExtensionPoint.contribute(contribution)

        Contribute an object to all bound attributes.
        
        :param contribution:
            is the object to contribute.


:class:`IPlugin`
----------------
.. class:: IPlugin

    Base class: :class:`~dip.model.Interface`

    The IPlugin interface defines the API of a :term:`plugin`. 

    .. attribute:: enabled = Bool(True)

        This is set if the plugin is enabled.

    .. attribute:: id = Str()

        The identifier of the plugin.  Two plugins are considered equivalent if
        their factories have the same identifier, even though the factories
        themselves are different.

    .. attribute:: requires = List(Str())

        The list of identifiers of plugins that must be enabled before this one
        can be enabled.

    .. method:: IPlugin.configure(plugin_manager)

        This is called when the plugin is enabled to ask that it configures
        itself.
        
        :param plugin_manager:
            the plugin manager.


:class:`IPluginManager`
-----------------------
.. class:: IPluginManager

    Base class: :class:`~dip.model.Interface`

    The IPluginManager interface defines the API of a
    :term:`plugin manager`.

    .. attribute:: extension_points = List(IExtensionPoint)

        The list of extension points.

    .. attribute:: plugins = List(IPlugin)

        The list of contributed plugins.

    .. attribute:: services = List(IService)

        The list of contributed services.

    .. method:: IPluginManager.bind_extension_point(id, obj, name)

        Bind an extension point to an attribute of an object.  The
        attribute must have an ``append()`` method.
        
        :param id:
            is the identifier of the extension point.
        :param obj:
            is the object containing the attribute that the extension point is
            bound to.
        :param name:
            is the name of the attribute that the extension point is bound to.

    .. method:: IPluginManager.bind_service(interface, obj, name)

        Bind the service for an interface to an attribute of an object.
        
        :param interface:
            is the interface.
        :param obj:
            is the object containing the attribute that the service is bound
            to.
        :param name:
            is the name of the attribute that the service is bound to.

    .. method:: IPluginManager.choose_service(services)

        Choose a particular service from a list of possible services.
        
        :param services:
            a list of contributed services to choose from.
        :return:
            the chosen service or ``None`` if one wasn't chosen.

    .. method:: IPluginManager.contribute(id, contribution)

        Contribute an object to an extension point.
        
        :param id:
            is the identifier of the extension point.
        :param contribution:
            is the contribution to make to the extension point.

    .. method:: IPluginManager.service(interface)

        Get a service for a particular interface.
        
        :param interface:
            is the interface.
        :return:
            the service which will implement or be able to be adapted to the
            interface.  An exception is raised if there is no service
            available.


:class:`IService`
-----------------
.. class:: IService

    Base class: :class:`~dip.model.Interface`

    The IService interface defines the API of a :term:`service` definition.
        

    .. attribute:: implementation = Any()

        The service implementation.

    .. attribute:: interface = Subclass(Interface)

        The interface that the service implements.


:class:`PluginManager`
----------------------
.. class:: PluginManager

    Base class: :class:`~dip.model.Singleton`

    The PluginManager class is a singleton that provides access to a
    default :term:`plugin manager`.

    .. attribute:: instance = Instance(IPluginManager)

        The plugin manager instance.

    .. classmethod:: PluginManager.add_plugin(plugin)

        Add a plugin to the plugin manager.
        
        :param plugin:
            is the plugin.


:class:`Service`
----------------
.. class:: Service

    Base class: :class:`~dip.model.Model`

    The Service class is the default implementation of a :term:`service`
    definition.
