From 2d4bb65c1668c44e40b10d1c5b20ef62b1592291 Mon Sep 17 00:00:00 2001 From: James Bunton Date: Sun, 2 Jan 2011 20:49:41 +1100 Subject: [PATCH] Unicode fixes, use only safe characters --- libsyncitunes.py | 38 ++++++++++++++++++++++++++++++-------- syncitunes.py | 2 +- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/libsyncitunes.py b/libsyncitunes.py index 3bccfec..9573fe6 100644 --- a/libsyncitunes.py +++ b/libsyncitunes.py @@ -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)) diff --git a/syncitunes.py b/syncitunes.py index 1de4fae..fb9dba0 100755 --- a/syncitunes.py +++ b/syncitunes.py @@ -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 -- 2.39.2