From 349450dff9d3eb5a020bf4a8e29e4e4658274e60 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 10 May 2010 12:43:05 -0400 Subject: [PATCH] Pass Hooke instance to CommandEngine.run(), not UserInterface.run(). User interface just needs its configuration (already setup in Hooke.load_ui() -> ui.load_ui(self.config) ) and a read-only list of commands. Giving the Hooke instance to CommandEngine allows the commands to work on the Hooke instance directly. This makes user interfaces less intelligent (i.e. easier to write), and more consistent (because they all depend on the same commands engine.) --- hooke/command.py | 12 +-- hooke/engine.py | 4 +- hooke/hooke.py | 7 +- hooke/hooke_cli.py | 160 --------------------------------------- hooke/plugin/cut.py | 9 ++- hooke/plugin/playlist.py | 95 ++++++++++++----------- hooke/ui/commandline.py | 6 +- 7 files changed, 69 insertions(+), 224 deletions(-) diff --git a/hooke/command.py b/hooke/command.py index adb3818..c044c06 100644 --- a/hooke/command.py +++ b/hooke/command.py @@ -52,7 +52,7 @@ class Command (object): ] + arguments self._help = help - def run(self, inqueue=None, outqueue=None, **kwargs): + def run(self, hooke, inqueue=None, outqueue=None, **kwargs): """`Normalize inputs and handle before punting to :meth:`_run`. """ @@ -61,11 +61,11 @@ class Command (object): if outqueue == None: outqueue = NullQueue() try: - params = self.handle_arguments(inqueue, outqueue, kwargs) + params = self.handle_arguments(hooke, inqueue, outqueue, kwargs) if params['help'] == True: outqueue.put(self.help()) raise(Success()) - self._run(inqueue, outqueue, params) + self._run(hooke, inqueue, outqueue, params) except CommandExit, e: if isinstance(e, Failure): outqueue.put(str(e)) @@ -84,7 +84,7 @@ class Command (object): """ pass - def handle_arguments(self, inqueue, outqueue, params): + def handle_arguments(self, hooke, inqueue, outqueue, params): """Normalize and validate input parameters (:class:`Argument` values). """ for argument in self.arguments: @@ -108,7 +108,7 @@ class Command (object): params[argument.name] = value if argument.callback != None: if num_provided > 0: - value = argument.callback(self, argument, value) + value = argument.callback(hooke, self, argument, value) params[argument.name] = value argument.validate(value) return params @@ -180,7 +180,7 @@ class Argument (object): class StoreValue (object): def __init__(self, value): self.value = value - def __call__(self, command, argument, fragment=None): + def __call__(self, hooke, command, argument, fragment=None): return self.value class NullQueue (queue.Queue): diff --git a/hooke/engine.py b/hooke/engine.py index a03a2a4..c70ee6b 100644 --- a/hooke/engine.py +++ b/hooke/engine.py @@ -5,7 +5,7 @@ from .ui import CloseEngine, CommandMessage class CommandEngine (object): - def run(self, ui_to_command_queue, command_to_ui_queue): + def run(self, hooke, ui_to_command_queue, command_to_ui_queue): """Get a :class:`hooke.ui.QueueMessage` from the incoming `ui_to_command_queue` and act accordingly. @@ -24,5 +24,5 @@ class CommandEngine (object): if isinstance(msg, CloseEngine): break assert isinstance(msg, CommandMessage), type(msg) - msg.command.run(ui_to_command_queue, command_to_ui_queue, + msg.command.run(hooke, ui_to_command_queue, command_to_ui_queue, **msg.arguments) diff --git a/hooke/hooke.py b/hooke/hooke.py index 0b05aff..4142a5f 100644 --- a/hooke/hooke.py +++ b/hooke/hooke.py @@ -12,6 +12,7 @@ import multiprocessing from . import engine as engine from . import config as config_mod +from . import playlist as playlist from . import plugin as plugin_mod from . import driver as driver_mod from . import ui as ui @@ -34,6 +35,8 @@ class Hooke (object): self.load_ui() self.command = engine.CommandEngine() + self.playlists = playlist.PlaylistManager() + def load_plugins(self): self.plugins = plugin_mod.load_graph( plugin_mod.PLUGIN_GRAPH, self.config, include_section='plugins') @@ -61,10 +64,10 @@ class Hooke (object): ui_to_command = multiprocessing.Queue() command_to_ui = multiprocessing.Queue() command = multiprocessing.Process( - target=self.command.run, args=(ui_to_command, command_to_ui)) + target=self.command.run, args=(self, ui_to_command, command_to_ui)) command.start() try: - self.ui.run(self, ui_to_command, command_to_ui) + self.ui.run(self.commands, ui_to_command, command_to_ui) finally: ui_to_command.put(ui.CloseEngine()) command.join() diff --git a/hooke/hooke_cli.py b/hooke/hooke_cli.py index 2bd9628..bbb6cc6 100644 --- a/hooke/hooke_cli.py +++ b/hooke/hooke_cli.py @@ -206,166 +206,6 @@ Syntax: set [variable] [value] self.config[key]=value self.do_plot(0) -#PLAYLIST MANAGEMENT AND NAVIGATION -#------------------------------------ - - def help_loadlist(self): - print ''' -LOADLIST -Loads a file playlist ------------ -Syntax: loadlist [playlist file] - ''' - def do_loadlist(self, args): - #checking for args: if nothing is given as input, we warn and exit. - while len(args)==0: - args=linp.safeinput('File to load?') - - arglist=args.split() - play_to_load=arglist[0] - - #We assume a Hooke playlist has the extension .hkp - if play_to_load[-4:] != '.hkp': - play_to_load+='.hkp' - - try: - playxml=PlaylistXML() - self.current_list, self.playlist_generics=playxml.load(play_to_load) - self.current_playxml=playxml - except IOError: - print 'File not found.', play_to_load - return - - print 'Loaded %s curves from %s' \ - % (len(self.current_list), play_to_load) - - if 'pointer' in self.playlist_generics.keys(): - self.pointer=int(self.playlist_generics['pointer']) - else: - #if no pointer is found, set the current curve as the first curve of the loaded playlist - self.pointer=0 - print 'Starting at curve ',self.pointer - - self.current=self.current_list[self.pointer] - - #resets saved/notes saved state - self.playlist_saved=0 - self.playlist_name='' - self.notes_saved=0 - - self.do_plot(0) - - - def help_genlist(self): - print ''' -GENLIST -Generates a file playlist. -Note it doesn't *save* it: see savelist for this. - -If [input files] is a directory, it will use all files in the directory for playlist. -So: -genlist dir -genlist dir/ -genlist dir/*.* - -are all equivalent syntax. ------------- -Syntax: genlist [input files] - -''' - def do_genlist(self,args): - #args list is: input path, output name - if len(args)==0: - args=linp.safeinput('Input files?') - - arglist=args.split() - list_path=arglist[0] - - #if it's a directory, is like /directory/*.* - #FIXME: probably a bit kludgy. - if os.path.isdir(list_path): - if platform.system == 'Windows': - SLASH="\\" - else: - SLASH="/" - if list_path[-1] == SLASH: - list_path=list_path+'*' - else: - list_path=list_path+SLASH+'*' - - #expanding correctly the input list with the glob module :) - list_files=glob.glob(list_path) - list_files.sort() - - self.current_list=[] - for item in list_files: - try: - if os.path.isfile(item): - self.current_list.append(lhc.HookeCurve(os.path.abspath(item))) - except: - pass - - self.pointer=0 - if len(self.current_list)>0: - self.current=self.current_list[self.pointer] - else: - print 'Empty list!' - return - - #resets saved/notes saved state - self.playlist_saved=0 - self.playlist_name='' - self.notes_saved=0 - - self.do_plot(0) - - - def do_savelist(self,args): - ''' - SAVELIST - Saves the current file playlist on disk. - ------------ - Syntax: savelist [filename] - ''' - while len(args)==0: - args=linp.safeinput('Output file?',['savedlist.txt']) - - output_filename=args - - self.playlist_generics['pointer']=self.pointer - - #autocomplete filename if not specified - if output_filename[-4:] != '.hkp': - output_filename+='.hkp' - - playxml=PlaylistXML() - playxml.export(self.current_list, self.playlist_generics) - playxml.save(output_filename) - - #remembers we have saved playlist - self.playlist_saved=1 - - def help_addtolist(self): - print ''' -ADDTOLIST -Adds a file to the current playlist --------------- -Syntax: addtolist [filename] -''' - def do_addtolist(self,args): - #args list is: input path - if len(args)==0: - print 'You must give the input filename you want to add' - self.help_addtolist() - return - - filenames=glob.glob(args) - - for filename in filenames: - self.current_list.append(lhc.HookeCurve(os.path.abspath(filename))) - #we need to save playlist - self.playlist_saved=0 - def help_printlist(self): print ''' PRINTLIST diff --git a/hooke/plugin/cut.py b/hooke/plugin/cut.py index e93367b..dc55d89 100644 --- a/hooke/plugin/cut.py +++ b/hooke/plugin/cut.py @@ -22,8 +22,8 @@ class CutCommand (Command): super(CutCommand, self).__init__( name='cut', arguments=[ - Argument(name='curve', type='curve', optional=False, help=""" -:class:`hooke.curve.Curve` to cut from. + Argument(name='curve', type='curve', help=""" +:class:`hooke.curve.Curve` to cut from. Defaults to the current curve. """.strip()), Argument(name='block', aliases=['set'], type='int', default=0, help=""" @@ -41,7 +41,10 @@ File name for the output data. ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): + if params['curve'] == None: + params['curve'] = hooke.playlists.current().current() + i_min = min([p.index for p in params['points']]) i_max = max([p.index for p in params['points']]) diff --git a/hooke/plugin/playlist.py b/hooke/plugin/playlist.py index 04116b7..8d0559c 100644 --- a/hooke/plugin/playlist.py +++ b/hooke/plugin/playlist.py @@ -20,21 +20,40 @@ class PlaylistPlugin (Builtin): AddCommand(), AddGlobCommand(), RemoveCommand(), FilterCommand()] +# Define common or complicated arguments + +def current_playlist_callback(hooke, command, argument, value): + return hooke.playlists.current() + +PlaylistArgument = Argument( + name='playlist', type='playlist', callback=current_playlist_callback, + help=""" +:class:`hooke.plugin.playlist.Playlist` to act on. Defaults to the +current playlist. +""".strip()), + +def playlist_name_callback(hooke, command, argument, value): + return hooke.playlists.free_name() + +PlaylistNameArgument = Argument( + name='name', type='string', optional=True, callback=playlist_name_callback, + help=""" +Name of the new playlist (defaults to an auto-generated name). +""".strip()) + + +# Define commands + class NextCommand (Command): """Move playlist to the next curve. """ def __init__(self): super(NextCommand, self).__init__( name='next curve', - arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), - ], + arguments=[PlaylistArgument], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): params['playlist'].next() class PreviousCommand (Command): @@ -43,15 +62,10 @@ class PreviousCommand (Command): def __init__(self): super(PreviousCommand, self).__init__( name='previous curve', - arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), - ], + arguments=[PlaylistArgument], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): params['playlist'].previous() class JumpCommand (Command): @@ -61,17 +75,14 @@ class JumpCommand (Command): super(JumpCommand, self).__init__( name='jump to curve', arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), + PlaylistArgument, Argument(name='index', type='int', optional=False, help=""" Index of target curve. """.strip()), ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): params['playlist'].jump(params['index']) class SaveCommand (Command): @@ -81,19 +92,16 @@ class SaveCommand (Command): super(SaveCommand, self).__init__( name='save playlist', arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), + PlaylistArgument, Argument(name='output', type='file', help=""" -File name for the output playlist. Defaults to overwring the input +File name for the output playlist. Defaults to overwriting the input playlist. """.strip()), ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): params['playlist'].save(params['output']) class LoadCommand (Command): @@ -107,17 +115,18 @@ class LoadCommand (Command): help=""" File name for the input playlist. """.strip()), - Argument(name='digests', type='digest', optional=False, + Argument(name='drivers', type='driver', optional=False, count=-1, help=""" -Digests for loading curves. +Drivers for loading curves. """.strip()), ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): p = FilePlaylist(drivers=params['drivers'], path=params['input']) p.load() + hooke.playlists.append(p) outqueue.put(p) class AddCommand (Command): @@ -127,10 +136,7 @@ class AddCommand (Command): super(AddCommand, self).__init__( name='add curve to playlist', arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), + PlaylistArgument, Argument(name='input', type='file', optional=False, help=""" File name for the input :class:`hooke.curve.Curve`. @@ -142,7 +148,7 @@ Additional information for the input :class:`hooke.curve.Curve`. ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): params['playlist'].append_curve_by_path(params['input'], params['info']) @@ -157,10 +163,7 @@ class AddGlobCommand (Command): super(AddGlobCommand, self).__init__( name='glob curves to playlist', arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), + PlaylistArgument, Argument(name='input', type='glob', optional=False, help=""" File name glob for the input :class:`hooke.curve.Curve`. @@ -172,7 +175,7 @@ Additional information for the input :class:`hooke.curve.Curve`. ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): for path in sorted(glob.glob(params['input'])): params['playlist'].append_curve_by_path(path, params['info']) @@ -183,17 +186,14 @@ class RemoveCommand (Command): super(RemoveCommand, self).__init__( name='remove curve from playlist', arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), + PlaylistArgument, Argument(name='index', type='int', optional=False, help=""" Index of target curve. """.strip()), ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): params['playlist'].pop(params['index']) params['playlist'].jump(params._index) @@ -208,10 +208,8 @@ class FilterCommand (Command): super(FilterCommand, self).__init__( name='filter playlist', arguments=[ - Argument(name='playlist', type='playlist', optional=False, - help=""" -:class:`hooke.plugin.playlist.Playlist` to act on. -""".strip()), + PlaylistArgument, + PlaylistNameArgument, Argument(name='filter', type='function', optional=False, help=""" Function returning `True` for "good" curves. `filter(curve) -> True/False`. @@ -219,6 +217,7 @@ Function returning `True` for "good" curves. `filter(curve) -> True/False`. ], help=self.__doc__) - def _run(self, inqueue, outqueue, params): + def _run(self, hooke, inqueue, outqueue, params): p = params['playlist'].filter(params['filter']) + hooke.playlists.add(p) outqueue.put(p) diff --git a/hooke/ui/commandline.py b/hooke/ui/commandline.py index c9ed605..41fe990 100644 --- a/hooke/ui/commandline.py +++ b/hooke/ui/commandline.py @@ -98,9 +98,9 @@ class CompleteCommand (CommandMethod): # Now onto the main attraction. class HookeCmd (cmd.Cmd): - def __init__(self, hooke, inqueue, outqueue): + def __init__(self, commands, inqueue, outqueue): cmd.Cmd.__init__(self) - self.hooke = hooke + self.commands = commands self.prompt = 'hooke> ' self._add_command_methods() self.inqueue = inqueue @@ -110,7 +110,7 @@ class HookeCmd (cmd.Cmd): return name.lower().replace(' ', '_') def _add_command_methods(self): - for command in self.hooke.commands: + for command in self.commands: command.name = self._safe_name(command.name) command.aliases = [self._safe_name(n) for n in command.aliases] for name in [command.name] + command.aliases: -- 2.26.2