Logo Search packages:      
Sourcecode: mayavi2 version File versions  Download package

plugin.py

00001 """ The base class for all plugin implementations. """


# Standard library imports.
import logging
from os.path import join

# Enthought library imports.
from enthought.traits.api import Any, HasTraits, Instance, Int, List, Property
from enthought.traits.api import Str

# Local imports.
from preferences import Preferences
from preference_binding import PreferenceBinding


# Setup a logger for this module.
logger=logging.getLogger(__name__)


00021 class Plugin(HasTraits):
    """ The base class for all plugin implementations. """

    # The name of the plugin's user preferences file.
    PREFERENCES_FILE = 'preferences'

    #### 'Plugin' interface ##################################################

    # The plugin's globally unique identifier.
    id = Str

    # The application that the plugin is part of.
    application = Instance('enthought.envisage.core.application.Application')

    # The plugin's user preferences.
    preferences = Property(Instance(Preferences))

    # The plugin's state location is a directory on the local filesystem that
    # the plugin can read and write to at will.  By default, the plugin's
    # preferences are stored in here.
    state_location = Property(Str)

    #### Private interface ####################################################

    # Shadow trait for the 'preferences' property.
    _preferences = Any

    # Preference bindings.
    _preference_bindings = List

    # The IDs of all services registered by the plugin.
    _service_ids = List(Int)

    # Shadow trait for the 'state_location' property.
    _state_location = Any

    ###########################################################################
    # 'Plugin' interface.
    ###########################################################################

    #### Properties ###########################################################

    # preferences
00064     def _get_preferences(self):
        """ Returns the plugin's preferences. """

        if self._preferences is None:
            self._preferences = self._initialize_preferences()

        return self._preferences

    # state_location
00073     def _get_state_location(self):
        """ Returns the name of the plugin's state location. """

        if self._state_location is None:
            self._state_location = self._initialize_state_location()

        return self._state_location

    #### Methods ##############################################################

    # Lifecycle methods.
00084     def start(self, application):
        """ Starts the plugin.

        Can be called manually, but is usually called exactly once when the
        plugin is first required.

        """

        pass

00094     def stop(self, application):
        """ Stops the plugin.

        Can be called manually, but is usually called exactly once when the
        application exits.

        Notes
        -----

        * Envisage takes care of unregistering any services that were offered
          by the plugin, so you don't have to do anything here for that.

        * The default implementation calls `save_preferences()`.

        """

        self.save_preferences()

        return

    # Preferences.
00115     def bind_preference(self, obj, trait_name, preference_name=None,
                        preferences=None, default=None):
        """ Sets up a preference binding.

        A preference binding synchronizes a preference value with a trait
        on an object.

        If the preference name is **None**, the trait name is used.

        If the preferences instance is **None** the plugin's preferences are
        used.

        """

        if preference_name is None:
            preference_name = trait_name

        if preferences is None:
            preferences = self.preferences

        # fixme: We put the bindings in a list as a simple way to keep a
        # reference to them to prevent them getting garbage collected!
        self._preference_bindings.append(
            PreferenceBinding(
                obj           = obj,
                trait_name    = trait_name,
                pref_name     = preference_name,
                preferences   = preferences,
                default_value = default
            )
        )

        return

00149     def save_preferences(self):
        """ Saves the plugin's user preferences.

        This method actually saves only preferences that the user has changed
        from the plugin defaults.

        """

        # The pathname of the preferences file.
        filename = join(self.state_location, self.PREFERENCES_FILE)

        # Save 'em!
        self.preferences.save(filename)

        return

    # Convenience methods for common operations on the import manager.
00166     def import_symbol(self, symbol_path):
        """ Imports the symbol defined by *symbol_path*.

        Parameters
        ----------
        symbol_path : a string in the form 'foo.bar.baz'
            The module path to a symbol to import.

        The *symbol_path* value is turned into an import statement
        ``'from foo.bar import baz'``
        (i.e., the last component of the name is the symbol name, the rest
        is the module path to load it from).

        """

        return self.application.import_symbol(symbol_path)

00183     def get_class(self, class_path):
        """ Returns the class defined by **class_path**.

        Returns **None** if the class has not yet been loaded.

        """

        return self.application.get_class(class_path)

    # Convenience methods for common operations on the extension registry.
