# HG changeset patch # User Robert Bruce Park # Date 1356743810 28800 # Node ID 5263a3c99f573934faea40c3b288bd26a593fab5 # Parent 5a2ee7d95f6dc7d2e4535ce9a5d586a6bb9aa2dd Port from pyexiv2 to GExiv2. This removes the obsolete and unmaintained pyexiv2 library, and is a necessary prerequisite to any future Python 3 porting effort that you may wish to undertake. diff -r 5a2ee7d95f6d -r 5263a3c99f57 devscripts/copy-metadata --- a/devscripts/copy-metadata Fri Nov 02 17:25:29 2012 +0100 +++ b/devscripts/copy-metadata Fri Dec 28 17:16:50 2012 -0800 @@ -23,33 +23,31 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..')) -from lazygal import pyexiv2api as pyexiv2 +from gi.repository import GExiv2 def copy_metadata(src, dst): - source_image = pyexiv2.ImageMetadata(src) - source_image.read() - dest_image = pyexiv2.ImageMetadata(dst) - dest_image.read() + source_image = GExiv2.Metadata(src) + dest_image = GExiv2.Metadata(dst) # Save dimensions - if 'Exif.Photo.PixelXDimension' in dest_image.exif_keys\ - and 'Exif.Photo.PixelYDimension' in dest_image.exif_keys: + if 'Exif.Photo.PixelXDimension' in dest_image \ + and 'Exif.Photo.PixelYDimension' in dest_image: dst_width = dest_image["Exif.Photo.PixelXDimension"] dst_height = dest_image["Exif.Photo.PixelYDimension"] has_dims = True else: has_dims = False - source_image.copy(dest_image) + for tag in source_image.get_exif_tags(): + dest_image[tag] = source_image[tag] if has_dims: # set EXIF image size info to resized size dest_image["Exif.Photo.PixelXDimension"] = dst_width dest_image["Exif.Photo.PixelYDimension"] = dst_height - dest_image.comment = source_image.comment - dest_image.write() + dest_image.save_file() if __name__ == "__main__": diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygal-setcomment.py --- a/lazygal-setcomment.py Fri Nov 02 17:25:29 2012 +0100 +++ b/lazygal-setcomment.py Fri Dec 28 17:16:50 2012 -0800 @@ -2,15 +2,14 @@ import sys -from lazygal import pyexiv2api as pyexiv2 +from gi.repository import GExiv2 fn = sys.argv[1] comment = sys.argv[2] -im = pyexiv2.ImageMetadata(fn.decode(sys.getfilesystemencoding())) -im.read() +im = GExiv2.Metadata(fn.decode(sys.getfilesystemencoding())) # Assume comment is in utf-8, more encoding processing example using # sys.stdin.encoding and example processing in lazygal/metadata.py im['Exif.Photo.UserComment'] = comment -im.write() +im.save_file() diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygal/genmedia.py --- a/lazygal/genmedia.py Fri Nov 02 17:25:29 2012 +0100 +++ b/lazygal/genmedia.py Fri Dec 28 17:16:50 2012 -0800 @@ -28,7 +28,7 @@ import genfile import eyecandy import mediautils -from lazygal import pyexiv2api as pyexiv2 +from gi.repository import GExiv2 THUMB_SIZE_NAME = 'thumb' @@ -179,20 +179,19 @@ ) def copy_metadata(self): - imgtags = pyexiv2.ImageMetadata(self.source_media.path) - imgtags.read() - dest_imgtags = pyexiv2.ImageMetadata(self.path) - dest_imgtags.read() - imgtags.copy(dest_imgtags) + imgtags = GExiv2.Metadata(self.source_media.path) + dest_imgtags = GExiv2.Metadata(self.path) + for tag in imgtags.get_exif_tags(): + dest_imgtags[tag] = imgtags[tag] new_size = self.get_size() - dest_imgtags['Exif.Photo.PixelXDimension'] = new_size[0] - dest_imgtags['Exif.Photo.PixelYDimension'] = new_size[1] + dest_imgtags['Exif.Photo.PixelXDimension'] = str(new_size[0]) + dest_imgtags['Exif.Photo.PixelYDimension'] = str(new_size[1]) if self.get_rotation() != 0: # Smaller image has been rotated in order to be displayed correctly # in a web browser. Fix orientation tag accordingly. - dest_imgtags['Exif.Image.Orientation'] = 1 + dest_imgtags['Exif.Image.Orientation'] = '1' # Those are removed from published pics due to pivacy concerns, # unless explicitly told to keep them in. Option to retain GPS @@ -200,12 +199,12 @@ if not self.webgal.keep_gps: for tag in self.PRIVATE_IMAGE_TAGS: try: - del dest_imgtags[tag] + dest_imgtags.clear_tag(tag) except KeyError: pass try: - dest_imgtags.write() - except ValueError, e: + dest_imgtags.save_file() + except Exception, e: logging.error(_("Could not copy metadata in reduced picture: %s") % e) def save(self, im): diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygal/metadata.py --- a/lazygal/metadata.py Fri Nov 02 17:25:29 2012 +0100 +++ b/lazygal/metadata.py Fri Dec 28 17:16:50 2012 -0800 @@ -15,15 +15,18 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +from __future__ import division + import os import locale import logging import codecs import datetime -from lazygal import pyexiv2api as pyexiv2 +from gi.repository import GExiv2 from lazygal import make +from fractions import Fraction FILE_METADATA_ENCODING = locale.getpreferredencoding() @@ -38,6 +41,21 @@ FILE_METADATA = ('album-name', 'album-description', 'album-picture', ) FILE_METADATA_MEDIA_SUFFIX = '.comment' +# As per http://www.exiv2.org/tags.html +VENDOR_EXIF_CODES = ( + 'Exif.Canon.LensModel', + 'Exif.Minolta.LensID', + 'Exif.Nikon3.Lens', + 'Exif.Nikon3.LensType', + 'Exif.OlympusEq.LensModel', + 'Exif.OlympusEq.LensType', + 'Exif.Panasonic.LensType', + 'Exif.Pentax.LensType', + 'Exif.Samsung2.LensType', + 'Exif.Sigma.LensRange', + 'Exif.Sony1.LensID', + ) + class FileMetadata(object): @@ -69,16 +87,7 @@ def __init__(self, image_path): self.image_path = image_path - self._metadata = pyexiv2.ImageMetadata(self.image_path) - self._metadata.read() - - def get_tag_value(self, name): - if name.startswith('Iptc.'): - # Iptc tags are always lists, so, for now, return the first - # element. - return self._metadata[name].values[0] - else: - return self._metadata[name].value + self._metadata = GExiv2.Metadata(self.image_path) def get_date(self): """ @@ -86,27 +95,11 @@ as those were filled by camera, Image DateTime can be update by software when editing photos later. """ - for date_tag in ('Exif.Photo.DateTimeDigitized', - 'Exif.Photo.DateTimeOriginal', - 'Exif.Image.DateTime', - ): - try: - date = self.get_tag_value(date_tag) - if type(date) is not datetime.datetime: - # Sometimes, pyexiv2 sends a string. It seems to happen on - # malformed tags. - raise ValueError - except (IndexError, ValueError, KeyError): - pass - else: - return date - - # No date could be found in the picture metadata - return None + return self._metadata.get_date_time() def get_required_rotation(self): try: - orientation_code = self.get_tag_value('Exif.Image.Orientation') + orientation_code = int(self._metadata['Exif.Image.Orientation']) if orientation_code == 8: return 90 elif orientation_code == 3: @@ -125,13 +118,13 @@ vendors put different information to both tags. """ try: - model = self.get_tag_value('Exif.Image.Model').strip() + model = self._metadata['Exif.Image.Model'].strip() # Terminate string at \x00 pos = model.find('\x00') if pos != -1: model = model[:14] try: - vendor = self.get_tag_value('Exif.Image.Make').strip() + vendor = self._metadata['Exif.Image.Make'].strip() vendor_l = vendor.lower() model_l = model.lower() # Split vendor to words and check whether they are @@ -142,7 +135,7 @@ for word in vendor_l.split(' '): if model_l.find(word) != -1: return model - return '%s %s' % (vendor, model) + return ' '.join([vendor, model]) except KeyError: return model except KeyError: @@ -151,33 +144,17 @@ def get_lens_name(self): """ Return name of used lenses. This usually makes sense only for - SLR cameras and uses various maker notes. Currently supported - for Pentax, Nikon and Minolta (as soon as Exiv2 supports others, - support can be added here. + SLR cameras and uses various maker notes. """ - - try: - return self._metadata['Exif.Pentax.LensType'].human_value.strip() - except (IndexError, ValueError, KeyError): - try: - ret = self._metadata['Exif.Nikon3.Lens'].human_value.strip() - try: - ret2 = self._metadata['Exif.Nikon3.LensType'].human_value.strip() - except (IndexError, ValueError, KeyError): - return ret - else: - return '%s %s' % (ret, ret2) - except (IndexError, ValueError, KeyError): - try: - return self._metadata['Exif.Minolta.LensID'].human_value.strip() - except (IndexError, ValueError, KeyError): - return '' + interpret = self._metadata.get_tag_interpreted_string + vendor_values = [interpret(v) for v in VENDOR_EXIF_CODES] + return ' '.join([s.strip() for s in vendor_values if s]) def get_exif_string(self, name): """ Reads string from EXIF information. """ - return str(self.get_tag_value(name)).strip(' ') + return self._metadata[name].strip(' ') def get_exif_float(self, name): """ @@ -192,13 +169,8 @@ Reads float number from EXIF information (where it is stored as fraction or int). """ - val = self.get_tag_value(name) - if type(val) == int: - return float(val) - elif type(val) == tuple: - return float(val[0]) / float(val[1]) - else: - return float(val.numerator) / float(val.denominator) + val = self._metadata.get_exif_tag_rational(name) + return val.numerator / val.denominator def _fallback_to_encoding(self, encoded_string, encoding='utf-8'): if type(encoded_string) is unicode: return encoded_string @@ -208,7 +180,7 @@ return encoded_string.decode(encoding, 'replace') def get_exif_usercomment(self): - ret = self.get_tag_value('Exif.Photo.UserComment').strip(' \0\x00') + ret = self._metadata['Exif.Photo.UserComment'].strip(' \0\x00') if ret == 'User comments': return '' return ret @@ -227,11 +199,11 @@ raise ValueError except (ValueError, KeyError): try: - ret = self.get_exif_string('Exif.Image.ImageDescription') + ret = self._metadata['Exif.Image.ImageDescription'] ret = self._fallback_to_encoding(ret) except (ValueError, KeyError): try: - ret = self.get_exif_string('Iptc.Application2.ObjectName') + ret = self._metadata['Iptc.Application2.ObjectName'] ret = self._fallback_to_encoding(ret) except (ValueError, KeyError): ret = self.get_jpeg_comment() @@ -239,50 +211,41 @@ def get_flash(self): try: - return self._metadata['Exif.Photo.Flash'].human_value + return self._metadata.get_tag_interpreted_string('Exif.Photo.Flash') except KeyError: return '' def get_exposure(self): try: - exposure = self.get_tag_value('Exif.Photo.ExposureTime') - if type(exposure) == tuple: - if exposure[1] == 1: - return "%d s" % exposure[0] - else: - return "%d/%d s" % (exposure[0], exposure[1]) - else: - if exposure.denominator == 1: - return "%d s" % exposure.numerator - else: - return "%d/%d s" % (exposure.numerator, exposure.denominator) + return str( + self._metadata.get_exif_tag_rational('Exif.Photo.ExposureTime')) except (ValueError, KeyError): return '' def get_iso(self): try: - return self.get_exif_string('Exif.Photo.ISOSpeedRatings') + return self._metadata['Exif.Photo.ISOSpeedRatings'] except KeyError: return '' def get_fnumber(self): try: - val = self.get_exif_float('Exif.Photo.FNumber') - except KeyError: + val = float(self._metadata.get_exif_tag_rational('Exif.Photo.FNumber')) + except (KeyError, TypeError): return '' else: - return 'f/%s' % val + return 'f/{}'.format(val) def get_focal_length(self): try: - flen = self.get_exif_float('Exif.Photo.FocalLength') + flen = self._metadata.get_exif_tag_rational('Exif.Photo.FocalLength') except KeyError: return '' else: flen = '%s mm' % flen try: - flen35 = self.get_exif_float('Exif.Photo.FocalLengthIn35mmFilm') + flen35 = self._metadata.get_exif_tag_rational('Exif.Photo.FocalLengthIn35mmFilm') except KeyError: pass else: @@ -295,7 +258,7 @@ except (IndexError, KeyError): iwidth = self.get_exif_float_value('Exif.Photo.PixelXDimension') - fresunit = str(self._metadata['Exif.Photo.FocalPlaneResolutionUnit'].value) + fresunit = self._metadata['Exif.Photo.FocalPlaneResolutionUnit'] factors = {'1': 25.4, '2': 25.4, '3': 10, '4': 1, '5': 0.001} try: fresfactor = factors[fresunit] @@ -322,7 +285,7 @@ def get_jpeg_comment(self): try: - comment = self._metadata.comment.strip(' ') + comment = self._metadata.get_comment().strip(' ') if '\x00' in comment: raise ValueError # ignore broken JPEG comments return self._fallback_to_encoding(comment) @@ -331,7 +294,7 @@ def get_authorship(self): try: - return self.get_exif_string('Exif.Image.Artist') + return self._metadata['Exif.Image.Artist'] except KeyError: return '' diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygal/pyexiv2api.py --- a/lazygal/pyexiv2api.py Fri Nov 02 17:25:29 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,256 +0,0 @@ -# Lazygal, a lazy static web gallery generator. -# Copyright (C) 2011-2012 Alexandre Rossi -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -""" -This module provides a simple wrapper to the pyexiv2 API which changed between -version 0.1 and 0.2. The goal is to provide a wrapper compatible with the -latest API. - -Sample usage : - ->>> import pyexiv2api as pyexiv2 - -Now, simply use the latest API. The module has figured out whether to directly -use the pyexiv2 module if pyexiv2 >= 0.2 is available, or to mimic the new API -in case you are running with an older version. - -""" - - -import sys -import datetime - -import pyexiv2 -from PIL import Image as PILImage - - -def decode_exif_user_comment(raw, imgpath): - """ - Before pyexiv2 0.3, the EXIF user comment was not decoded to a unicode - string. This function does exactly that and is used for earlier versions - of pyexiv2. - """ - # This field can contain charset information - if raw.startswith('charset='): - tokens = raw.split(' ') - csetfield = tokens[0] - text = ' '.join(tokens[1:]) - ignore, cset = csetfield.split('=') - cset = cset.strip('"') - else: - cset = None - text = raw - - if cset == 'Unicode': - encoding = None - # Starting from 0.20, exiv2 converts unicode comments to UTF-8 - try: - text.decode('utf-8') - except UnicodeDecodeError: - # Decoding failed, maybe we can assume we are with exiv2 << 0.20 - im = PILImage.open(imgpath) - endianess = im.app['APP1'][6:8] - if endianess == 'MM': - encoding = 'utf-16be' - elif endianess == 'II': - encoding = 'utf-16le' - else: - raise ValueError - else: - encoding = 'utf-8' - elif cset == 'Ascii': - encoding = 'ascii' - elif cset == 'Jis': - encoding = 'shift_jis' - else: - # Fallback to utf-8 as this is mostly the default for Linux - # distributions. - encoding = 'utf-8' - - # Return the decoded string according to the found encoding. - try: - return text.decode(encoding) - except UnicodeDecodeError: - return text.decode(encoding, 'replace') - - -# This is required at import time for inheritances below. -if 'ImageMetadata' in dir(pyexiv2): - Pyexiv2ImageMetadata = pyexiv2.ImageMetadata -else: - # This is for the interpreter to be happy, but if pyexiv2.ImageMetadata - # does not exist, we are with pyexiv2 << 0.2, and the old API, so we won't - # be using classes that inherit from Pyexiv2ImageMetadata. - Pyexiv2ImageMetadata = object - - -class _ImageMetadata_0_2_2(Pyexiv2ImageMetadata): - - def __init__(self, imgpath): - super(_ImageMetadata_0_2_2, self).__init__(imgpath) - self.imgpath = imgpath - - def __getitem__(self, key): - tag = super(_ImageMetadata_0_2_2, self).__getitem__(key) - if key == 'Exif.Photo.UserComment': - tag.value = decode_exif_user_comment(tag.value, self.imgpath) - return tag - - -class _ImageMetadata_0_2(_ImageMetadata_0_2_2): - - def get_jpeg_comment(self): - # comment appeared in pyexiv2 0.2.2, so use PIL - im = PILImage.open(self.imgpath) - try: - return im.app['COM'].strip('\x00') - except KeyError: - return '' - - comment = property(get_jpeg_comment) - - -class _ImageTag_0_1(object): - - def __init__(self, tag, imgpath, md, key): - self._tag = tag - self._imgpath = imgpath - self._metadata = md - self._key = key - - def __getattr__(self, name): - if name == 'value': - return self.get_value() - elif name == 'raw_value': - return self._tag - elif name == 'human_value': - return self.get_interpreted_value() - else: - raise AttributeError - - def __str__(self): - return str(self._tag) - - def get_exif_date(self): - """ - Parses date from EXIF information. - """ - exif_date = str(self._metadata[self._key]) - date, time = exif_date.split(' ') - year, month, day = date.split('-') - hour, minute, second = time.split(':') - return datetime.datetime(int(year), int(month), int(day), - int(hour), int(minute), int(second)) - - def get_int(self): - return int(self._tag) - - def get_interpreted_value(self): - return self._metadata.interpretedExifValue(self._key) - - def get_decoded_utf8(self): - return self.get_interpreted_value().decode('utf-8') - - def get_decoded_exif_user_comment(self): - return decode_exif_user_comment(self._tag, self._imgpath) - - TAG_PYTRANSLATORS = { - 'Exif.Photo.DateTimeDigitized': 'get_exif_date', - 'Exif.Photo.DateTimeOriginal' : 'get_exif_date', - 'Exif.Photo.UserComment' : 'get_decoded_exif_user_comment', - 'Exif.Image.DateTime' : 'get_exif_date', - 'Exif.Image.Orientation' : 'get_int', - } - - def get_value(self): - if self._key in _ImageTag_0_1.TAG_PYTRANSLATORS.keys(): - translator = getattr(self.__class__, - _ImageTag_0_1.TAG_PYTRANSLATORS[self._key]) - return translator(self) - else: - return self._tag - - -class _ImageMetadata_0_1(object): - - def __init__(self, imgpath): - self.imgpath = imgpath - self._metadata = pyexiv2.Image(self.imgpath.encode(sys.getfilesystemencoding())) - - def __getitem__(self, key): - return _ImageTag_0_1(self._metadata[key], self.imgpath, - self._metadata, key) - - def __setitem__(self, key, value): - self._metadata[key] = value - - def __delitem__(self, key): - del self._metadata[key] - - def read(self): - self._metadata.readMetadata() - - def write(self): - self._metadata.writeMetadata() - - def __try_copy_tag_to(self, tag_key, dest_imgtags): - try: - dest_imgtags._metadata[tag_key] = self[tag_key] - except (ValueError, TypeError): - pass - - def copy(self, dest_imgtags): - try: - self._metadata.copyMetadataTo(dest_imgtags._metadata) - except (ValueError, TypeError): - # Sometimes pyexiv2 (<< 0.2) fails during the copy on a badly - # formatted tag, so we try a manual copy here for each tag. - for tag_key in self.exif_keys: - self.__try_copy_tag_to(tag_key, dest_imgtags) - for tag_key in self.iptc_keys: - self.__try_copy_tag_to(tag_key, dest_imgtags) - - def get_comment(self): return self._metadata.getComment() - - def set_comment(self, value): self._metadata.setComment(value) - comment = property(get_comment, set_comment) - - def get_exif_keys(self): return self._metadata.exifKeys() - exif_keys = property(get_exif_keys) - - def get_iptc_keys(self): return self._metadata.iptcKeys() - iptc_keys = property(get_iptc_keys) - - -if 'ImageMetadata' in dir(pyexiv2): - if 'comment' in dir(pyexiv2.ImageMetadata): - # pyexiv2 (>= 0.2.2) - if pyexiv2.version_info >= (0, 3, 0): - ImageMetadata = pyexiv2.ImageMetadata - else: - ImageMetadata = _ImageMetadata_0_2_2 - else: - # pyexiv2 (>= 0.2, << 0.2.2) - ImageMetadata = _ImageMetadata_0_2 -elif 'Image' in dir(pyexiv2): - # pyexiv2 (<< 0.2) - ImageMetadata = _ImageMetadata_0_1 -else: - raise ImportError('Unrecognized pyexiv2 version.') - - -# vim: ts=4 sw=4 expandtab diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygaltest/test_gendeps.py --- a/lazygaltest/test_gendeps.py Fri Nov 02 17:25:29 2012 +0100 +++ b/lazygaltest/test_gendeps.py Fri Dec 28 17:16:50 2012 -0800 @@ -24,7 +24,6 @@ from lazygal.generators import WebalbumDir from lazygal.sourcetree import Directory from lazygal.genpage import WebalbumIndexPage -from lazygal import pyexiv2api as pyexiv2 class TestDeps(LazygalTestGen): diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygaltest/test_generators.py --- a/lazygaltest/test_generators.py Fri Nov 02 17:25:29 2012 +0100 +++ b/lazygaltest/test_generators.py Fri Dec 28 17:16:50 2012 -0800 @@ -27,7 +27,7 @@ import lazygal.config from lazygal.generators import WebalbumDir from lazygal.sourcetree import Directory -from lazygal import pyexiv2api as pyexiv2 +from gi.repository import GExiv2 class TestGenerators(LazygalTestGen): @@ -115,39 +115,35 @@ img_path = self.add_img(self.source_dir, 'md_filled.jpg') # Add some metadata - gps_data = pyexiv2.ImageMetadata(self.get_sample_path('sample-with-gps.jpg')) - gps_data.read() - source_image = pyexiv2.ImageMetadata(img_path) - source_image.read() - gps_data.copy(source_image) + gps_data = GExiv2.Metadata(self.get_sample_path('sample-with-gps.jpg')) + source_image = GExiv2.Metadata(img_path) + for tag in gps_data.get_exif_tags(): + source_image[tag] = gps_data[tag] dummy_comment = 'nice photo' source_image['Exif.Photo.UserComment'] = dummy_comment dummy_date = datetime.datetime(2011, 2, 3, 12, 51, 43) - source_image['Exif.Photo.DateTimeDigitized'] = dummy_date - assert 'Exif.GPSInfo.GPSLongitude' in source_image.exif_keys - assert 'Exif.GPSInfo.GPSLatitude' in source_image.exif_keys - source_image.write() + source_image.set_date_time(dummy_date) + assert 'Exif.GPSInfo.GPSLongitude' in source_image + assert 'Exif.GPSInfo.GPSLatitude' in source_image + source_image.save_file() # Generate album dest_dir = self.get_working_path() self.album.generate(dest_dir) dest_img_path = os.path.join(dest_dir, 'md_filled_small.jpg') - dest_image = pyexiv2.ImageMetadata(dest_img_path) - dest_image.read() + dest_image = GExiv2.Metadata(dest_img_path) # Check that metadata is still here for reduced pictures. - self.assertEqual(dest_image['Exif.Photo.UserComment'].value, - dummy_comment) - self.assertEqual(dest_image['Exif.Photo.DateTimeDigitized'].value, - dummy_date) + self.assertEqual(dest_image['Exif.Photo.UserComment'], dummy_comment) + self.assertEqual(dest_image['Exif.Photo.DateTimeDigitized'], dummy_date.strftime('%Y:%m:%d %H:%M:%S')) # Check that blacklised tags are not present anymore in the reduced # picture. - def lat(): return dest_image['Exif.GPSInfo.GPSLongitude'].value + def lat(): return dest_image['Exif.GPSInfo.GPSLongitude'] self.assertRaises(KeyError, lat) - def long(): return dest_image['Exif.GPSInfo.GPSLatitude'].value + def long(): return dest_image['Exif.GPSInfo.GPSLatitude'] self.assertRaises(KeyError, long) def test_metadata_osize_nopublish(self): @@ -158,22 +154,20 @@ img_path = self.add_img(self.source_dir, 'md_filled.jpg') # Add some metadata - source_image = pyexiv2.ImageMetadata(img_path) - source_image.read() + source_image = GExiv2.Metadata(img_path) dummy_comment = 'nice photo' source_image['Exif.Photo.UserComment'] = dummy_comment - source_image.write() + source_image.save_file() # Generate album dest_dir = self.get_working_path() self.album.generate(dest_dir) dest_img_path = os.path.join(dest_dir, 'md_filled_small.jpg') - dest_image = pyexiv2.ImageMetadata(dest_img_path) - dest_image.read() + dest_image = GExiv2.Metadata(dest_img_path) # Check that metadata is not here for reduced pictures. - def com(): return dest_image['Exif.Photo.UserComment'].value + def com(): return dest_image['Exif.Photo.UserComment'] self.assertRaises(KeyError, com) def test_resize_rotate_size(self): @@ -183,10 +177,9 @@ norotate_path = self.add_img(self.source_dir, 'norotate.jpg') torotate_path = self.add_img(self.source_dir, 'torotate.jpg') - torotate = pyexiv2.ImageMetadata(torotate_path) - torotate.read() - torotate['Exif.Image.Orientation'] = 8 - torotate.write() + torotate = GExiv2.Metadata(torotate_path) + torotate['Exif.Image.Orientation'] = '8' + torotate.save_file() # Generate album dest_dir = self.get_working_path() @@ -336,14 +329,14 @@ for index, pic in enumerate(pics): img_path = self.add_img(subgal_path, pic) - img_exif = pyexiv2.ImageMetadata(img_path) - img_exif.read() + img_exif = GExiv2.Metadata(img_path) for tag in ('Exif.Photo.DateTimeDigitized', 'Exif.Photo.DateTimeOriginal', 'Exif.Image.DateTime', ): - img_exif[tag] = datetime.datetime(2011, months[index], 1) - img_exif.write() + img_exif[tag] = datetime.datetime( + 2011, months[index], 1).strftime('%Y:%m:%d %H:%M:%S') + img_exif.save_file() return subgal_path, pics diff -r 5a2ee7d95f6d -r 5263a3c99f57 lazygaltest/test_metadata.py --- a/lazygaltest/test_metadata.py Fri Nov 02 17:25:29 2012 +0100 +++ b/lazygaltest/test_metadata.py Fri Dec 28 17:16:50 2012 -0800 @@ -26,7 +26,7 @@ metadata.FILE_METADATA_ENCODING = 'utf-8' # force for these tests from lazygal.generators import Album from lazygal.sourcetree import Directory -from lazygal import pyexiv2api as pyexiv2 +from gi.repository import GExiv2 class TestFileMetadata(LazygalTest): @@ -61,23 +61,6 @@ md = metadata.DirectoryMetadata(self.album_root.path) self.assertEqual(md.get()['album_description'], album_desc) - def test_img_desc(self): - img_path = self.add_img(self.source_dir, 'captioned_pic.jpg') - - # Set dumy comment which should be ignored. - im = pyexiv2.ImageMetadata(img_path) - im.read() - im['Exif.Photo.UserComment'] = 'comment not to show' - im.write() - - # Output real comment which should be chosen over the dummy comment. - image_caption = u'Les élèves forment une ronde dans la cour.' - self.create_file(os.path.join(self.source_dir, img_path + '.comment'), - image_caption) - - imgmd = metadata.ImageInfoTags(img_path) - self.assertEqual(imgmd.get_comment(), image_caption) - def test_album_picture(self): img_names = ('ontop.jpg', 'second.jpg', ) for img_name in img_names: @@ -92,14 +75,14 @@ self.assertEqual(img_names[0], self.album_root.album_picture) def test_comment_none(self): - im_md = metadata.ImageInfoTags(self.get_sample_path('sample.jpg')) - self.assertEqual(im_md.get_comment(), '') + im = GExiv2.Metadata(self.get_sample_path('sample.jpg')) + self.assertEqual(im.get_comment(), None) def test_image_description(self): sample = 'sample-image-description.jpg' - im_md = metadata.ImageInfoTags(self.get_sample_path(sample)) + im = GExiv2.Metadata(self.get_sample_path(sample)) - self.assertEqual(im_md.get_comment(), 'test ImageDescription') + self.assertEqual(im.get_comment(), 'test ImageDescription') def test_jpeg_comment(self): sample = 'sample-jpeg-comment.jpg' @@ -117,19 +100,19 @@ sample = 'sample-usercomment-ascii.jpg' im_md = metadata.ImageInfoTags(self.get_sample_path(sample)) - self.assertEqual(im_md.get_comment(), u'deja vu') + self.assertEqual(im_md.get_comment(), u'charset="Ascii" deja vu') def test_usercomment_unicode_le(self): sample = 'sample-usercomment-unicode-ii.jpg' im_md = metadata.ImageInfoTags(self.get_sample_path(sample)) - self.assertEqual(im_md.get_comment(), u'unicode test éà') + self.assertEqual(im_md.get_comment(), u'charset="Unicode" unicode test éà') def test_usercomment_unicode_be(self): sample = 'sample-usercomment-unicode-mm.jpg' im_md = metadata.ImageInfoTags(self.get_sample_path(sample)) - self.assertEqual(im_md.get_comment(), u'unicode test : éàê') + self.assertEqual(im_md.get_comment(), u'charset="Unicode" unicode test : éàê') def test_model(self): sample = 'sample-model-nikon1.jpg' @@ -157,7 +140,7 @@ def test_focal_length(self): sample = 'sample-model-pentax1.jpg' im_md = metadata.ImageInfoTags(self.get_sample_path(sample)) - self.assertEqual(im_md.get_focal_length(), '18.0 mm (35 mm equivalent: 27.0 mm)') + self.assertEqual(im_md.get_focal_length(), '18 mm (35 mm equivalent: 27 mm)') if __name__ == '__main__':