]> code.delx.au - notipod/commitdiff
Unicode fixes, use only safe characters
authorJames Bunton <jamesbunton@fastmail.fm>
Sun, 2 Jan 2011 09:49:41 +0000 (20:49 +1100)
committerJames Bunton <jamesbunton@fastmail.fm>
Sun, 2 Jan 2011 09:49:41 +0000 (20:49 +1100)
libsyncitunes.py
syncitunes.py

index 3bccfec30a9bbe1e4a00d279028ca6a9bddbb02e..9573fe6fc7dc93b70c36e5b46a952d6491a94531 100644 (file)
@@ -5,6 +5,7 @@
 import logging
 import os
 import shutil
+import sys
 import urllib
 
 from Foundation import *
@@ -67,13 +68,12 @@ class ITunesLibrary(NSObject):
                        trackID = item["Track ID"]
                        filename = str(pl_tracks[str(trackID)]["Location"])
                        filename = self.loc2name(filename)
-                       filename = eval(repr(filename).lstrip("u")).decode("utf-8")
+                       filename = filename.decode("utf-8")
+###                    filename = eval(repr(filename).lstrip("u")).decode("utf-8")
                        if not filename.startswith(self.folder):
                                logging.warn("Skipping: " + filename)
                                continue
-                       filename = filename[len(self.folder):]
-                       if filename.startswith("/"):
-                               filename = filename[1:]
+                       filename = strip_prefix(filename, self.folder)
                        tracks.append(filename)
                playlist = Playlist.alloc().init()
                playlist.set(name, pid, tracks, parent)
@@ -117,6 +117,23 @@ class ITunesLibrary(NSObject):
                return item.name
 
 
+encoded_names = {}
+valid_chars = frozenset("\\/-_.() abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
+def encode_filename(filename):
+       try:
+               return encoded_names[filename]
+       except KeyError:
+               pass
+       orig_filename = filename
+       filename = filename.encode("ascii", "ignore")
+       filename = "".join(c for c in filename if c in valid_chars)
+       if filename in encoded_names:
+               a, b = os.path.splitext(filename)
+               a += "-dup"
+               filename = a + b
+       encoded_names[orig_filename] = filename
+       return filename
+
 def export_m3u(dry_run, dest, path_prefix, playlist_name, files):
        if dry_run:
                return
@@ -126,7 +143,7 @@ def export_m3u(dry_run, dest, path_prefix, playlist_name, files):
        for filename in files:
                if path_prefix.find("\\") > 0:
                        filename = filename.replace("/", "\\")
-               filename = filename.encode("utf-8")
+               filename = encode_filename(filename)
                f.write("%s%s\n" % (path_prefix, filename))
        f.close()
 
@@ -154,13 +171,18 @@ def sync(dry_run, source, dest, files):
        join = os.path.join
 
        logging.info("Calculating files to sync and deleting old files")
-       files = set(files)
+       source = source.encode("utf-8")
+       dest = dest.encode("utf-8")
+       filemap = {}
+       for f in files:
+               filemap[encode_filename(f)] = f.encode("utf-8")
+       files = set(filemap.keys())
        for dirpath, dirnames, filenames in os.walk(dest):
                full_dirpath = dirpath
                dirpath = strip_prefix(dirpath, dest)
 
                for filename in filenames:
-                       filename = join(dirpath, filename).decode("utf-8")
+                       filename = join(dirpath, filename)
 
                        # Whenever 'file' is deleted OSX will helpfully remove '._file'
                        if not os.path.exists(join(dest, filename)):
@@ -195,6 +217,6 @@ def sync(dry_run, source, dest, files):
                logging.debug("copy: " + filename)
                if not dry_run:
                        mkdirhier(os.path.dirname(join(dest, filename)))
-                       shutil.copy2(join(source, filename), join(dest, filename))
+                       shutil.copy2(join(source, filemap[filename]), join(dest, filename))
 
 
index 1de4faea89bc101d8e10b31e5c79631c558361f5..fb9dba0eb20a265998a3eb9e2d392f440209f9e9 100755 (executable)
@@ -30,7 +30,7 @@ def parse_options():
        if len(args) < 2:
                parser.print_usage()
                sys.exit(1)
-       opts.dest = args[0]
+       opts.dest = args[0].decode("utf-8")
        opts.playlists = args[1:]
 
        return opts