00193     def get_extensions(self, extension_point_id, plugin_id=None):
        """ Returns a list of all extensions made to an extension point. """

        return self.application.get_extensions(extension_point_id, plugin_id)

00198     def load_extensions(self, extension_point_id, plugin_id=None):
        """ Returns a list of all extensions made to an extension point.

        The difference between this and `get_extensions()` is that this method
        will make sure that the plugin that contributed each extension has
        been started.

        Parameters
        ----------
        extension_point_id : a class that is derived from **ExtensionPoint**
            The extension point whose extensions are retrieved.
        plugin_id : a plugin ID
            If specified, only this plugin's extensions to the extension point
            are returned

        """

        return self.application.load_extensions(extension_point_id, plugin_id)

00217     def extension_added(self, extension):
        """ Responds to new extensions added in the extension registry. """

        pass

    # Convenience methods for common operations on the application.
00223     def lookup_application_object(self, uol):
        """ Resolve a UOL (Universal Object Locator) to produce an actual object.

        For 'lookup' the UOL can be:

        * ``'service://a_service_identifier'``
        * ``'name://a/path/through/the/naming/service'``
        * ``'factory://package.module.callable'``
        * ``'import://package.module.symbol'``
        * ``'file://the/pathname/of/a/file/containing/a/UOL'``
        * ``'http://a/URL/pointing/to/a/text/document/containing/a/UOL'``

        fixme: This mechanism needs to be extensible with new UOL protocols.
        """

        return self.application.lookup_application_object(uol)

00240     def publish_application_object(self, uol, obj, properties=None):
        """ Publish an object via a UOL.

        For 'publishing' the UOL can be:

        * ``'service://a_service_identifier'``
        * ``'name://a/path/through/the/naming/service'``

        fixme: This mechanism needs to be extensible with new UOL protocols.
        """

        self.application.publish_application_object(uol, obj, properties)

        return

    # Convenience methods for common operations on the service registry.
00256     def get_service(self, interface, query=None):
        """ Returns at most one service that matches the specified query.

        Returns **None** if no such service is found.

        NOTE: Don't try to guess *which* one it will return -- the algorithm
        used by this method is subject to change without notice!

        """

        return self.application.get_service(interface, query)

00268     def get_services(self, interface, query=None):
        """ Returns all services that match the specified query.

        If no services match the query, then an empty list is returned.

        """

        return self.application.get_services(interface, query)

00277     def register_service(self, interface, obj, properties=None):
        """ Registers a service that implements the specified interface.

        Returns a service ID (a unique ID for the service within the
        application).

        """

        service_id = self.application.register_service(
            interface, obj, properties
        )

        self._service_ids.append(service_id)

        return service_id

00293     def unregister_service(self, service_id):
        """ Unregisters a service. """

        self.application.unregister_service(service_id)
        self._service_ids.remove(service_id)

        return

00301     def unregister_all_services(self):
        """ Unregisters all services offered by the plugin. """

        # Take a copy of the list since we are deleting its contents with
        # each call to 'unregister_service'!
        service_ids = self._service_ids[:]
        for service_id in service_ids:
            self.unregister_service(service_id)

        return

    ###########################################################################
    # Private interface.
    ###########################################################################

00316     def _create_default_preferences_dict(self, preferences_list):
        """ Return a dictionary of default values from a list of preferences.

            The dictionary should contain values based on priority ranking.

            Parameters:
            -----------
            preferences_list: List(Preferences)
                enthought.envisage.core.core_plugin_definition.Preferences

            Returns:
            --------
            final_dict: Dict(Str, PreferenceValue)

        """

        # fixme: The base Envisage should not be dependent on the core plugin
        from enthought.envisage.core.core_plugin_definition import \
            PreferenceValue

        final_dict = {}

        for preference in preferences_list:
            for k,v in preference.defaults.items():
                # If the current value is not a PreferenceValue, create one
                # using the value
                if not isinstance(v, PreferenceValue):
                    new_contribution = PreferenceValue(value=v,
                                                       priority=0)
                else:
                    new_contribution = v

                # If the key is not already in the dictionary, add it; else
                # check priority and enter it
                if not final_dict.has_key(k) or \
                     final_dict[k].priority < new_contribution.priority:
                    final_dict[k] = new_contribution

        return final_dict


