X-Git-Url: http://git.tremily.us/?p=hooke.git;a=blobdiff_plain;f=hooke%2Fhooke.py;h=1942ac9d32c1e9fa2c065d934a7a0b267eea8c0e;hp=c2ef159d8bccc4bbbfe5ac5b789ad52ae55132f1;hb=a72a0929928e2cfdbf2ace492e6e6dd9fd07c2f2;hpb=b3c8903707dc971342df2adb59b136f0e2f41330 diff --git a/hooke/hooke.py b/hooke/hooke.py index c2ef159..1942ac9 100644 --- a/hooke/hooke.py +++ b/hooke/hooke.py @@ -54,6 +54,7 @@ if False: # Queue pickle error debugging code feed(buffer, notempty, s, writelock, close) multiprocessing.queues.Queue._feed = staticmethod(new_feed) +from ConfigParser import NoSectionError import logging import logging.config import multiprocessing @@ -64,12 +65,13 @@ import unittest import StringIO import sys -from . import engine as engine +from . import version +from . import engine from . import config as config_mod -from . import playlist as playlist +from . import playlist from . import plugin as plugin_mod from . import driver as driver_mod -from . import ui as ui +from . import ui class Hooke (object): @@ -89,8 +91,8 @@ class Hooke (object): self.load_plugins() self.load_drivers() self.load_ui() - self.command = engine.CommandEngine() - self.playlists = playlist.NoteIndexList() + self.engine = engine.CommandEngine() + self.playlists = playlist.Playlists() def load_log(self): config_file = StringIO.StringIO() @@ -99,23 +101,62 @@ class Hooke (object): # Don't attach the logger because it contains an unpicklable # thread.lock. Instead, grab it directly every time you need it. #self.log = logging.getLogger('hooke') + log = logging.getLogger('hooke') + log.debug('config paths: %s' % self.config._config_paths) def load_plugins(self): self.plugins = plugin_mod.load_graph( plugin_mod.PLUGIN_GRAPH, self.config, include_section='plugins') + self.configure_plugins() self.commands = [] for plugin in self.plugins: self.commands.extend(plugin.commands()) + self.command_by_name = dict( + [(c.name, c) for c in self.commands]) def load_drivers(self): self.drivers = plugin_mod.load_graph( driver_mod.DRIVER_GRAPH, self.config, include_section='drivers') + self.configure_drivers() def load_ui(self): self.ui = ui.load_ui(self.config) + self.configure_ui() + + def configure_plugins(self): + for plugin in self.plugins: + self._configure_item(plugin) + + def configure_drivers(self): + for driver in self.drivers: + self._configure_item(driver) + + def configure_ui(self): + self._configure_item(self.ui) + + def _configure_item(self, item): + conditions = self.config.items('conditions') + try: + item.config = dict(self.config.items(item.setting_section)) + except NoSectionError: + item.config = {} + for key,value in conditions: + if key not in item.config: + item.config[key] = value + + def close(self, save_config=False): + if save_config == True: + self.config.write() # Does not preserve original comments + + def run_command(self, command, arguments): + """Run the command named `command` with `arguments` using + :meth:`~hooke.engine.CommandEngine.run_command`. + + Allows for running commands without spawning another process + as in :class:`HookeRunner`. + """ + self.engine.run_command(self, command, arguments) - def close(self): - self.config.write() # Does not preserve original comments class HookeRunner (object): def run(self, hooke): @@ -152,25 +193,32 @@ class HookeRunner (object): command_to_ui = multiprocessing.Queue() manager = multiprocessing.Manager() command = multiprocessing.Process(name='command engine', - target=hooke.command.run, args=(hooke, ui_to_command, command_to_ui)) + target=hooke.engine.run, args=(hooke, ui_to_command, command_to_ui)) command.start() + hooke.engine = None # no more need for the UI-side version. return (ui_to_command, command_to_ui, command) def _cleanup_run(self, ui_to_command, command_to_ui, command): log = logging.getLogger('hooke') log.debug('cleanup sending CloseEngine') - ui_to_command.put(ui.CloseEngine()) + ui_to_command.put(engine.CloseEngine()) hooke = None while not isinstance(hooke, Hooke): log.debug('cleanup waiting for Hooke instance from the engine.') hooke = command_to_ui.get(block=True) log.debug('cleanup got %s instance' % type(hooke)) command.join() + for playlist in hooke.playlists: # Curve._hooke is not pickled. + for curve in playlist: + curve.set_hooke(hooke) return hooke def main(): p = optparse.OptionParser() + p.add_option( + '--version', dest='version', default=False, action='store_true', + help="Print Hooke's version information and exit.") p.add_option( '-s', '--script', dest='script', metavar='FILE', help='Script of command line Hooke commands to run.') @@ -178,28 +226,60 @@ def main(): '-c', '--command', dest='commands', metavar='COMMAND', action='append', default=[], help='Add a command line Hooke command to run.') + p.add_option( + '-p', '--persist', dest='persist', action='store_true', default=False, + help="Don't exit after running a script or commands.") + p.add_option( + '-u', '--ui', dest='user_interface', + help="Override the configured user interface (for easy switching).") + p.add_option( + '--config', dest='config', metavar='FILE', + help="Override the default config file chain.") + p.add_option( + '--save-config', dest='save_config', + action='store_true', default=False, + help="Automatically save a changed configuration on exit.") + p.add_option( + '--debug', dest='debug', action='store_true', default=False, + help="Enable debug logging.") options,arguments = p.parse_args() if len(arguments) > 0: print >> sys.stderr, 'More than 0 arguments to %s: %s' \ % (sys.argv[0], arguments) p.print_help(sys.stderr) sys.exit(1) + if options.config != None: + config_mod.DEFAULT_PATHS = [ + os.path.abspath(os.path.expanduser(options.config))] hooke = Hooke(debug=__debug__) runner = HookeRunner() + if options.version == True: + print version() + sys.exit(0) + if options.debug == True: + hooke.config.set( + section='handler_hand1', option='level', value='NOTSET') + hooke.load_log() + if options.user_interface not in [None, hooke.ui.name]: + hooke.config.set( + ui.USER_INTERFACE_SETTING_SECTION, hooke.ui.name, False) + hooke.config.set( + ui.USER_INTERFACE_SETTING_SECTION, options.user_interface, True) + hooke.load_ui() if options.script != None: - f = open(os.path.expanduser(options.script), 'r') - options.commands.extend(f.readlines()) - f.close + with open(os.path.expanduser(options.script), 'r') as f: + options.commands.extend(f.readlines()) if len(options.commands) > 0: try: hooke = runner.run_lines(hooke, options.commands) finally: - hooke.close() - sys.exit(0) + if options.persist == False: + hooke.close(save_config=options.save_config) + sys.exit(0) try: hooke = runner.run(hooke) finally: - hooke.close() + hooke.close(save_config=options.save_config)