1 # Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
3 # This file is part of Hooke.
5 # Hooke is free software: you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation, either
8 # version 3 of the License, or (at your option) any later version.
10 # Hooke is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with Hooke. If not, see
17 # <http://www.gnu.org/licenses/>.
19 """The `plugin` module provides optional submodules that add new Hooke
22 All of the science happens in here.
25 import ConfigParser as configparser
27 from ..config import Setting
28 from ..util.pluggable import IsSubclass, construct_graph
33 # ('curvetools', True),
36 # ('flatfilts-rolf', True),
38 # ('generalclamp', True),
39 # ('generaltccd', True),
40 # ('generalvclamp', True),
43 # ('massanalysis', True),
44 # ('multidistance', True),
48 # ('procplots', True),
50 # ('showconvoluted', True),
51 # ('superimpose', True),
54 """List of plugin modules and whether they should be included by
55 default. TODO: autodiscovery
66 """List of builtin modules. TODO: autodiscovery
69 PLUGIN_SETTING_SECTION = 'plugins'
70 """Name of the config section which controls plugin selection.
74 # Plugins and settings
76 class Plugin (object):
77 """A pluggable collection of Hooke commands.
79 Fulfills the same role for Hooke that a software package does for
82 def __init__(self, name):
84 self.setting_section = '%s plugin' % self.name
88 def dependencies(self):
89 """Return a list of names of :class:`Plugin`\s we require."""
92 def default_settings(self):
93 """Return a list of :class:`hooke.config.Setting`\s for any
94 configurable plugin settings.
96 The suggested section setting is::
98 Setting(section=self.setting_section, help=self.__doc__)
102 def _setup_commands(self):
103 """Perform internal setup on stored commands.
107 * Adds a `plugin` attribute to each command so they can access
108 the plugin configuration with `.plugin.config`.
110 for command in self._commands:
111 command.plugin = self
114 """Return a list of :class:`hooke.command.Command`\s provided.
116 return list(self._commands)
118 class Builtin (Plugin):
119 """A required collection of Hooke commands.
121 These "core" plugins provide essential administrative commands
122 (playlist handling, etc.).
126 # Construct plugin dependency graph and load plugin instances.
128 PLUGIN_GRAPH = construct_graph(
129 this_modname=__name__,
130 submodnames=[name for name,include in PLUGIN_MODULES] + BUILTIN_MODULES,
131 class_selector=IsSubclass(Plugin, blacklist=[Plugin, Builtin]))
132 """Topologically sorted list of all possible :class:`Plugin`\s and
136 def default_settings():
137 settings = [Setting(PLUGIN_SETTING_SECTION,
138 help='Enable/disable default plugins.')]
139 for pnode in PLUGIN_GRAPH:
140 if pnode.data.name in BUILTIN_MODULES:
141 continue # builtin inclusion is not optional
143 default_include = [di for mod_name,di in PLUGIN_MODULES
144 if mod_name == plugin.name][0]
145 help = 'Commands: ' + ', '.join([c.name for c in plugin.commands()])
146 settings.append(Setting(
147 section=PLUGIN_SETTING_SECTION,
149 value=str(default_include),
152 for pnode in PLUGIN_GRAPH:
154 settings.extend(plugin.default_settings())
157 def load_graph(graph, config, include_section):
162 include = config.getboolean(include_section, item.name)
163 except configparser.NoOptionError:
164 include = True # non-optional include (e.g. a Builtin)
167 item.config = dict(config.items(item.setting_section))
168 except configparser.NoSectionError: