import os.path
import numpy
-from .driver import NotRecognized
+class NotRecognized (ValueError):
+ def __init__(self, curve):
+ msg = 'Not a recognizable curve format: %s' % curve.path
+ ValueError.__init__(self, msg)
+ self.curve = curve
class Data (numpy.ndarray):
"""Stores a single, continuous data set.
Hooke commands could like to know if they're looking at force
clamp data, regardless of their origin.
"""
- def __init__(self, path):
+ def __init__(self, path, info=None):
#the data dictionary contains: {name of data: list of data sets [{[x], [y]}]
self.path = path
self.driver = None
self.data = []
- self.info = None
+ if info == None:
+ info = {}
+ self.info = info
self.name = os.path.basename(path)
- self.notes = ''
def identify(self, drivers):
"""Identify the appropriate :class:`hooke.driver.Driver` for
if driver.is_me(self.path):
self.driver = driver # remember the working driver
return
- raise NotRecognized(self.path)
+ raise NotRecognized(self)
def load(self):
"""Use the driver to read the curve into memory.
default. TODO: autodiscovery
"""
-class NotRecognized (ValueError):
- def __init__(self, path):
- msg = 'Not a recognizable curve format: %s' % self.path
- ValueError.__init__(self, msg)
- self.path = path
class Driver(object):
"""Base class for file format drivers.
default_settings=default_settings)
config.read()
self.config = config
+ self.load_builtins()
self.load_plugins()
self.load_drivers()
+ self.setup_commands()
+
+ def load_builtins(self):
+ self.builtins = []
+ for builtin in plugin_mod.BUILTINS.values():
+ builtin = plugin_mod.BUILTINS[builtin_name]
+ try:
+ builtin.config = dict(
+ self.config.items(builtin.setting_section))
+ except configparser.NoSectionError:
+ pass
+ self.builtins.append(plugin_mod.BUILTINS[builtin_name])
def load_plugins(self):
self.plugins = []
- self.commands = []
for plugin_name,include in self.config.items('plugins'):
if include == 'True':
plugin = plugin_mod.PLUGINS[plugin_name]
except configparser.NoSectionError:
pass
self.plugins.append(plugin_mod.PLUGINS[plugin_name])
- self.commands.extend(plugin.commands())
def load_drivers(self):
self.drivers = []
pass
self.drivers.append(driver_mod.DRIVERS[driver_name])
+ def setup_commands(self):
+ self.commands = []
+ for plugin in self.builtins + self.plugins:
+ self.commands.extend(plugin.commands())
+
def close(self):
if self.config.changed:
self.config.write() # Does not preserve original comments
+ def playlist_status(self, playlist):
+ if playlist.has_curves()
+ return '%s (%s/%s)' % (playlist.name, playlist._index + 1,
+ len(playlist))
+ return 'The playlist %s does not contain any valid force curve data.' \
+ % self.name
+
# def _GetActiveCurveIndex(self):
# playlist = self.GetActivePlaylist()
# #get the selected item from the tree
# if files:
# playlist = Playlist.Playlist(self.drivers)
# for item in files:
-# playlist.add_curve(item)
+# playlist.append_curve_by_path(item)
# if playlist.count > 0:
# playlist.name = self._GetUniquePlaylistName(name)
# playlist.reset()
# def GetActiveCurve(self):
# playlist = self.GetActivePlaylist()
# if playlist is not None:
-# return playlist.get_active_curve()
+# return playlist.active_curve()
# return None
#
# def GetActivePlaylist(self):
# self.plotNotebook.SetSelection(index)
# #if a curve was double-clicked
# item = self.panelPlaylists.PlaylistsTree.GetSelection()
-# #TODO: fix with get_active_curve
+# #TODO: fix with active_curve
# if not self.panelPlaylists.PlaylistsTree.ItemHasChildren(item):
# index = self._GetActiveCurveIndex()
# else:
# #if a curve was clicked
# item = self.panelPlaylists.PlaylistsTree.GetSelection()
# if not self.panelPlaylists.PlaylistsTree.ItemHasChildren(item):
-# #TODO: fix with get_active_curve
+# #TODO: fix with active_curve
# index = self._GetActiveCurveIndex()
# if index >= 0:
# #playlist = self.playlists[playlist_name][0]
# #self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
# playlist = playlist.Playlist(self.drivers)
# for item in files:
-# curve = playlist.add_curve(item)
+# curve = playlist.append_curve_by_path(item)
# plot = copy.deepcopy(curve.plots[0])
# #add the 'raw' data
# curve.add_data('raw', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
# playlist_name = self._GetActivePlaylistName()
# index = self._GetActiveCurveIndex()
# playlist = self.playlists[playlist_name][0]
-# curve = playlist.get_active_curve()
+# curve = playlist.active_curve()
# plot = playlist.get_active_plot()
# figure = self.playlists[playlist_name][1]
#
+++ /dev/null
-import copy
-import os
-import os.path
-import xml.dom.minidom
-
-from . import hooke as hooke
-from . import curve as lhc
-from . import libhooke as lh
-
-class Playlist(object):
- def __init__(self, drivers):
- self._saved = False
- self.count = 0
- self.curves = []
- self.drivers = drivers
- self.path = ''
- self.genericsDict = {}
- self.hiddenAttributes = ['curve', 'driver', 'name', 'plots']
- self.index = -1
- self.name = 'Untitled'
- self.plotPanel = None
- self.plotTab = None
- self.xml = None
-
- def add_curve(self, path, attributes={}):
- curve = lhc.HookeCurve(path)
- for key,value in attribures.items():
- setattr(curve, key, value)
- curve.identify(self.drivers)
- curve.plots = curve.driver.default_plots()
- self.curves.append(curve)
- self._saved = False
- self.count = len(self.curves)
- return curve
-
- def close_curve(self, index):
- if index >= 0 and index < self.count:
- self.curves.remove(index)
-
- def filter_curves(self, keeper_fn=labmda curve:True):
- playlist = copy.deepcopy(self)
- for curve in reversed(playlist.curves):
- if not keeper_fn(curve):
- playlist.curves.remove(curve)
- try: # attempt to maintain the same active curve
- playlist.index = playlist.curves.index(self.get_active_curve())
- except ValueError:
- playlist.index = 0
- playlist._saved = False
- playlist.count = len(playlist.curves)
- return playlist
-
- def get_active_curve(self):
- return self.curves[self.index]
-
- #TODO: do we need this?
- def get_active_plot(self):
- return self.curves[self.index].plots[0]
-
- def get_status_string(self):
- if self.has_curves()
- return '%s (%s/%s)' % (self.name, self.index + 1, self.count)
- return 'The file %s does not contain any valid force curve data.' \
- % self.name
-
- def has_curves(self):
- if self.count > 0:
- return True
- return False
-
- def is_saved(self):
- return self._saved
-
- def load(self, path):
- '''
- loads a playlist file
- '''
- self.path = path
- self.name = os.path.basename(path)
- playlist = lh.delete_empty_lines_from_xmlfile(path)
- self.xml = xml.dom.minidom.parse(path)
- # Strip blank spaces:
- self._removeWhitespaceNodes()
-
- generics_list = self.xml.getElementsByTagName('generics')
- curve_list = self.xml.getElementsByTagName('curve')
- self._loadGenerics(generics_list)
- self._loadCurves(curve_list)
- self._saved = True
-
- def _removeWhitespaceNodes(self, root_node=None):
- if root_node == None:
- root_node = self.xml
- for node in root_node.childNodes:
- if node.nodeType == node.TEXT_NODE and node.data.strip() == '':
- root_node.removeChild(node) # drop this whitespace node
- else:
- _removeWhitespaceNodes(root_node=node) # recurse down a level
-
- def _loadGenerics(self, generics_list, clear=True):
- if clear:
- self.genericsDict = {}
- #populate generics
- generics_list = self.xml.getElementsByTagName('generics')
- for generics in generics_list:
- for attribute in generics.attributes.keys():
- self.genericsDict[attribute] = generics_list[0].getAttribute(attribute)
- if self.genericsDict.has_key('pointer'):
- index = int(self.genericsDict['pointer'])
- if index >= 0 and index < len(self.curves):
- self.index = index
- else:
- index = 0
-
- def _loadCurves(self, curve_list, clear=True):
- if clear:
- self.curves = []
- #populate playlist with curves
- for curve in curve_list:
- #rebuild a data structure from the xml attributes
- curve_path = lh.get_file_path(element.getAttribute('path'))
- #extract attributes for the single curve
- attributes = dict([(k,curve.getAttribute(k))
- for k in curve.attributes.keys()])
- attributes.pop('path')
- curve = self.add_curve(os.path.join(path, curve_path), attributes)
- if curve is not None:
- for plot in curve.plots:
- curve.add_data('raw', plot.vectors[0][0], plot.vectors[0][1], color=plot.colors[0], style='plot')
- curve.add_data('raw', plot.vectors[1][0], plot.vectors[1][1], color=plot.colors[1], style='plot')
-
- def next(self):
- self.index += 1
- if self.index > self.count - 1:
- self.index = 0
-
- def previous(self):
- self.index -= 1
- if self.index < 0:
- self.index = self.count - 1
-
- def reset(self):
- if self.has_curves():
- self.index = 0
- else:
- self.index = None
-
- def save(self, path):
- '''
- saves the playlist in a XML file.
- '''
- try:
- output_file = file(path, 'w')
- except IOError, e:
- #TODO: send message
- print 'Cannot save playlist: %s' % e
- return
- self.xml.writexml(output_file, indent='\n')
- output_file.close()
- self._saved = True
-
- def set_XML(self):
- '''
- Creates an initial playlist from a list of files.
- A playlist is an XML document with the following syntax:
- <?xml version="1.0" encoding="utf-8"?>
- <playlist>
- <generics pointer="0"/>
- <curve path="/my/file/path/"/ attribute="value" ...>
- <curve path="...">
- </playlist>
- Relative paths are interpreted relative to the location of the
- playlist file.
- '''
- #create the output playlist, a simple XML document
- implementation = xml.dom.minidom.getDOMImplementation()
- #create the document DOM object and the root element
- self.xml = implementation.createDocument(None, 'playlist', None)
- root = self.xml.documentElement
-
- #save generics variables
- playlist_generics = self.xml.createElement('generics')
- root.appendChild(playlist_generics)
- self.genericsDict['pointer'] = self.index
- for key in self.genericsDict.keys():
- self.xml.createAttribute(key)
- playlist_generics.setAttribute(key, str(self.genericsDict[key]))
-
- #save curves and their attributes
- for item in self.curves:
- playlist_curve = self.xml.createElement('curve')
- root.appendChild(playlist_curve)
- for key in item.__dict__:
- if not (key in self.hiddenAttributes):
- self.xml.createAttribute(key)
- playlist_curve.setAttribute(key, str(item.__dict__[key]))
- self._saved = False
default. TODO: autodiscovery
"""
+BUILTIN_MODULES = [
+ 'playlist',
+ ]
+"""List of builtin modules. TODO: autodiscovery
+"""
+
+
# Plugins and settings
class Plugin (object):
- """The pluggable collection of Hooke commands.
+ """A pluggable collection of Hooke commands.
Fulfills the same role for Hooke that a software package does for
an operating system.
"""Return a list of :class:`Commands` provided."""
return []
+class Builtin (Plugin):
+ """A required collection of Hooke commands.
+ These "core" plugins provide essential administrative commands
+ (playlist handling, etc.).
+ """
+ pass
# Commands and arguments
"""One-line command description here.
>>> c = Command(name='test', help='An example Command.')
- >>> status = c.run(NullQueue(), PrintQueue(), help=True)
+ >>> status = c.run(NullQueue(), PrintQueue(), help=True) # doctest: +REPORT_UDIFF
ITEM:
Command: test
<BLANKLINE>
Arguments:
- help HELP (bool) Print a help message.
+ help BOOL (bool) Print a help message.
<BLANKLINE>
An example Command.
ITEM:
print 'ITEM:\n%s' % item
-# Construct plugin dependency graph and load default plugins.
+# Construct plugin dependency graph and load plugin instances.
-PLUGINS = {}
-"""(name,instance) :class:`dict` of all possible :class:`Plugin`\s.
-"""
+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`).
-for plugin_modname,default_include in PLUGIN_MODULES:
- assert len([mod_name for mod_name,di in PLUGIN_MODULES]) == 1, \
- 'Multiple %s entries in PLUGIN_MODULES' % mod_name
- this_mod = __import__(__name__, fromlist=[plugin_modname])
- plugin_mod = getattr(this_mod, plugin_modname)
- for objname in dir(plugin_mod):
- obj = getattr(plugin_mod, objname)
+ 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
+ graph = Graph([Node([instances[name] for name in i.dependencies()],
+ data=i)
+ for i in instances.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(obj, Plugin)
+ subclass = issubclass(other, self.base_class)
except TypeError:
- continue
- if subclass == True and obj != Plugin:
- p = obj()
- if p.name != plugin_modname:
- raise Exception('Plugin name %s does not match module name %s'
- % (p.name, plugin_modname))
- PLUGINS[p.name] = p
-
-PLUGIN_GRAPH = Graph([Node([PLUGINS[name] for name in p.dependencies()],
- data=p)
- for p in PLUGINS.values()])
-PLUGIN_GRAPH.topological_sort()
-
+ 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,
+ class_selector=IsSubclass(Plugin, blacklist=[Plugin, Builtin]))
+"""Topologically sorted list of all possible :class:`Plugin`\s and
+:class:`Builtin`\s.
+"""
def default_settings():
settings = [Setting(
'plugins', help='Enable/disable default plugins.')]
for pnode in PLUGIN_GRAPH:
+ if pnode.name in BUILTIN_MODULES:
+ continue # builtin inclusion is not optional
plugin = pnode.data
default_include = [di for mod_name,di in PLUGIN_MODULES
if mod_name == plugin.name][0]
--- /dev/null
+"""Defines :class:`PlaylistPlugin` several associated
+:class:`hooke.plugin.Command`\s.
+"""
+
+import copy
+import hashlib
+import os
+import os.path
+import xml.dom.minidom
+
+
+from .. import curve as curve
+from ..plugin import Plugin, Command, Argument
+
+class PlaylistPlugin (Plugin):
+ def __init__(self):
+ super(PlaylistPlugin, self).__init__(name='playlist')
+
+ def commands(self):
+ return [NextCommand(), PreviousCommand(), JumpCommand(),
+ SaveCommand(), LoadCommand(),
+ AddCommand(), RemoveCommand(), FilterCommand()]
+
+class Playlist (list):
+ """A list of :class:`hooke.curve.Curve`\s.
+
+ Keeps a list of :attr:`drivers` for loading curves, the
+ :attr:`index` (i.e. "bookmark") of the currently active curve, and
+ a :class:`dict` of additional informtion (:attr:`info`).
+ """
+ def __init__(self, drivers, name=None):
+ super(Playlist, self).__init__()
+ self.drivers = drivers
+ self.name = name
+ self.info = {}
+ self._index = 0
+
+ def append_curve_by_path(self, path, info=None, identify=True):
+ if self.path != None:
+ path = os.path.join(self.path, path)
+ path = os.path.normpath(path)
+ c = curve.Curve(path, info=info)
+ if identify == True:
+ c.identify(self.drivers)
+ self.append(c)
+ return c
+
+ def active_curve(self):
+ return self[self._index]
+
+ def has_curves(self):
+ return len(self) > 0
+
+ def jump(self, index):
+ if len(self) == 0:
+ self._index = 0
+ else:
+ self._index = index % len(self)
+
+ def next(self):
+ self.jump(self._index + 1)
+
+ def previous(self):
+ self.jump(self._index - 1)
+
+ def filter(self, keeper_fn=lambda curve:True):
+ playlist = copy.deepcopy(self)
+ for curve in reversed(playlist.curves):
+ if keeper_fn(curve) != True:
+ playlist.curves.remove(curve)
+ try: # attempt to maintain the same active curve
+ playlist._index = playlist.index(self.active_curve())
+ except ValueError:
+ playlist._index = 0
+ return playlist
+
+class FilePlaylist (Playlist):
+ version = '0.1'
+
+ def __init__(self, drivers, name=None, path=None):
+ if name == None and path != None:
+ name = os.path.basename(path)
+ super(FilePlaylist, self).__init__(drivers, name)
+ self.path = path
+ self._digest = None
+
+ def is_saved(self):
+ return self.digest() == self._digest
+
+ def digest(self):
+ r"""Compute the sha1 digest of the flattened playlist
+ representation.
+
+ Examples
+ --------
+
+ >>> root_path = os.path.sep + 'path'
+ >>> p = FilePlaylist(drivers=[],
+ ... path=os.path.join(root_path, 'to','playlist'))
+ >>> p.info['note'] = 'An example playlist'
+ >>> c = curve.Curve(os.path.join(root_path, 'to', 'curve', 'one'))
+ >>> c.info['note'] = 'The first curve'
+ >>> p.append(c)
+ >>> c = curve.Curve(os.path.join(root_path, 'to', 'curve', 'two'))
+ >>> c.info['note'] = 'The second curve'
+ >>> p.append(c)
+ >>> p.digest()
+ "\xa1\x99\x8a\x99\xed\xad\x13'\xa7w\x12\x00\x07Z\xb3\xd0zN\xa2\xe1"
+ """
+ string = self.flatten()
+ return hashlib.sha1(string).digest()
+
+ def flatten(self, absolute_paths=False):
+ """Create a string representation of the playlist.
+
+ A playlist is an XML document with the following syntax::
+
+ <?xml version="1.0" encoding="utf-8"?>
+ <playlist attribute="value">
+ <curve path="/my/file/path/"/ attribute="value" ...>
+ <curve path="...">
+ </playlist>
+
+ Relative paths are interpreted relative to the location of the
+ playlist file.
+
+ Examples
+ --------
+
+ >>> root_path = os.path.sep + 'path'
+ >>> p = FilePlaylist(drivers=[],
+ ... path=os.path.join(root_path, 'to','playlist'))
+ >>> p.info['note'] = 'An example playlist'
+ >>> c = curve.Curve(os.path.join(root_path, 'to', 'curve', 'one'))
+ >>> c.info['note'] = 'The first curve'
+ >>> p.append(c)
+ >>> c = curve.Curve(os.path.join(root_path, 'to', 'curve', 'two'))
+ >>> c.info['note'] = 'The second curve'
+ >>> p.append(c)
+ >>> print p.flatten() # doctest: +NORMALIZE_WHITESPACE +REPORT_UDIFF
+ <?xml version="1.0" encoding="utf-8"?>
+ <playlist index="0" note="An example playlist" version="0.1">
+ <curve note="The first curve" path="../curve/one"/>
+ <curve note="The second curve" path="../curve/two"/>
+ </playlist>
+ <BLANKLINE>
+ >>> print p.flatten(absolute_paths=True) # doctest: +NORMALIZE_WHITESPACE +REPORT_UDIFF
+ <?xml version="1.0" encoding="utf-8"?>
+ <playlist index="0" note="An example playlist" version="0.1">
+ <curve note="The first curve" path="/path/to/curve/one"/>
+ <curve note="The second curve" path="/path/to/curve/two"/>
+ </playlist>
+ <BLANKLINE>
+ """
+ implementation = xml.dom.minidom.getDOMImplementation()
+ # create the document DOM object and the root element
+ doc = implementation.createDocument(None, 'playlist', None)
+ root = doc.documentElement
+ root.setAttribute('version', self.version) # store playlist version
+ root.setAttribute('index', str(self._index))
+ for key,value in self.info.items(): # save info variables
+ root.setAttribute(key, str(value))
+ for curve in self: # save curves and their attributes
+ curve_element = doc.createElement('curve')
+ root.appendChild(curve_element)
+ path = os.path.abspath(os.path.expanduser(curve.path))
+ if absolute_paths == False:
+ path = os.path.relpath(
+ path,
+ os.path.abspath(os.path.expanduser(self.path)))
+ curve_element.setAttribute('path', path)
+ for key,value in curve.info.items():
+ curve_element.setAttribute(key, str(value))
+ string = doc.toprettyxml(encoding='utf-8')
+ root.unlink() # break circular references for garbage collection
+ return string
+
+ def _from_xml_doc(self, doc):
+ """Load a playlist from an :class:`xml.dom.minidom.Document`
+ instance.
+ """
+ root = doc.documentElement
+ for attribute,value in root.attributes.items():
+ if attribute == 'version':
+ assert value == self.version, \
+ 'Cannot read v%s playlist with a v%s reader' \
+ % (value, self.version)
+ elif attribute == 'index':
+ self._index = int(value)
+ else:
+ self.info[attribute] = value
+ for curve_element in doc.getElementsByTagName('curve'):
+ path = curve_element.getAttribute('path')
+ info = dict(curve_element.attributes.items())
+ info.pop('path')
+ self.append_curve_by_path(path, info, identify=False)
+ self.jump(self._index) # ensure valid index
+
+ def from_string(self, string):
+ """Load a playlist from a string.
+
+ Examples
+ --------
+
+ >>> string = '''<?xml version="1.0" encoding="utf-8"?>
+ ... <playlist index="1" note="An example playlist" version="0.1">
+ ... <curve note="The first curve" path="../curve/one"/>
+ ... <curve note="The second curve" path="../curve/two"/>
+ ... </playlist>
+ ... '''
+ >>> p = FilePlaylist(drivers=[],
+ ... path=os.path.join('path', 'to','playlist'))
+ >>> p.from_string(string)
+ >>> p._index
+ 1
+ >>> p.info
+ {u'note': u'An example playlist'}
+ >>> for curve in p:
+ ... print curve.path
+ path/to/curve/one
+ path/to/curve/two
+ """
+ doc = xml.dom.minidom.parseString(string)
+ return self._from_xml_doc(doc)
+
+ def load(self, path=None):
+ """Load a playlist from a file.
+ """
+ if path != None:
+ self.path = path
+ if self.name == None:
+ self.name = os.path.basename(self.path)
+ doc = xml.dom.minidom.parse(path)
+ return self._from_xml_doc(doc)
+
+ def save(self, path):
+ """Saves the playlist in a XML file.
+ """
+ f = file(path, 'w')
+ f.write(self.flatten())
+ f.close()
+
+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()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ params['playlist'].next()
+
+class PreviousCommand (Command):
+ """Move playlist to the previous curve.
+ """
+ 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()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ params['playlist'].previous()
+
+class JumpCommand (Command):
+ """Move playlist to a given curve.
+ """
+ def __init__(self):
+ 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()),
+ Argument(name='index', type='int', optional=False, help="""
+Index of target curve.
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ params['playlist'].jump(params['index'])
+
+class SaveCommand (Command):
+ """Save a playlist.
+ """
+ def __init__(self):
+ 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()),
+ Argument(name='output', type='file',
+ help="""
+File name for the output playlist. Defaults to overwring the input
+playlist.
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ params['playlist'].save(params['output'])
+
+class LoadCommand (Command):
+ """Load a playlist.
+ """
+ def __init__(self):
+ super(LoadCommand, self).__init__(
+ name='load playlist',
+ arguments=[
+ Argument(name='input', type='file', optional=False,
+ help="""
+File name for the input playlist.
+""".strip()),
+ Argument(name='digests', type='digest', optional=False,
+ count=-1,
+ help="""
+Digests for loading curves.
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ p = FilePlaylist(drivers=params['drivers'], path=params['input'])
+ p.load()
+ outqueue.put(p)
+
+class AddCommand (Command):
+ """Add a curve to a playlist.
+ """
+ def __init__(self):
+ 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()),
+ Argument(name='input', type='file', optional=False,
+ help="""
+File name for the input :class:`hooke.curve.Curve`.
+""".strip()),
+ Argument(name='info', type='dict', optional=True,
+ help="""
+Additional information for the input :class:`hooke.curve.Curve`.
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ params['playlist'].append_curve_by_path(params['input'],
+ params['info'])
+
+class RemoveCommand (Command):
+ """Remove a curve from a playlist.
+ """
+ def __init__(self):
+ 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()),
+ Argument(name='index', type='int', optional=False, help="""
+Index of target curve.
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ params['playlist'].pop(params['index'])
+ params['playlist'].jump(params._index)
+
+class FilterCommand (Command):
+ """Create a subset playlist via a selection function.
+ """
+ def __init__(self):
+ 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()),
+ Argument(name='filter', type='function', optional=False,
+ help="""
+Function returning `True` for "good" curves.
+""".strip()),
+ ],
+ help=self.__doc__)
+
+ def _run(inqueue, outqueue, params):
+ p = params['playlist'].filter(params['filter'])
+ outqueue.put(p)
#if files:
#playlist = hookeplaylist.Playlist(self.drivers)
#for item in files:
- #playlist.add_curve(item)
+ #playlist.append_curve_by_path(item)
#if playlist.count > 0:
#playlist_name = name
#count = 1