diff -Nru exiflow-0.4.5.13/PKG-INFO exiflow-0.4.5.14/PKG-INFO --- exiflow-0.4.5.13/PKG-INFO 2013-01-15 23:04:43.000000000 +0000 +++ exiflow-0.4.5.14/PKG-INFO 2013-01-24 22:03:20.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Exiflow -Version: 0.4.5.13 +Version: 0.4.5.14 Summary: A set of tools including a little GUI to provide a complete digital photo workflow for Unixes, using EXIF headers as the central information repository. Home-page: http://exiflow.org/ Author: Ulf Rompe, Sebastian Berthold diff -Nru exiflow-0.4.5.13/debian/changelog exiflow-0.4.5.14/debian/changelog --- exiflow-0.4.5.13/debian/changelog 2013-01-24 22:12:17.000000000 +0000 +++ exiflow-0.4.5.14/debian/changelog 2013-01-24 22:12:18.000000000 +0000 @@ -1,26 +1,32 @@ -exiflow (0.4.5.13-1ppa1~oneiric1) oneiric; urgency=low +exiflow (0.4.5.14-1ppa1~oneiric1) oneiric; urgency=low - * Upload Exiflow 0.4.5.13 for oneiric. + * Upload Exiflow 0.4.5.14 for oneiric. - -- Sebastian Berthold Wed, 16 Jan 2013 00:05:13 +0100 + -- Sebastian Berthold Thu, 24 Jan 2013 23:03:56 +0100 -exiflow (0.4.5.13-1ppa1~natty1) natty; urgency=low +exiflow (0.4.5.14-1ppa1~natty1) natty; urgency=low - * Upload Exiflow 0.4.5.13 for natty. + * Upload Exiflow 0.4.5.14 for natty. - -- Sebastian Berthold Wed, 16 Jan 2013 00:05:03 +0100 + -- Sebastian Berthold Thu, 24 Jan 2013 23:03:45 +0100 -exiflow (0.4.5.13-1ppa1~maverick1) maverick; urgency=low +exiflow (0.4.5.14-1ppa1~maverick1) maverick; urgency=low - * Upload Exiflow 0.4.5.13 for maverick. + * Upload Exiflow 0.4.5.14 for maverick. - -- Sebastian Berthold Wed, 16 Jan 2013 00:04:53 +0100 + -- Sebastian Berthold Thu, 24 Jan 2013 23:03:35 +0100 -exiflow (0.4.5.13-1ppa1~lucid1) lucid; urgency=low +exiflow (0.4.5.14-1ppa1~lucid1) lucid; urgency=low - * Upload Exiflow 0.4.5.13 for lucid. + * Upload Exiflow 0.4.5.14 for lucid. - -- Sebastian Berthold Wed, 16 Jan 2013 00:04:43 +0100 + -- Sebastian Berthold Thu, 24 Jan 2013 23:03:21 +0100 + +exiflow (0.4.5.14-1) precise; urgency=low + + * Release Exiflow 0.4.5.14. + + -- Sebastian Berthold Thu, 24 Jan 2013 23:03:07 +0100 exiflow (0.4.5.13-1) precise; urgency=low diff -Nru exiflow-0.4.5.13/exiflow/configfile.py exiflow-0.4.5.14/exiflow/configfile.py --- exiflow-0.4.5.13/exiflow/configfile.py 2013-01-15 22:59:54.000000000 +0000 +++ exiflow-0.4.5.14/exiflow/configfile.py 2013-01-24 19:26:09.000000000 +0000 @@ -61,6 +61,8 @@ # Configure global values in the [all] section and camera specific values # in a section for the camera model. It is also possible to create sections # with arbitrary names and supply these names later on the command line. +# All supported tags of ExifTool are allowed as keys - so it's possible to set +# or unset (just use "keyword =") specific tags with exiperson. #[all] #Artist = Arthur Dent @@ -77,6 +79,10 @@ #[NIKON Dxx] #artist = I. R. Baboon + +#[GT-I9100] +#ImageUniqueID = + """} # ConfigParser Caches diff -Nru exiflow-0.4.5.13/exiflow/exigui.glade exiflow-0.4.5.14/exiflow/exigui.glade --- exiflow-0.4.5.13/exiflow/exigui.glade 2013-01-15 23:03:09.000000000 +0000 +++ exiflow-0.4.5.14/exiflow/exigui.glade 2013-01-24 22:00:51.000000000 +0000 @@ -1073,7 +1073,7 @@ True GDK_WINDOW_TYPE_HINT_NORMAL ExiFlow - 0.4.5.13 + 0.4.5.14 © Copyright 2006-2013. Some rights reserved. This is a beta version. Use at your own risk. http://exiflow.org/ diff -Nru exiflow-0.4.5.13/exiflow/exigui.py exiflow-0.4.5.14/exiflow/exigui.py --- exiflow-0.4.5.13/exiflow/exigui.py 2013-01-15 22:59:54.000000000 +0000 +++ exiflow-0.4.5.14/exiflow/exigui.py 2013-01-24 19:26:09.000000000 +0000 @@ -4,13 +4,15 @@ """ A nice PyGTK GUI for the exiflow tool collection. """ -__revision__ = "$Id: exigui.py 379 2013-01-09 01:30:51Z sleif $" +__revision__ = "$Id: exigui.py 392 2013-01-23 00:52:36Z sleif $" import os import sys import logging import optparse import pygtk +import shutil +import tempfile pygtk.require("2.0") import gtk import gtk.glade @@ -150,6 +152,7 @@ logging.basicConfig(format="%(module)s: %(message)s", stream=stdlog, level=logging.INFO) self.batch_scripts = [] + self.batch_tmpdir = "" self.window.connect("map_event", self.batch_run) def _make_sensitive(self, name): @@ -161,7 +164,7 @@ self.wtree.get_widget(name).set_sensitive(False) def _is_active(self, name): - """ Retrun True if widget "name" is activated, False otherwise. """ + """ Return True if widget "name" is activated, False otherwise. """ return self.wtree.get_widget(name).get_active() def set_active(self, name): @@ -404,6 +407,26 @@ nbook.set_current_page(tabs.index(script)) self.on_run_activate(run_button) self.batch_scripts = [] + if self.batch_tmpdir: + self.set_text("exiimport_targetdir_entry", self.batch_target) + for subdir in os.listdir(self.batch_tmpdir): + target_subdir = subdir + while os.path.exists(os.path.join(self.batch_target, target_subdir)): + logger.warning("%s already exists!", + os.path.join(self.batch_target, target_subdir)) + target_subdir += "+" + logger.info("Moving %s into target directory %s", + subdir, os.path.join(self.batch_target, target_subdir)) + try: + shutil.move(os.path.join(self.batch_tmpdir, subdir), + os.path.join(self.batch_target, target_subdir)) + except shutil.Error, msg: + logger.error("ERROR: %s", msg) + for rownum in range(0, len(self.liststore)): + self.liststore[rownum][0] = self.liststore[rownum][0].\ + replace(os.path.join(self.batch_tmpdir, subdir),\ + os.path.join(self.batch_target, target_subdir)) + return 0 @@ -421,9 +444,6 @@ " in this directory.") parser.add_option("-d", "--device", dest="device", help="(Ignored for backwards compatibility. Don't use.)") - parser.add_option("-b", "--batch", action="store_true", dest="batch", - help="Autorun from exiimport over exirename, exiperson " - "and exiconvert to exiassign.") parser.add_option("--cam_id", "-c", dest="cam_id", help="ID string for the camera model. Should normally be" " three characters long.") @@ -434,9 +454,17 @@ help="Create filenames containing the image time, for" " example 20071231-235959-n001234-xy000.jpg instead" " of 20071231-n001234-xy000.jpg .") + parser.add_option("-b", "--batch", action="store_true", dest="batch", + help="Autorun from exiimport over exirename, exiperson " + "and exiconvert to exiassign.") parser.add_option("--batch_order", help="Comma separated processing order for --batch. " "Default: %default") + parser.add_option("--batch_tmpdir", + help="If the processing order starts with 'exiimport', " + "this temporary directory is used for batch processing. " + "After batch processing, the created subdirectory will " + "be moved into the target directory.") parser.add_option("--nofork", action="store_true", help="Do not fork, stay in foreground instead.") options, args = parser.parse_args(argv) @@ -460,6 +488,15 @@ win1.set_filelist(args) if options.batch: win1.batch_scripts = options.batch_order.split(',') + if options.batch_tmpdir and "exiimport" in win1.batch_scripts: + if not options.mount or not options.target: + print( "Wrong syntax. Missing --mount or --target\n" + + parser.format_help()) + win1.batch_scripts = [] + win1.batch_tmpdir = tempfile.mkdtemp(dir=options.batch_tmpdir) + win1.batch_target = options.target + win1.set_text("exiimport_targetdir_entry", win1.batch_tmpdir) + gtk.main() return 0 diff -Nru exiflow-0.4.5.13/exiflow/exiimport.py exiflow-0.4.5.14/exiflow/exiimport.py --- exiflow-0.4.5.13/exiflow/exiimport.py 2013-01-15 22:59:54.000000000 +0000 +++ exiflow-0.4.5.14/exiflow/exiimport.py 2013-01-24 19:26:09.000000000 +0000 @@ -5,7 +5,7 @@ Import files from given directories to your photo folder. Optionally unmounts source media after successfull import. """ -__revision__ = "$Id: exiimport.py 359 2012-07-16 20:53:52Z rompe $" +__revision__ = "$Id: exiimport.py 390 2013-01-22 22:17:39Z rompe $" import os import sys @@ -42,9 +42,7 @@ logging.getLogger().setLevel(logging.INFO) logger = logging.getLogger("exiimport") if len(args) > 0 or not options.mount or not options.target: - logger.error("Wrong syntax.") - logger.warning(parser.format_help()) - sys.exit(1) + return "Wrong syntax.\n" + parser.format_help() # Build file list whithout skipping unknown files filelist = exiflow_filelist.Filelist([]) @@ -53,8 +51,7 @@ # Cry if we found no images if filelist.get_filecount() == 0: - logger.error("No files to import, sorry.") - sys.exit(1) + return "No files to import, sorry." # Create targetdir targetdir = os.path.join(options.target, filelist.get_daterange()) @@ -92,4 +89,4 @@ if __name__ == "__main__": - run(sys.argv[1:]) + sys.exit(run(sys.argv[1:])) diff -Nru exiflow-0.4.5.13/exiflow/exiperson.py exiflow-0.4.5.14/exiflow/exiperson.py --- exiflow-0.4.5.13/exiflow/exiperson.py 2013-01-15 22:59:54.000000000 +0000 +++ exiflow-0.4.5.14/exiflow/exiperson.py 2013-01-24 19:26:09.000000000 +0000 @@ -11,7 +11,7 @@ Exiftool documentation for information about possible names. """ -__revision__ = "$Id: exiperson.py 375 2012-12-13 21:50:24Z sleif $" +__revision__ = "$Id: exiperson.py 391 2013-01-23 00:50:45Z sleif $" import sys import logging @@ -80,6 +80,8 @@ parser = optparse.OptionParser(usage="usage: %prog [options] " "[-- -TAGNAME=VALUE [...]] " "") + parser.description = ("Hint: %prog is able to set or unset any tags supported in " + "ExifTool with -TAGNAME=[VALUE] syntax.") parser.add_option("--section", "-s", dest="section", help="Name of a config file section to be read. This is" " useful if different people are using the same" diff -Nru exiflow-0.4.5.13/setup.py exiflow-0.4.5.14/setup.py --- exiflow-0.4.5.13/setup.py 2013-01-15 23:01:33.000000000 +0000 +++ exiflow-0.4.5.14/setup.py 2013-01-24 22:00:22.000000000 +0000 @@ -10,7 +10,7 @@ setup(name='Exiflow', install_requires=["glade2"], - version='0.4.5.13', + version='0.4.5.14', packages=['exiflow'], scripts=["exiassign", "exiconvert", "exigate", "exigui", "exiimport", "exiperson", "exirename"], diff -Nru exiflow-0.4.5.13/tests/test_exiimport.py exiflow-0.4.5.14/tests/test_exiimport.py --- exiflow-0.4.5.13/tests/test_exiimport.py 1970-01-01 00:00:00.000000000 +0000 +++ exiflow-0.4.5.14/tests/test_exiimport.py 2013-01-24 19:26:09.000000000 +0000 @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim: tabstop=4 expandtab shiftwidth=4 +""" +Unit tests for exiimport.py +""" +__revision__ = "$Id: test_exiimport.py 390 2013-01-22 22:17:39Z rompe $" + + +import shutil +import os +import sys +import tempfile +import time +import unittest + +import NikonD70 +sys.path.append(os.path.dirname(sys.path[0])) +import exiflow.configfile +import exiflow.exiimport + + +class TestImport(unittest.TestCase): + """ Tests for exiimport.py """ + + def setUp(self): + """ Create a directory with an image. """ + self.__data_dir = os.path.join(os.path.dirname(__file__), "testdata") + self.__sourcedir = tempfile.mkdtemp() + self.__targetdir = tempfile.mkdtemp() + self.__configdir = tempfile.mkdtemp() + exiflow.configfile.global_config_dir = self.__configdir + exiflow.configfile.local_config_dir = self.__configdir + + def tearDown(self): + """ Clean up. """ + shutil.rmtree(self.__configdir) + shutil.rmtree(self.__sourcedir) + shutil.rmtree(self.__targetdir) + + def test_run(self): + """ Test run(). """ + shutil.copyfile(os.path.join(self.__data_dir, "NikonD70.jpg"), + os.path.join(self.__sourcedir, "DSC0001.jpg")) + shutil.copyfile(os.path.join(self.__data_dir, "NikonD70.jpg"), + os.path.join(self.__sourcedir, "DSC0002.jpg")) + exiflow.exiimport.run(argv=["--mount", self.__sourcedir, + "--target", self.__targetdir, + "--verbose"]) + self.assertEqual(os.listdir(self.__sourcedir), + os.listdir(os.path.join(self.__targetdir, + os.listdir(self.__targetdir)[0]))) + # Run twice and check if another directory have been created. + exiflow.exiimport.run(argv=["--mount", self.__sourcedir, + "--target", self.__targetdir]) + self.assertEqual(len(os.listdir(self.__targetdir)), 2) + + def test_run__syntax_error(self): + """ Test run() with wrong syntax. """ + result = exiflow.exiimport.run(argv=["--target", self.__targetdir, + "bla"]) + self.assertTrue(result) + + def test_run__no_files(self): + """ Test run() with empty source dir. """ + result = exiflow.exiimport.run(argv=["--mount", self.__sourcedir, + "--target", self.__targetdir]) + self.assertTrue(result) + + def test_run__callback(self): + """ Test run() with a callback function. """ + mylist = [] + + def callback(*dummy_args, **dummy_kwargs): + """ Just set callback_called to True. """ + mylist.append(True) + return True + + shutil.copyfile(os.path.join(self.__data_dir, "NikonD70.jpg"), + os.path.join(self.__sourcedir, "DSC0001.jpg")) + exiflow.exiimport.run(argv=["--mount", self.__sourcedir, + "--target", self.__targetdir, + "--verbose"], callback=callback) + self.assertEqual(mylist, [True]) +