00357     def _create_others_to_self_default_preferences_dict(self):
        """ Return a dictionary containing plugin preference defaults which
            are contributed by other plugins and targetted to self.

            Returns:
            -------
            final_dict: Dict(Str, PreferenceValue)
                enthought.envisage.core.core_plugin_definition.PreferenceValue

        """

        # fixme: The base Envisage should not be dependent on the core plugin
        from enthought.envisage.core.core_plugin_definition import Preferences

        # Obtain preferences extensions contributed by others to self
        extension_registry = self.application.extension_registry

        self_extensions = extension_registry.get_extensions(Preferences,self.id)
        all_extensions = extension_registry.get_extensions(Preferences)
        others_extensions = list(set(all_extensions)-set(self_extensions))

        others_to_self_extensions = \
            [extension for extension in others_extensions \
             if extension.target == self.id]

        # Build the dictionary of default values to Preferences
        return self._create_default_preferences_dict(others_to_self_extensions)


00386     def _create_self_to_self_default_preferences_dict(self):
        """ Return a dictionary containing plugin preference defaults which
            are contributed by self and targetted to self.

            No target is generally defaulted to self.

            Returns:
            -------
            final_dict: Dict(Str, PreferenceValue)
                enthought.envisage.core.core_plugin_definition.PreferenceValue

        """

        # fixme: The base Envisage should not be dependent on the core plugin
        from enthought.envisage.core.core_plugin_definition import Preferences

        extension_registry = self.application.extension_registry
        self_extensions = extension_registry.get_extensions(Preferences,self.id)

        self_to_self_extensions = [extension for extension in self_extensions \
                                   if extension.target == '' or \
                                   extension.target == self.id]


        # Build the dictionary of default values to Preferences
        return self._create_default_preferences_dict(self_to_self_extensions)


00414     def _initialize_preferences(self):
        """ Initializes the plugin's preferences.

        Any previously saved user preferences are loaded by this method.

        """

        # Create an empty set of preferences.
        preferences = Preferences()

        # Initialize any default preference values defined in the plugin
        # definition.
        self._initialize_default_preferences(preferences)

        # Initialize any user preferences found in the plugin's user
        # preferences file.
        self._initialize_user_preferences(preferences)

        return preferences


00435     def _initialize_default_preferences(self, preferences):
        """ Initializes the plugin's default preferences (if it has any). """

        # The preferences extension point.  We do the import here because this
        # class is imported by the application class before the 'plugins'
        # directory has been added to the Python path.
        #
        # Get all extensions made by :
        # 1. the plugin to the preferences extension point targetted to either
        #    itself or no other plugins
        # 2. other plugins to the preferences extension point targetted to this
        #    plugin
        #
        # This is based on the modifications made on 05/17/2007 on Preferences
        # class which helps contributions to be ranked by priority.

        preferences.defaults = self._merge_default_preferences_dicts(
                      self._create_self_to_self_default_preferences_dict(),
                      self._create_others_to_self_default_preferences_dict())

        return


00458     def _initialize_user_preferences(self, preferences):
        """ Initializes the plugin's user preferences (if it has any). """

        # The pathname of the user preferences file.
        filename = join(self.state_location, self.PREFERENCES_FILE)

        # Load any user preferences from the file.
        preferences.load(filename)

        return


00470     def _initialize_state_location(self):
        """ Initializes the plugin's state location. """

        # The application tells us where our state location is!
        return self.application.get_plugin_state_location(self)


00477     def _merge_default_preferences_dicts(self, dict1, dict2):
        """ Merge dictionaries of default preference values to return a single
            dictionary.

            Merge using priority ranking.

            Parameters:
            -----------
            dict1: Dict(Str, PreferenceValue)
                enthought.envisage.core.core_plugin_definition.PreferenceValue
            dict2: Dict(Str, PreferenceValue)

            Returns:
            --------
            final_dict: Dict(Str, Any)

        """

        # Default to the first dictionary
        final_dict = dict1

        # Populate final_dict with the second dictionary
        for k,v in dict2.items():
            # If the key is not already present in the final_dict or its
            # priority is less than what the dict2 item is offering, modify
            # final_dict
            if not final_dict.has_key(k) or final_dict[k].priority < v.priority:
                final_dict[k] = v

        # Trim the values of final_dict
        for k,v in final_dict.items():
            final_dict[k] = v.value

        return final_dict


#### EOF ######################################################################

Generated by  Doxygen 1.6.0   Back to index