Run update-copyright.py.
[hooke.git] / hooke / plugin / __init__.py
index 89a23b248e750b0bf8220dd2296a9c7e622d7fe1..78a9f95087fc34b2717e29f8fedc585c24c9b381 100644 (file)
@@ -1,20 +1,19 @@
-# Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
+# Copyright (C) 2010-2012 W. Trevor King <wking@drexel.edu>
 #
 # This file is part of Hooke.
 #
-# Hooke is free software: you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation, either
-# version 3 of the License, or (at your option) any later version.
+# Hooke is free software: you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
 #
-# Hooke is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
+# Hooke is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
 #
-# You should have received a copy of the GNU Lesser General Public
-# License along with Hooke.  If not, see
-# <http://www.gnu.org/licenses/>.
+# You should have received a copy of the GNU Lesser General Public License
+# along with Hooke.  If not, see <http://www.gnu.org/licenses/>.
 
 """The `plugin` module provides optional submodules that add new Hooke
 commands.
@@ -23,6 +22,7 @@ All of the science happens in here.
 """
 
 import ConfigParser as configparser
+import logging
 
 from ..config import Setting
 from ..util.pluggable import IsSubclass, construct_graph
@@ -30,37 +30,36 @@ from ..util.pluggable import IsSubclass, construct_graph
 
 PLUGIN_MODULES = [
 #    ('autopeak', True),
-#    ('curvetools', True),
+    ('convfilt', True),
     ('cut', True),
-#    ('fit', True),
-#    ('flatfilts-rolf', True),
-#    ('flatfilts', True),
-#    ('generalclamp', True),
-#    ('generaltccd', True),
-#    ('generalvclamp', True),
+#    ('fclamp', True),
+    ('flatfilt', True),
 #    ('jumpstat', True),
-#    ('macro', True),
 #    ('massanalysis', True),
 #    ('multidistance', True),
 #    ('multifit', True),
 #    ('pcluster', True),
-#    ('peakspot', True),
-#    ('procplots', True),
-#    ('review', True),
+    ('polymer_fit', True),
 #    ('showconvoluted', True),
 #    ('superimpose', True),
-#    ('tutorial', True),
+#    ('tccd', True),
+    ('tutorial', True),
+    ('vclamp', True),
     ]
 """List of plugin modules and whether they should be included by
 default.  TODO: autodiscovery
 """
 
 BUILTIN_MODULES = [
+    'command_stack',
     'config',
     'curve',
     'debug',
+    'engine',
+    'license',
     'note',
     'playlist',
+    'playlists',
     'system',
     ]
 """List of builtin modules.  TODO: autodiscovery
@@ -77,15 +76,18 @@ class Plugin (object):
     """A pluggable collection of Hooke commands.
 
     Fulfills the same role for Hooke that a software package does for
-    an operating system.
+    an operating system: contains a chunk of related commands and
+    routines.  Command configuration also happens on the `Plugin`
+    level, with per-plugin sections in the configuration file.
     """
     def __init__(self, name):
         self.name = name
         self.setting_section = '%s plugin' % self.name
         self.config = {}
+        self._commands = []
 
     def dependencies(self):
-        """Return a list of :class:`Plugin`\s we require."""
+        """Return a list of names of :class:`Plugin`\s we require."""
         return []
 
     def default_settings(self):
@@ -101,7 +103,8 @@ class Plugin (object):
     def commands(self):
         """Return a list of :class:`hooke.command.Command`\s provided.
         """
-        return []
+        return list(self._commands)
+
 
 class Builtin (Plugin):
     """A required collection of Hooke commands.
@@ -111,6 +114,25 @@ class Builtin (Plugin):
     """
     pass
 
+
+# Plugin utility functions
+
+def argument_to_setting(section_name, argument):
+    """Convert an :class:`~hooke.command.Argument` to a
+    `~hooke.conf.Setting`.
+
+    This is useful if, for example, you want to define arguments with
+    configurable default values.
+
+    Conversion is lossy transition, because
+    :class:`~hooke.command.Argument`\s store more information than
+    `~hooke.conf.Setting`\s.
+    """
+    return Setting(section_name, option=argument.name, value=argument.default,
+                   type=argument.type, count=argument.count,
+                   help=argument._help)
+
+
 # Construct plugin dependency graph and load plugin instances.
 
 PLUGIN_GRAPH = construct_graph(
@@ -143,6 +165,7 @@ def default_settings():
     return settings
 
 def load_graph(graph, config, include_section):
+    enabled = {}
     items = []
     for node in graph:
         item = node.data
@@ -150,10 +173,15 @@ def load_graph(graph, config, include_section):
             include = config.getboolean(include_section, item.name)
         except configparser.NoOptionError:
             include = True # non-optional include (e.g. a Builtin)
+        enabled[item.name] = include
         if include == True:
-            try:
-                item.config = dict(config.items(item.setting_section))
-            except configparser.NoSectionError:
-                pass
+            for dependency in node:
+                if enabled.get(dependency.data.name, None) != True:
+                    log = logging.getLogger('hooke')
+                    log.warn(
+                     'could not setup plugin %s.  unsatisfied dependency on %s.'
+                     % (item.name, dependency.data.name))
+                    enabled[item.name] = False
+                    continue
             items.append(item)
     return items