Allow flattening of path-less playlists for command.
[hooke.git] / hooke / playlist.py
index dfec6d72c28c65b3888f6b4d5265b43fee523d73..f8199d4a5a44429044b690cbfd4ff50b6695f7af 100644 (file)
 
 import copy
 import hashlib
+import os
 import os.path
 import types
 import xml.dom.minidom
 
 from . import curve as curve
 from .compat import minidom as minidom  # dynamically patch xml.sax.minidom
+from .util.itertools import reverse_enumerate
 
 
 class NoteIndexList (list):
@@ -94,14 +96,14 @@ class NoteIndexList (list):
         Updates :attr:`_index` during the iteration so
         :func:`~hooke.plugin.curve.current_curve_callback` works as
         expected in :class:`~hooke.command.Command`\s called from
-        :class:`~hooke.plugin.playlist.ApplyCommandStack`.  After the
+        :class:`~hooke.plugin.playlist.ApplyCommand`.  After the
         iteration completes, :attr:`_index` is restored to its
         original value.
         """
         index = self._index
         items = self
         if reverse == True:
-            items = reversed(enumerate(self))
+            items = reverse_enumerate(self)
         else:
             items = enumerate(self)
         for i,item in items:
@@ -157,6 +159,8 @@ class Playlist (NoteIndexList):
 
 
 class FilePlaylist (Playlist):
+    """A file-backed :class:`Playlist`.
+    """
     version = '0.1'
 
     def __init__(self, drivers, name=None, path=None):
@@ -240,7 +244,7 @@ class FilePlaylist (Playlist):
 
         Relative paths are interpreted relative to the location of the
         playlist file.
-        
+
         Examples
         --------
 
@@ -281,6 +285,11 @@ class FilePlaylist (Playlist):
                 or not isinstance(value, types.StringTypes)):
                 continue
             root.setAttribute(self._clean_key(key), str(value))
+        if self.path == None:
+            base_path = os.getcwd()
+        else:
+            base_path = os.path.abspath(
+                os.path.expanduser(self.path))
         for curve in self: # save curves and their attributes
             curve_element = doc.createElement('curve')
             root.appendChild(curve_element)
@@ -288,9 +297,7 @@ class FilePlaylist (Playlist):
             if absolute_paths == False:
                 path = os.path.relpath(
                     path,
-                    os.path.dirname(
-                        os.path.abspath(
-                            os.path.expanduser(self.path))))
+                    os.path.dirname(base_path))
             curve_element.setAttribute('path', path)
             for key,value in curve.info.items():
                 if (key in self._ignored_keys
@@ -362,11 +369,14 @@ class FilePlaylist (Playlist):
         self._digest = self.digest()
         for curve in self:
             curve.set_hooke(hooke)
-        
-    def save(self, path=None):
+
+    def save(self, path=None, makedirs=True):
         """Saves the playlist in a XML file.
         """
         self.set_path(path)
+        dirname = os.path.dirname(self.path) or '.'
+        if makedirs == True and not os.path.isdir(dirname):
+            os.makedirs(dirname)
         with open(self.path, 'w') as f:
             f.write(self.flatten())
             self._digest = self.digest()