Let commandline registration group image versions
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 25 Jul 2007 19:33:48 +0000 (21:33 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 25 Jul 2007 19:33:48 +0000 (21:33 +0200)
src/packages/kofoto/clientutils.py
src/packages/kofoto/commandline/main.py
src/test/test_all.py
src/test/test_clientutils.py [new file with mode: 0755]

index 6a7d21e..a2b0e61 100644 (file)
@@ -15,6 +15,7 @@ __all__ = [
 
 import locale
 import os
+import re
 import sys
 
 ######################################################################
@@ -48,6 +49,45 @@ def get_file_encoding(f):
     else:
         return locale.getpreferredencoding()
 
+def group_image_versions(paths):
+    original_extensions = [
+        ".cr2", ".crw", ".dcr", ".k25", ".kdc", ".mos", ".mrw", ".nef", ".orf",
+        ".pef", ".raf", ".raw", ".srf"]
+    def order_extension(ext):
+        try:
+            return original_extensions.index(ext.lower())
+        except ValueError:
+            # Not a known original extension. Sort it after originals.
+            return len(original_extensions)
+
+    def compare_paths(path1, path2):
+        (root1, ext1) = os.path.splitext(path1)
+        (root2, ext2) = os.path.splitext(path2)
+        extcmp = cmp(order_extension(ext1), order_extension(ext2))
+        if extcmp != 0:
+            return extcmp
+        # The extensions are equal. Sort shorter paths before longer,
+        # since originals probably have shorter names.
+        lencmp = cmp(len(root1), len(root2))
+        if lencmp != 0:
+            return lencmp
+        return cmp(root1, root2)
+
+    pat = re.compile(r"(\w+)", re.UNICODE)
+    bins = {}
+    for path in paths:
+        (head, tail) = os.path.split(path)
+        m = pat.match(tail)
+        if m:
+            key = os.path.join(head, m.group(1))
+        else:
+            key = path
+        bins.setdefault(key, []).append(path)
+    for key in sorted(bins):
+        vpaths = bins[key]
+        vpaths.sort(cmp=compare_paths)
+        yield vpaths
+
 def walk_files(paths, directories_to_ignore=None):
     """Traverse paths and return filename while ignoring some directories.
 
index 779c32a..ef81607 100755 (executable)
@@ -16,6 +16,7 @@ from kofoto.clientutils import \
     DIRECTORIES_TO_IGNORE, \
     expanduser, \
     get_file_encoding, \
+    group_image_versions, \
     walk_files
 from kofoto.albumtype import AlbumType
 from kofoto.config import DEFAULT_CONFIGFILE_LOCATION
@@ -884,6 +885,7 @@ def registerHelper(env, destalbum, registrationTimeString, paths):
     """Helper function for cmdRegister."""
     paths.sort()
     newchildren = []
+    filepaths = []
     for path in paths:
         if env.verbose:
             env.out("Processing %s ...\n" % path)
@@ -910,22 +912,36 @@ def registerHelper(env, destalbum, registrationTimeString, paths):
                 registrationTimeString,
                 [os.path.join(path, x) for x in os.listdir(path)])
         elif os.path.isfile(path):
-            image = env.shelf.createImage()
+            filepaths.append(path)
+        else:
+            env.err("No such file or directory (ignored): %s\n" % path)
+    for vpaths in group_image_versions(filepaths):
+        image = env.shelf.createImage()
+        validVersions = 0
+        for (i, vpath) in enumerate(vpaths):
+            if i == 0:
+                versiontype = ImageVersionType.Original
+            else:
+                versiontype = ImageVersionType.Other
             try:
-                env.shelf.createImageVersion(
-                    image, path, ImageVersionType.Original)
+                env.shelf.createImageVersion(image, vpath, versiontype)
                 image.setAttribute(u"registered", registrationTimeString)
-                newchildren.append(image)
                 if env.verbose:
-                    env.out("Registered image: %s\n" % path)
+                    if i == 0:
+                        tstr = "original image"
+                    else:
+                        tstr = "version of above original"
+                    env.out("Registered %s: %s\n" % (tstr, vpath))
             except NotAnImageFileError, x:
-                env.out("Ignoring non-image file: %s\n" % path)
-                env.shelf.deleteImage(image.getId())
+                env.out("Ignoring non-image file: %s\n" % vpath)
             except ImageVersionExistsError, x:
-                env.err("Ignoring already registered image version: %s\n" % path)
-                env.shelf.deleteImage(image.getId())
+                env.err("Ignoring already registered image: %s\n" % vpath)
+            else:
+                validVersions += 1
+        if validVersions > 0:
+            newchildren.append(image)
         else:
-            env.err("No such file or directory (ignored): %s\n" % path)
+            env.shelf.deleteImage(image.getId())
     addHelper(env, destalbum, newchildren)
 
 
index d10ed1d..e0e12b8 100755 (executable)
@@ -4,7 +4,7 @@ import os
 import sys
 import unittest
 
-tests = ["dag", "iodict", "searching", "shelf"]
+tests = ["dag", "clientutils", "iodict", "searching", "shelf"]
 
 cwd = os.getcwd()
 libdir = unicode(os.path.realpath(
diff --git a/src/test/test_clientutils.py b/src/test/test_clientutils.py
new file mode 100755 (executable)
index 0000000..7c5a9d4
--- /dev/null
@@ -0,0 +1,45 @@
+#! /usr/bin/env python
+
+import os
+import sys
+import unittest
+
+if __name__ == "__main__":
+    cwd = os.getcwd()
+    libdir = unicode(os.path.realpath(
+        os.path.join(os.path.dirname(sys.argv[0]), "..", "packages")))
+    os.chdir(libdir)
+    sys.path.insert(0, libdir)
+
+from kofoto.clientutils import group_image_versions
+
+
+class TestClientUtils(unittest.TestCase):
+    def test_group_image_versions(self):
+        transforms = [
+            # Different bases.
+            (["/foo/bar.jpg", "/foo/bar2.jpg"],
+             [["/foo/bar.jpg"], ["/foo/bar2.jpg"]]),
+            # Different directories.
+            (["/foo/bar.jpg", "/foo2/bar.cr2"],
+             [["/foo/bar.jpg"], ["/foo2/bar.cr2"]]),
+            # Sort known original first.
+            (["/foo/bar.jpg", "/foo/bar.cr2"],
+             [["/foo/bar.cr2", "/foo/bar.jpg"]]),
+            # Handle uppercase extensions.
+            (["/foo/bar.JPG", "/foo/bar.CR2"],
+             [["/foo/bar.CR2", "/foo/bar.JPG"]]),
+            # Sort shorter filenames first.
+            (["/foo/bar-test.jpg", "/foo/bar.jpg", "/foo/bar-fix.jpg"],
+             [["/foo/bar.jpg", "/foo/bar-fix.jpg", "/foo/bar-test.jpg"]]),
+            # Sort filenames with equal lengths conventionally.
+            (["/foo/bar-test2.jpg", "/foo/bar.jpg", "/foo/bar-test1.jpg"],
+             [["/foo/bar.jpg", "/foo/bar-test1.jpg", "/foo/bar-test2.jpg"]]),
+            ]
+        for (paths, expected) in transforms:
+            actual = list(group_image_versions(paths))
+            self.assertEqual(actual, expected)
+
+
+if __name__ == "__main__":
+    unittest.main()