From c4845a85000b50097f8a6a1688ec34d913fc1bff Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Tue, 18 May 2010 08:54:38 -0400 Subject: [PATCH] Actually, pass plugin instance to Command.__init__. Rather than using Plugin._setup_commands, because the commands may wish to use some aspects of the Plugin during initialization (e.g. to build argument lists from plugin settings). The previous implemetation gave the commands no way to respond to the attached plugin instance. --- hooke/command.py | 4 +- hooke/config.py | 2 +- hooke/plugin/__init__.py | 18 ++++----- hooke/plugin/config.py | 16 ++++---- hooke/plugin/curve.py | 32 +++++++-------- hooke/plugin/cut.py | 7 ++-- hooke/plugin/debug.py | 11 +++--- hooke/plugin/multifit.py | 7 ++-- hooke/plugin/note.py | 15 ++++--- hooke/plugin/playlist.py | 85 ++++++++++++++++++++-------------------- hooke/plugin/system.py | 21 +++++----- 11 files changed, 106 insertions(+), 112 deletions(-) diff --git a/hooke/command.py b/hooke/command.py index c822cc5..978c564 100644 --- a/hooke/command.py +++ b/hooke/command.py @@ -99,7 +99,8 @@ class Command (object): ITEM: """ - def __init__(self, name, aliases=None, arguments=[], help=''): + def __init__(self, name, aliases=None, arguments=[], help='', + plugin=None): # TODO: see_also=[other,command,instances,...] self.name = name if aliases == None: @@ -110,6 +111,7 @@ class Command (object): help='Print a help message.'), ] + arguments self._help = help + self.plugin = None def run(self, hooke, inqueue=None, outqueue=None, **kwargs): """`Normalize inputs and handle before punting diff --git a/hooke/config.py b/hooke/config.py index 10f4d6f..66f0b4c 100644 --- a/hooke/config.py +++ b/hooke/config.py @@ -45,7 +45,7 @@ class Setting (object): def __init__(self, section, option=None, value=None, help=None, wrap=True): self.section = section self.option = option - self.value = value + self.value = str(value) self.help = help self.wrap = wrap diff --git a/hooke/plugin/__init__.py b/hooke/plugin/__init__.py index 2418b69..5a1d43a 100644 --- a/hooke/plugin/__init__.py +++ b/hooke/plugin/__init__.py @@ -31,6 +31,7 @@ from ..util.pluggable import IsSubclass, construct_graph PLUGIN_MODULES = [ # ('autopeak', True), # ('curvetools', True), + ('convfilt', True), ('cut', True), # ('fit', True), # ('flatfilts-rolf', True), @@ -99,17 +100,6 @@ class Plugin (object): """ return [] - def _setup_commands(self): - """Perform internal setup on stored commands. - - Currently: - - * Adds a `plugin` attribute to each command so they can access - the plugin configuration with `.plugin.config`. - """ - for command in self._commands: - command.plugin = self - def commands(self): """Return a list of :class:`hooke.command.Command`\s provided. """ @@ -169,3 +159,9 @@ def load_graph(graph, config, include_section): pass items.append(item) return items + +def setting_to_argument(self, setting): + """Convert a :class:`~hooke.conf.Setting` to an + :class:`~hooke.command.Argument`. + """ + TODO diff --git a/hooke/plugin/config.py b/hooke/plugin/config.py index 7cb4ef5..82ba038 100644 --- a/hooke/plugin/config.py +++ b/hooke/plugin/config.py @@ -31,8 +31,8 @@ from ..plugin import Builtin class ConfigPlugin (Builtin): def __init__(self): super(ConfigPlugin, self).__init__(name='config') - self._commands = [GetCommand(), SetCommand(), PrintCommand()] - self._setup_commands() + self._commands = [GetCommand(self), SetCommand(self), + PrintCommand(self)] # Define common or complicated arguments @@ -55,11 +55,11 @@ Configuration option to act on. class GetCommand (Command): """Get the current value of a configuration option. """ - def __init__(self): + def __init__(self, plugin): super(GetCommand, self).__init__( name='get config', arguments=[SectionArgument, OptionArgument], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): outqueue.put(hooke.config.get(params['section'], params['option'])) @@ -73,7 +73,7 @@ class SetCommand (Command): noticed by the target classes unless the configuration is reloaded. This reloading may cause problems in poorly written UIs. """ - def __init__(self): + def __init__(self, plugin): super(SetCommand, self).__init__( name='set config', arguments=[ @@ -82,7 +82,7 @@ class SetCommand (Command): name='value', type='string', optional=False, help='Value to set.'), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): hooke.config.set(params['section'], params['option'], params['value']) @@ -95,9 +95,9 @@ class SetCommand (Command): class PrintCommand (Command): """Get the current value of a configuration option. """ - def __init__(self): + def __init__(self, plugin): super(PrintCommand, self).__init__( - name='print config', help=self.__doc__) + name='print config', help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): out = StringIO() diff --git a/hooke/plugin/curve.py b/hooke/plugin/curve.py index 27fb0cd..b93ccbc 100644 --- a/hooke/plugin/curve.py +++ b/hooke/plugin/curve.py @@ -36,10 +36,9 @@ class CurvePlugin (Builtin): def __init__(self): super(CurvePlugin, self).__init__(name='curve') self._commands = [ - InfoCommand(), ExportCommand(), - DifferenceCommand(), DerivativeCommand(), - PowerSpectrumCommand()] - self._setup_commands() + InfoCommand(self), ExportCommand(self), + DifferenceCommand(self), DerivativeCommand(self), + PowerSpectrumCommand(self)] # Define common or complicated arguments @@ -66,7 +65,7 @@ of the current playlist. class InfoCommand (Command): """Get selected information about a :class:`hooke.curve.Curve`. """ - def __init__(self): + def __init__(self, plugin): args = [ CurveArgument, Argument(name='all', type='bool', default=False, count=1, @@ -79,7 +78,8 @@ class InfoCommand (Command): name=field, type='bool', default=False, count=1, help='Get curve %s' % field)) super(InfoCommand, self).__init__( - name='curve info', arguments=args, help=self.__doc__) + name='curve info', arguments=args, + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): fields = {} @@ -125,7 +125,7 @@ class ExportCommand (Command): """Export a :class:`hooke.curve.Curve` data block as TAB-delimeted ASCII text. """ - def __init__(self): + def __init__(self, plugin): super(ExportCommand, self).__init__( name='export block', arguments=[ @@ -140,7 +140,7 @@ the approacing curve and `1` selects the retracting curve. File name for the output data. Defaults to 'curve.dat' """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): data = params['curve'].data[params['block']] @@ -155,7 +155,7 @@ class DifferenceCommand (Command): See :func:`hooke.util.calculus.derivative` for implementation details. """ - def __init__(self): + def __init__(self, plugin): super(DifferenceCommand, self).__init__( name='block difference', arguments=[ @@ -178,7 +178,7 @@ Column of data block to differentiate with respect to. Column of data block to differentiate. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): a = params['curve'].data[params['block one']] @@ -192,7 +192,7 @@ Column of data block to differentiate. class DerivativeCommand (Command): """Calculate the difference between two blocks of data. """ - def __init__(self): + def __init__(self, plugin): super(DerivativeCommand, self).__init__( name='block derivative', arguments=[ @@ -216,7 +216,7 @@ Weighting scheme dictionary for finite differencing. Defaults to central differencing. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): data = params['curve'].data[params['block']] @@ -227,7 +227,7 @@ central differencing. class PowerSpectrumCommand (Command): """Calculate the power spectrum of a data block. """ - def __init__(self): + def __init__(self, plugin): super(PowerSpectrumCommand, self).__init__( name='block power spectrum', arguments=[ @@ -249,13 +249,13 @@ Sampling frequency. help=""" Number of samples per chunk. Use a power of two. """.strip()), - Argument(name='overlap', type='bool', default=False, - help=""" + Argument(name='overlap', type='bool', default=False, + help=""" If `True`, each chunk overlaps the previous chunk by half its length. Otherwise, the chunks are end-to-end, and not overlapping. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): data = params['curve'].data[params['block']] diff --git a/hooke/plugin/cut.py b/hooke/plugin/cut.py index 7a2e5ea..2771ef5 100644 --- a/hooke/plugin/cut.py +++ b/hooke/plugin/cut.py @@ -29,8 +29,7 @@ from ..plugin import Plugin class CutPlugin (Plugin): def __init__(self): super(CutPlugin, self).__init__(name='cut') - self._commands = [CutCommand()] - self._setup_commands() + self._commands = [CutCommand(self)] # Define common or complicated arguments @@ -59,7 +58,7 @@ class CutCommand (Command): The data is saved in TAB-delimited ASCII text, where the first column is "x" and the second is "y". There is no header row. """ - def __init__(self): + def __init__(self, plugin): super(CutCommand, self).__init__( name='cut', arguments=[ @@ -78,7 +77,7 @@ Indicies of points bounding the selected data. File name for the output data. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): if params['curve'] == None: diff --git a/hooke/plugin/debug.py b/hooke/plugin/debug.py index cc9101d..a2e8812 100644 --- a/hooke/plugin/debug.py +++ b/hooke/plugin/debug.py @@ -32,17 +32,16 @@ from ..plugin import Builtin class DebugPlugin (Builtin): def __init__(self): super(DebugPlugin, self).__init__(name='debug') - self._commands = [VersionCommand(), DebugCommand()] - self._setup_commands() + self._commands = [VersionCommand(self), DebugCommand(self)] class VersionCommand (Command): """Get the Hooke version, as well as versions for important Python packages. Useful for debugging. """ - def __init__(self): + def __init__(self, plugin): super(VersionCommand, self).__init__( - name='version', help=self.__doc__) + name='version', help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): lines = [ @@ -72,7 +71,7 @@ class VersionCommand (Command): class DebugCommand (Command): """Get Hooke attributes. Useful for debugging. """ - def __init__(self): + def __init__(self, plugin): super(DebugCommand, self).__init__( name='debug', arguments=[ @@ -80,7 +79,7 @@ class DebugCommand (Command): Hooke attribute to print. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): if params['attribute'] == None: diff --git a/hooke/plugin/multifit.py b/hooke/plugin/multifit.py index ee42ea5..56befca 100644 --- a/hooke/plugin/multifit.py +++ b/hooke/plugin/multifit.py @@ -31,8 +31,7 @@ from ..plugin.playlist import PlaylistArgument class MultifitPlugin (Plugin): def __init__(self): super(MultifitPlugin, self).__init__(name='multifit') - self._commands = [MultifitCommand()] - self._setup_commands() + self._commands = [MultifitCommand(self)] class MultifitCommand (Command): @@ -46,7 +45,7 @@ class MultifitCommand (Command): """ #NOTE: centerzero plot modifier should be activated (set centerzero #1). - def __init__(self): + def __init__(self, plugin): super(MultifitCommand, self).__init__( name='multifit', arguments=[ @@ -86,7 +85,7 @@ data between them. Perform the fits on the current curve instead of iterating. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): counter=0 diff --git a/hooke/plugin/note.py b/hooke/plugin/note.py index 722b208..fa20592 100644 --- a/hooke/plugin/note.py +++ b/hooke/plugin/note.py @@ -31,14 +31,13 @@ class NotePlugin (Builtin): def __init__(self): super(NotePlugin, self).__init__(name='note') self._commands = [ - AddNoteCommand(), ClearNoteCommand(), GetNoteCommand()] - self._setup_commands() + AddNoteCommand(self), ClearNoteCommand(self), GetNoteCommand(self)] class AddNoteCommand (Command): """Add a note to one of several Hooke objects. """ - def __init__(self): + def __init__(self, plugin): super(AddNoteCommand, self).__init__( name='add note', arguments=[ @@ -54,7 +53,7 @@ Target object for the note. Defaults to the current playlist. The note text. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['target'].info['note'].append(params['note']) @@ -62,7 +61,7 @@ The note text. class ClearNoteCommand (Command): """Remove a note or notes from one of several Hooke objects. """ - def __init__(self): + def __init__(self, plugin): super(ClearNoteCommand, self).__init__( name='clear note', arguments=[ @@ -82,7 +81,7 @@ Run without prompting the user. Use if you save often or don't make typing mistakes ;). """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): num_notes = len(params['target'].info['note']) @@ -104,7 +103,7 @@ typing mistakes ;). class GetNoteCommand (Command): """Retrieve notes from one of several Hooke objects. """ - def __init__(self): + def __init__(self, plugin): super(GetNoteCommand, self).__init__( name='get note', arguments=[ @@ -115,7 +114,7 @@ class GetNoteCommand (Command): Target object for the note. Defaults to the current playlist. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): outqueue.put(params['target'].info['note']) diff --git a/hooke/plugin/playlist.py b/hooke/plugin/playlist.py index 47975f4..01d24b7 100644 --- a/hooke/plugin/playlist.py +++ b/hooke/plugin/playlist.py @@ -32,12 +32,11 @@ class PlaylistPlugin (Builtin): def __init__(self): super(PlaylistPlugin, self).__init__(name='playlist') self._commands = [ - NextCommand(), PreviousCommand(), JumpCommand(), - IndexCommand(), CurveListCommand(), - SaveCommand(), LoadCommand(), - AddCommand(), AddGlobCommand(), - RemoveCommand(), FilterCommand(), NoteFilterCommand()] - self._setup_commands() + NextCommand(self), PreviousCommand(self), JumpCommand(self), + IndexCommand(self), CurveListCommand(self), + SaveCommand(self), LoadCommand(self), + AddCommand(self), AddGlobCommand(self), + RemoveCommand(self), FilterCommand(self), NoteFilterCommand(self)] # Define common or complicated arguments @@ -75,11 +74,11 @@ def all_drivers_callback(hooke, command, argument, value): class NextCommand (Command): """Move playlist to the next curve. """ - def __init__(self): + def __init__(self, plugin): super(NextCommand, self).__init__( name='next curve', arguments=[PlaylistArgument], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].next() @@ -87,11 +86,11 @@ class NextCommand (Command): class PreviousCommand (Command): """Move playlist to the previous curve. """ - def __init__(self): + def __init__(self, plugin): super(PreviousCommand, self).__init__( name='previous curve', arguments=[PlaylistArgument], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].previous() @@ -99,7 +98,7 @@ class PreviousCommand (Command): class JumpCommand (Command): """Move playlist to a given curve. """ - def __init__(self): + def __init__(self, plugin): super(JumpCommand, self).__init__( name='jump to curve', arguments=[ @@ -108,7 +107,7 @@ class JumpCommand (Command): Index of target curve. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].jump(params['index']) @@ -118,13 +117,13 @@ class IndexCommand (Command): The first curve has index 0. """ - def __init__(self): + def __init__(self, plugin): super(IndexCommand, self).__init__( name='curve index', arguments=[ PlaylistArgument, ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): outqueue.put(params['playlist']._index) @@ -132,13 +131,13 @@ class IndexCommand (Command): class CurveListCommand (Command): """Get the curves in a playlist. """ - def __init__(self): + def __init__(self, plugin): super(CurveListCommand, self).__init__( name='playlist curves', arguments=[ PlaylistArgument, ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): outqueue.put([c for c in params['playlist']]) @@ -146,7 +145,7 @@ class CurveListCommand (Command): class SaveCommand (Command): """Save a playlist. """ - def __init__(self): + def __init__(self, plugin): super(SaveCommand, self).__init__( name='save playlist', arguments=[ @@ -157,7 +156,7 @@ File name for the output playlist. Defaults to overwriting the input playlist. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].save(params['output']) @@ -165,7 +164,7 @@ playlist. class LoadCommand (Command): """Load a playlist. """ - def __init__(self): + def __init__(self, plugin): super(LoadCommand, self).__init__( name='load playlist', arguments=[ @@ -179,7 +178,7 @@ File name for the input playlist. Drivers for loading curves. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): p = FilePlaylist(drivers=params['drivers'], path=params['input']) @@ -190,7 +189,7 @@ Drivers for loading curves. class AddCommand (Command): """Add a curve to a playlist. """ - def __init__(self): + def __init__(self, plugin): super(AddCommand, self).__init__( name='add curve to playlist', arguments=[ @@ -204,7 +203,7 @@ File name for the input :class:`hooke.curve.Curve`. Additional information for the input :class:`hooke.curve.Curve`. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].append_curve_by_path(params['input'], @@ -217,7 +216,7 @@ class AddGlobCommand (Command): command you can use globs (`data/curves/*.dat`) to add curves for all matching files at once. """ - def __init__(self): + def __init__(self, plugin): super(AddGlobCommand, self).__init__( name='glob curves to playlist', arguments=[ @@ -231,7 +230,7 @@ File name glob for the input :class:`hooke.curve.Curve`. Additional information for the input :class:`hooke.curve.Curve`. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): for path in sorted(glob.glob(params['input'])): @@ -240,7 +239,7 @@ Additional information for the input :class:`hooke.curve.Curve`. class RemoveCommand (Command): """Remove a curve from a playlist. """ - def __init__(self): + def __init__(self, plugin): super(RemoveCommand, self).__init__( name='remove curve from playlist', arguments=[ @@ -249,7 +248,7 @@ class RemoveCommand (Command): Index of target curve. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].pop(params['index']) @@ -262,34 +261,36 @@ class FilterCommand (Command): command you can use a function `filter` to select the curves you wish to keep. """ - def __init__(self): + def __init__(self, plugin, name='filter playlist', filter_fn=None): super(FilterCommand, self).__init__( - name='filter playlist', + name=name, arguments=[ PlaylistArgument, PlaylistNameArgument, + ], + help=self.__doc__, plugin=plugin) + self.filter_fn = filter_fn + if filter_fn == None: + self.arguments.append( Argument(name='filter', type='function', optional=False, help=""" Function returning `True` for "good" curves. `filter(curve) -> True/False`. -""".strip()), - ], - help=self.__doc__) +""".strip())) def _run(self, hooke, inqueue, outqueue, params): - p = params['playlist'].filter(params['filter']) + if self.filter_fn == None: + filter_fn = params['filter'] + else: + filter_fn = self.filter_fn + p = params['playlist'].filter(filter_fn) hooke.playlists.add(p) outqueue.put(p) class NoteFilterCommand (FilterCommand): """Create a subset playlist of curves with `.info['note'] != None`. """ - def __init__(self): - super(NoteFilterCommand, self).__init__() - self.name = 'note filter playlist' - self.arguments = [a for a in self.arguments if a.name != 'filter'] - - def _run(self, hooke, inqueue, outqueue, params): - params['filter'] = lambda curve : \ - 'note' in curve.info and curve.info['note'] != None - return super(NoteFilterCommand, self)._run( - hooke, inqueue, outqueue, params) + def __init__(self, plugin): + super(NoteFilterCommand, self).__init__( + plugin, name='note filter playlist', + filter_fn=lambda curve : \ + 'note' in curve.info and curve.info['note'] != None) diff --git a/hooke/plugin/system.py b/hooke/plugin/system.py index 185fa8e..8a09235 100644 --- a/hooke/plugin/system.py +++ b/hooke/plugin/system.py @@ -34,15 +34,14 @@ class SystemPlugin (Builtin): def __init__(self): super(SystemPlugin, self).__init__(name='system') self._commands = [ - ListDirectoryCommand(), GetWorkingDirectoryCommand(), - ChangeDirectoryCommand(), SystemCommand()] - self._setup_commands() + ListDirectoryCommand(self), GetWorkingDirectoryCommand(self), + ChangeDirectoryCommand(self), SystemCommand(self)] class ListDirectoryCommand (Command): """List the files in a directory. """ - def __init__(self): + def __init__(self, plugin): super(ListDirectoryCommand, self).__init__( name='ls', aliases=['dir'], arguments=[ @@ -53,7 +52,7 @@ Path to the directory whose contents get listed. Defaults to the current working directory. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): outqueue.put('\n'.join(sorted(os.listdir(params['path'])))) @@ -61,9 +60,9 @@ current working directory. class GetWorkingDirectoryCommand (Command): """Get the current working directory. """ - def __init__(self): + def __init__(self, plugin): super(GetWorkingDirectoryCommand, self).__init__( - name='cwd', aliases=['pwd'], help=self.__doc__) + name='cwd', aliases=['pwd'], help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): outqueue.put(os.getcwd()) @@ -71,7 +70,7 @@ class GetWorkingDirectoryCommand (Command): class ChangeDirectoryCommand (Command): """Change the current working directory. """ - def __init__(self): + def __init__(self, plugin): super(ChangeDirectoryCommand, self).__init__( name='cd', arguments=[ @@ -82,7 +81,7 @@ Path of the directory to change into. Default to the user's home directory. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): os.chdir(os.path.expanduser(params['path'])) @@ -90,7 +89,7 @@ directory. class SystemCommand (Command): """Execute a system command and report the output. """ - def __init__(self): + def __init__(self, plugin): super(SystemCommand, self).__init__( name='system', arguments=[ @@ -100,7 +99,7 @@ class SystemCommand (Command): Command line to execute. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): p = subprocess.Popen( -- 2.26.2