"""
import ConfigParser as configparser
+import logging
from ..config import Setting
from ..util.pluggable import IsSubclass, construct_graph
"""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
"""
return list(self._commands)
+
class Builtin (Plugin):
"""A required collection of Hooke commands.
"""
pass
+
# Plugin utility functions
def argument_to_setting(section_name, argument):
return Setting(section_name, option=argument.name, value=argument.default,
help=argument._help)
+
# Construct plugin dependency graph and load plugin instances.
PLUGIN_GRAPH = construct_graph(
return settings
def load_graph(graph, config, include_section):
+ enabled = {}
items = []
for node in graph:
item = node.data
include = config.getboolean(include_section, item.name)
except configparser.NoOptionError:
include = True # non-optional include (e.g. a Builtin)
+ enabled[item.name] = include
+ print item.name, include
if include == True:
+ 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
try:
item.config = dict(config.items(item.setting_section))
except configparser.NoSectionError:
Hooke plugin, including description of main Hooke internals.
"""
-import numpy as np
-
-from .. import curve as lhc
-
-'''
-SYNTAX OF DATA TYPE DECLARATION:
- type = type of object
- [ type ] = list containing objects of type
- {typekey:typearg} = dictionary with keys of type typekey and args of type typearg
- ( type ) = tuple containing objects of type
-'''
-
-
-class tutorialCommands(object):
- '''
- Here we define the class containing all the Hooke commands we want to define
- in the plugin.
-
- Notice the class name!!
- The syntax is filenameCommands. That is, if your plugin is pluggy.py, your class
- name is pluggyCommands.
-
- Otherwise, the class will be ignored by Hooke.
- '''
-
- def _plug_init(self):
- '''
- This is the plugin initialization.
- When Hooke starts and the plugin is loaded, this function is executed.
- If there is something you need to do when Hooke starts, code it in this function.
- '''
+from numpy import arange
+
+from ..command import Command, Argument, Failure
+from ..playlist import FilePlaylist
+from ..plugin import Plugin
+
+
+class TutorialPlugin (Plugin):
+ """An example plugin explaining how to code plugins.
+
+ Unlike previous versions of Hooke, the class name is no longer
+ important. Plugins identify themselves to
+ :func:`hooke.util.pluggable.construct_graph` by being subclasses
+ of :class:`hooke.plugin.Plugin`. However, for consistency we
+ suggest the following naming scheme, show here for the 'tutorial'
+ plugin:
+
+ =========== ==============
+ module file tutorial.py
+ class name TutorialPlugin
+ .name 'tutorial'
+ =========== ==============
+
+ To ensure filename sanity,
+ :func:`hooke.util.pluggable.construct_graph` requires that
+ :attr:`name` does match the submodule name, but don't worry,
+ you'll get a clear exception message if you make a mistake.
+ """
+ def __init__(self):
+ """TutorialPlugin initialization code.
+
+ We call our base class' :meth:`__init__` and setup
+ :attr:`_commands`.
+ """
+ # This is the plugin initialization. When Hooke starts and
+ # the plugin is loaded, this function is executed. If there
+ # is something you need to do when Hooke starts, code it in
+ # this function.
print 'I am the Tutorial plugin initialization!'
+ # This super() call similar to the old-style
+ # Plugin.__init__
+ # but super() is more robust under multiple inheritance.
+ # See Guido's introduction:
+ # http://www.python.org/download/releases/2.2.3/descrintro/#cooperation
+ # And the related PEPs:
+ # http://www.python.org/dev/peps/pep-0253/
+ # http://www.python.org/dev/peps/pep-3135/
+ super(TutorialPlugin, self).__init__(name='tutorial')
+
+ # We want :meth:`commands` to return a list of
+ # :class:`hooke.command.Command` instances. Rather than
+ # instantiate the classes for each call to :meth:`commands`,
+ # we instantiate them in a list here, and rely on
+ # :meth:`hooke.plugin.Plugin.commands` to return copies of
+ # that list.
+ self._commands = [] #CommandInit]
+
+
+ def dependencies(self):
+ """Return a list of names of :class:`hooke.plugin.Plugin`\s we
+ require.
+
+ Some plugins use features from other plugins. Hooke makes sure that
+ plugins are configured in topological order and that no plugin is
+ enabled if it is missing dependencies.
+ """
+ return ['vclamp']
#Here we initialize a local configuration variable; see plotmanip_absvalue() for explanation.
self.config['tutorial_absvalue']=0
- pass
def do_nothing(self,args):
'''
'''
#We generate some interesting data to plot for this example.
- xdata1=np.arange(-5,5,0.1)
- xdata2=np.arange(-5,5,0.1)
+ xdata1=arange(-5,5,0.1)
+ xdata2=arange(-5,5,0.1)
ydata1=[item**2 for item in xdata1]
ydata2=[item**3 for item in xdata2]
How to draw a scatter plot.
'''
#We generate some interesting data to plot for this example.
- xdata1=np.arange(-5,5,1)
- xdata2=np.arange(-5,5,1)
+ xdata1=arange(-5,5,1)
+ xdata2=arange(-5,5,1)
ydata1=[item**2 for item in xdata1]
ydata2=[item**3 for item in xdata2]