3 """The `plugin` module provides optional submodules that add new Hooke
6 All of the science happens in here.
9 import ConfigParser as configparser
11 from ..config import Setting
12 from ..util.pluggable import IsSubclass, construct_graph
17 # ('curvetools', True),
20 # ('flatfilts-rolf', True),
21 # ('flatfilts', True),
22 # ('generalclamp', True),
23 # ('generaltccd', True),
24 # ('generalvclamp', True),
27 # ('massanalysis', True),
28 # ('multidistance', True),
32 # ('procplots', True),
34 # ('showconvoluted', True),
35 # ('superimpose', True),
38 """List of plugin modules and whether they should be included by
39 default. TODO: autodiscovery
49 """List of builtin modules. TODO: autodiscovery
52 PLUGIN_SETTING_SECTION = 'plugins'
53 """Name of the config section which controls plugin selection.
57 # Plugins and settings
59 class Plugin (object):
60 """A pluggable collection of Hooke commands.
62 Fulfills the same role for Hooke that a software package does for
65 def __init__(self, name):
67 self.setting_section = '%s plugin' % self.name
70 def dependencies(self):
71 """Return a list of :class:`Plugin`\s we require."""
74 def default_settings(self):
75 """Return a list of :class:`hooke.config.Setting`\s for any
76 configurable plugin settings.
78 The suggested section setting is::
80 Setting(section=self.setting_section, help=self.__doc__)
85 """Return a list of :class:`hooke.command.Command`\s provided.
89 class Builtin (Plugin):
90 """A required collection of Hooke commands.
92 These "core" plugins provide essential administrative commands
93 (playlist handling, etc.).
97 # Construct plugin dependency graph and load plugin instances.
99 PLUGIN_GRAPH = construct_graph(
100 this_modname=__name__,
101 submodnames=[name for name,include in PLUGIN_MODULES] + BUILTIN_MODULES,
102 class_selector=IsSubclass(Plugin, blacklist=[Plugin, Builtin]))
103 """Topologically sorted list of all possible :class:`Plugin`\s and
107 def default_settings():
108 settings = [Setting(PLUGIN_SETTING_SECTION,
109 help='Enable/disable default plugins.')]
110 for pnode in PLUGIN_GRAPH:
111 if pnode.data.name in BUILTIN_MODULES:
112 continue # builtin inclusion is not optional
114 default_include = [di for mod_name,di in PLUGIN_MODULES
115 if mod_name == plugin.name][0]
116 help = 'Commands: ' + ', '.join([c.name for c in plugin.commands()])
117 settings.append(Setting(
118 section=PLUGIN_SETTING_SECTION,
120 value=str(default_include),
123 for pnode in PLUGIN_GRAPH:
125 settings.extend(plugin.default_settings())
128 def load_graph(graph, config, include_section):
133 include = config.getboolean(include_section, item.name)
134 except configparser.NoOptionError:
135 include = True # non-optional include (e.g. a Builtin)
138 item.config = dict(config.items(item.setting_section))
139 except configparser.NoSectionError: