1 """The `plugin` module provides optional submodules that add new Hooke
4 All of the science happens in here.
7 import ConfigParser as configparser
9 from ..config import Setting
10 from ..util.pluggable import IsSubclass, construct_graph
15 # ('curvetools', True),
18 # ('flatfilts-rolf', True),
19 # ('flatfilts', True),
20 # ('generalclamp', True),
21 # ('generaltccd', True),
22 # ('generalvclamp', True),
25 # ('massanalysis', True),
26 # ('multidistance', True),
30 # ('procplots', True),
32 # ('showconvoluted', True),
33 # ('superimpose', True),
36 """List of plugin modules and whether they should be included by
37 default. TODO: autodiscovery
47 """List of builtin modules. TODO: autodiscovery
50 PLUGIN_SETTING_SECTION = 'plugins'
51 """Name of the config section which controls plugin selection.
55 # Plugins and settings
57 class Plugin (object):
58 """A pluggable collection of Hooke commands.
60 Fulfills the same role for Hooke that a software package does for
63 def __init__(self, name):
65 self.setting_section = '%s plugin' % self.name
68 def dependencies(self):
69 """Return a list of :class:`Plugin`\s we require."""
72 def default_settings(self):
73 """Return a list of :class:`hooke.config.Setting`\s for any
74 configurable plugin settings.
76 The suggested section setting is::
78 Setting(section=self.setting_section, help=self.__doc__)
83 """Return a list of :class:`hooke.command.Command`\s provided.
87 class Builtin (Plugin):
88 """A required collection of Hooke commands.
90 These "core" plugins provide essential administrative commands
91 (playlist handling, etc.).
95 # Construct plugin dependency graph and load plugin instances.
97 PLUGIN_GRAPH = construct_graph(
98 this_modname=__name__,
99 submodnames=[name for name,include in PLUGIN_MODULES] + BUILTIN_MODULES,
100 class_selector=IsSubclass(Plugin, blacklist=[Plugin, Builtin]))
101 """Topologically sorted list of all possible :class:`Plugin`\s and
105 def default_settings():
106 settings = [Setting(PLUGIN_SETTING_SECTION,
107 help='Enable/disable default plugins.')]
108 for pnode in PLUGIN_GRAPH:
109 if pnode.data.name in BUILTIN_MODULES:
110 continue # builtin inclusion is not optional
112 default_include = [di for mod_name,di in PLUGIN_MODULES
113 if mod_name == plugin.name][0]
114 help = 'Commands: ' + ', '.join([c.name for c in plugin.commands()])
115 settings.append(Setting(
116 section=PLUGIN_SETTING_SECTION,
118 value=str(default_include),
121 for pnode in PLUGIN_GRAPH:
123 settings.extend(plugin.default_settings())
126 def load_graph(graph, config, include_section):
131 include = config.getboolean(include_section, item.name)
132 except configparser.NoOptionError:
133 include = True # non-optional include (e.g. a Builtin)
136 item.config = dict(config.items(item.setting_section))
137 except configparser.NoSectionError: