"""
from ..config import Setting
-from ..plugin import construct_graph, IsSubclass
+from ..util.pluggable import IsSubclass, construct_graph
+
DRIVER_MODULES = [
# ('csvdriver', True),
point.absolute_coords=xvector[index],yvector[index]
point.find_graph_coords(xvector,yvector)
return point
-
-#HERE COMMANDS BEGIN
-
- def help_set(self):
- print '''
-SET
-Sets a local configuration variable
--------------
-Syntax: set [variable] [value]
- '''
- def do_set(self,args):
- #FIXME: some variables in self.config should be hidden or intelligently configurated...
- args=args.split()
- if len(args)==0:
- print 'You must specify a variable and a value'
- print 'Available variables:'
- print self.config.keys()
- return
- if args[0] not in self.config.keys():
- print 'This is not an internal Hooke variable!'
- return
- if len(args)==1:
- #FIXME:we should reload the config file and reset the config value
- print self.config[args[0]]
- return
- key=args[0]
- try: #try to have a numeric value
- value=float(args[1])
- except ValueError: #if it cannot be converted to float, it's None, or a string...
- value=args[1]
- if value.lower()=='none':
- value=None
- else:
- value=args[1]
-
- self.config[key]=value
- self.do_plot(0)
class PointResponse (Response):
def __init__(self, value):
super(PointResponse, self).__init__('point', value)
+
+
+class Notification (object):
+ def __init__(self, type):
+ self.type = type
+
+class ReloadUserInterfaceConfig (Notification):
+ def __init__(self, config):
+ super(ReloadUserInterfaceConfig, self).__init__(
+ 'reload user interface config')
+ self.config = config
import ConfigParser as configparser
from ..config import Setting
-from ..util.graph import Node, Graph
+from ..util.pluggable import IsSubclass, construct_graph
PLUGIN_MODULES = [
"""
BUILTIN_MODULES = [
+ 'config',
'debug',
'note',
'playlist',
# Construct plugin dependency graph and load plugin instances.
-def construct_graph(this_modname, submodnames, class_selector,
- assert_name_match=True):
- """Search the submodules `submodnames` of a module `this_modname`
- for class objects for which `class_selector(class)` returns
- `True`. These classes are instantiated, and the `instance.name`
- is compared to the `submodname` (if `assert_name_match` is
- `True`).
-
- The instances are further arranged into a dependency
- :class:`hooke.util.graph.Graph` according to their
- `instance.dependencies()` values. The topologically sorted graph
- is returned.
- """
- instances = {}
- for submodname in submodnames:
- count = len([s for s in submodnames if s == submodname])
- assert count > 0, 'No %s entries: %s' % (submodname, submodnames)
- assert count == 1, 'Multiple (%d) %s entries: %s' \
- % (count, submodname, submodnames)
- this_mod = __import__(this_modname, fromlist=[submodname])
- submod = getattr(this_mod, submodname)
- for objname in dir(submod):
- obj = getattr(submod, objname)
- if class_selector(obj):
- instance = obj()
- if assert_name_match == True and instance.name != submodname:
- raise Exception(
- 'Instance name %s does not match module name %s'
- % (instance.name, submodname))
- instances[instance.name] = instance
- nodes = {}
- for i in instances.values(): # make nodes for each instance
- nodes[i.name] = Node(data=i)
- for n in nodes.values(): # fill in dependencies for each node
- n.extend([nodes[name] for name in n.data.dependencies()])
- graph = Graph(nodes.values())
- graph.topological_sort()
- return graph
-
-class IsSubclass (object):
- """A safe subclass comparator.
-
- Examples
- --------
-
- >>> class A (object):
- ... pass
- >>> class B (A):
- ... pass
- >>> C = 5
- >>> is_subclass = IsSubclass(A)
- >>> is_subclass(A)
- True
- >>> is_subclass = IsSubclass(A, blacklist=[A])
- >>> is_subclass(A)
- False
- >>> is_subclass(B)
- True
- >>> is_subclass(C)
- False
- """
- def __init__(self, base_class, blacklist=None):
- self.base_class = base_class
- if blacklist == None:
- blacklist = []
- self.blacklist = blacklist
- def __call__(self, other):
- try:
- subclass = issubclass(other, self.base_class)
- except TypeError:
- return False
- if other in self.blacklist:
- return False
- return subclass
-
PLUGIN_GRAPH = construct_graph(
this_modname=__name__,
submodnames=[name for name,include in PLUGIN_MODULES] + BUILTIN_MODULES,
--- /dev/null
+"""The `config` module provides :class:`ConfigPlugin` and several
+associated :class:`hooke.command.Command`\s for handling
+:mod:`hooke.config` classes.
+"""
+
+from StringIO import StringIO
+
+from ..command import Command, Argument, Failure
+from ..interaction import ReloadUserInterfaceConfig
+from ..plugin import Builtin
+
+
+class ConfigPlugin (Builtin):
+ def __init__(self):
+ super(ConfigPlugin, self).__init__(name='config')
+
+ def commands(self):
+ return [GetCommand(), SetCommand(), PrintCommand()]
+
+
+# Define common or complicated arguments
+
+SectionArgument = Argument(
+ name='section', type='string', optional=False,
+ help="""
+Configuration section to act on.
+""".strip())
+
+OptionArgument = Argument(
+ name='option', type='string', optional=False,
+ help="""
+Configuration option to act on.
+""".strip())
+
+
+# Define commands
+
+class GetCommand (Command):
+ """Get the current value of a configuration option.
+ """
+ def __init__(self):
+ super(GetCommand, self).__init__(
+ name='get config',
+ arguments=[SectionArgument, OptionArgument],
+ help=self.__doc__)
+
+ def _run(self, hooke, inqueue, outqueue, params):
+ outqueue.put(hooke.config.get(params['section'], params['option']))
+
+class SetCommand (Command):
+ """Set the current value of a configuration option.
+
+ Currently many config options are read at startup time, and config
+ dicts are passed out to their target classes. This means that changes
+ to the central :attr:`hooke.hooke.Hooke.config` location *will not* be
+ noticed by the target classes unless the configuration is reloaded.
+ This reloading may cause problems in poorly written UIs.
+ """
+ def __init__(self):
+ super(SetCommand, self).__init__(
+ name='set config',
+ arguments=[
+ SectionArgument, OptionArgument,
+ Argument(
+ name='value', type='string', optional=False,
+ help='Value to set.'),
+ ],
+ help=self.__doc__)
+
+ def _run(self, hooke, inqueue, outqueue, params):
+ hooke.config.set(params['section'], params['option'], params['value'])
+ # push config changes
+ hooke.load_plugins()
+ hooke.load_drivers()
+ # notify UI to update config
+ outqueue.put(ReloadUserInterfaceConfig(hooke.config))
+
+class PrintCommand (Command):
+ """Get the current value of a configuration option.
+ """
+ def __init__(self):
+ super(PrintCommand, self).__init__(
+ name='print config', help=self.__doc__)
+
+ def _run(self, hooke, inqueue, outqueue, params):
+ out = StringIO()
+ hooke.config.write(out)
+ outqueue.put(out.getvalue())
from .. import version
from ..compat.odict import odict
from ..config import Setting
-from ..plugin import IsSubclass
+from ..util.pluggable import IsSubclass
USER_INTERFACE_MODULES = [
"""Name of the config section which controls UI selection.
"""
+
class QueueMessage (object):
def __str__(self):
return self.__class__.__name__
"""
def __init__(self, name):
self.name = name
- self.setting_section = '%s user interface' % self.name
+ self.setting_section = '%s user interface' % (self.name)
self.config = {}
-
+
def default_settings(self):
"""Return a list of :class:`hooke.config.Setting`\s for any
configurable UI settings.
"""
return []
+ def reload_config(self, config):
+ """Update the user interface for new config settings.
+
+ Should be called with the new `config` upon recipt of
+ `ReloadUserInterfaceConfig` from the `CommandEngine`.
+ """
+ try:
+ self.config = dict(config.items(self.setting_section))
+ except configparser.NoSectionError:
+ self.config = {}
+
def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
return
import shlex
from ..command import CommandExit, Exit, Command, Argument, StoreValue
-from ..interaction import Request, BooleanRequest
+from ..interaction import Request, BooleanRequest, ReloadUserInterfaceConfig
from ..ui import UserInterface, CommandMessage
self.cmd.stdout.write(msg.__class__.__name__+'\n')
self.cmd.stdout.write(str(msg).rstrip()+'\n')
break
+ elif isinstance(msg, ReloadUserInterfaceConfig):
+ self.cmd.ui.reload_config(msg.config)
+ continue
elif isinstance(msg, Request):
self._handle_request(msg)
continue
# Now onto the main attraction.
class HookeCmd (cmd.Cmd):
- def __init__(self, commands, inqueue, outqueue):
+ def __init__(self, ui, commands, inqueue, outqueue):
cmd.Cmd.__init__(self)
+ self.ui = ui
self.commands = commands
self.local_commands = [LocalExitCommand(), LocalHelpCommand()]
self.prompt = 'hooke> '
super(CommandLine, self).__init__(name='command line')
def run(self, commands, ui_to_command_queue, command_to_ui_queue):
- cmd = HookeCmd(commands,
+ cmd = HookeCmd(self, commands,
inqueue=ui_to_command_queue,
outqueue=command_to_ui_queue)
cmd.cmdloop(self._splash_text())
--- /dev/null
+"""`pluggable`
+"""
+
+from ..util.graph import Node, Graph
+
+
+class IsSubclass (object):
+ """A safe subclass comparator.
+
+ Examples
+ --------
+
+ >>> class A (object):
+ ... pass
+ >>> class B (A):
+ ... pass
+ >>> C = 5
+ >>> is_subclass = IsSubclass(A)
+ >>> is_subclass(A)
+ True
+ >>> is_subclass = IsSubclass(A, blacklist=[A])
+ >>> is_subclass(A)
+ False
+ >>> is_subclass(B)
+ True
+ >>> is_subclass(C)
+ False
+ """
+ def __init__(self, base_class, blacklist=None):
+ self.base_class = base_class
+ if blacklist == None:
+ blacklist = []
+ self.blacklist = blacklist
+ def __call__(self, other):
+ try:
+ subclass = issubclass(other, self.base_class)
+ except TypeError:
+ return False
+ if other in self.blacklist:
+ return False
+ return subclass
+
+def construct_graph(this_modname, submodnames, class_selector,
+ assert_name_match=True):
+ """Search the submodules `submodnames` of a module `this_modname`
+ for class objects for which `class_selector(class)` returns
+ `True`. These classes are instantiated, and the `instance.name`
+ is compared to the `submodname` (if `assert_name_match` is
+ `True`).
+
+ The instances are further arranged into a dependency
+ :class:`hooke.util.graph.Graph` according to their
+ `instance.dependencies()` values. The topologically sorted graph
+ is returned.
+ """
+ instances = {}
+ for submodname in submodnames:
+ count = len([s for s in submodnames if s == submodname])
+ assert count > 0, 'No %s entries: %s' % (submodname, submodnames)
+ assert count == 1, 'Multiple (%d) %s entries: %s' \
+ % (count, submodname, submodnames)
+ this_mod = __import__(this_modname, fromlist=[submodname])
+ submod = getattr(this_mod, submodname)
+ for objname in dir(submod):
+ obj = getattr(submod, objname)
+ if class_selector(obj):
+ instance = obj()
+ if assert_name_match == True and instance.name != submodname:
+ raise Exception(
+ 'Instance name %s does not match module name %s'
+ % (instance.name, submodname))
+ instances[instance.name] = instance
+ nodes = {}
+ for i in instances.values(): # make nodes for each instance
+ nodes[i.name] = Node(data=i)
+ for n in nodes.values(): # fill in dependencies for each node
+ n.extend([nodes[name] for name in n.data.dependencies()])
+ graph = Graph(nodes.values())
+ graph.topological_sort()
+ return graph