diff options
author | Olivier Tilloy <olivier@tilloy.net> | 2010-02-18 00:01:04 +0100 |
---|---|---|
committer | Olivier Tilloy <olivier@tilloy.net> | 2010-02-18 00:01:04 +0100 |
commit | f5cdc26f8283fc727ebd3861f74f87a3df937541 (patch) | |
tree | ca6c46c44c8e78ab842491c6ea9faa472dcfc44f | |
parent | 6f165359c2e67e35b328fdb5b6ad6aa8f22cdab9 (diff) | |
parent | 314907a2796b09d25c99933f6f2c765ac9784784 (diff) | |
download | pyexiv2-f5cdc26f8283fc727ebd3861f74f87a3df937541.tar.gz |
Support direct value assignment.
This should ease the life of application developers.
Thanks to Damien Moore for the suggestion.
-rw-r--r-- | doc/tutorial.rst | 21 | ||||
-rwxr-xr-x | src/examples.py | 15 | ||||
-rw-r--r-- | src/pyexiv2/metadata.py | 41 | ||||
-rw-r--r-- | test/metadata.py | 67 |
4 files changed, 113 insertions, 31 deletions
diff --git a/doc/tutorial.rst b/doc/tutorial.rst index a5bc849..7ecf1e5 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -87,6 +87,13 @@ pair (see exiv2's documentation for a list of valid >>> value = 'This is a useful comment.' >>> metadata[key] = pyexiv2.ExifTag(key, value) +As a handy shortcut, you can always assign a value for a given key regardless +of whether it's already present in the metadata. +If a tag was present, its value is overwritten. +If the tag was not present, one is created and its value is set:: + + >>> metadata[key] = value + Reading and writing IPTC tags ############################# @@ -155,6 +162,13 @@ pair (see exiv2's documentation for a list of valid >>> values = ['John', 'Paul', 'Ringo', 'George'] >>> metadata[key] = pyexiv2.IptcTag(key, values) +As a handy shortcut, you can always assign values for a given key regardless +of whether it's already present in the metadata. +If a tag was present, its values are overwritten. +If the tag was not present, one is created and its values are set:: + + >>> metadata[key] = values + Reading and writing XMP tags ############################ @@ -209,6 +223,13 @@ pair (see exiv2's documentation for a list of valid >>> value = 'A beautiful picture.' >>> metadata[key] = pyexiv2.XmpTag(key, value) +As a handy shortcut, you can always assign a value for a given key regardless +of whether it's already present in the metadata. +If a tag was present, its value is overwritten. +If the tag was not present, one is created and its value is set:: + + >>> metadata[key] = value + Accessing embedded previews ########################### diff --git a/src/examples.py b/src/examples.py index 1a36758..d393387 100755 --- a/src/examples.py +++ b/src/examples.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -from pyexiv2 import ImageMetadata, ExifTag, IptcTag, XmpTag +from pyexiv2 import ImageMetadata import sys, os from datetime import datetime, date @@ -26,14 +26,14 @@ if __name__ == '__main__': print_key_value(metadata, key) # Set the value of the Exif.Image.DateTime tag - metadata[key].value = datetime.now() + metadata[key] = datetime.now() print_key_value(metadata, key) except KeyError: print '[not set]' # Add a new tag key = 'Exif.Image.Orientation' - metadata[key] = ExifTag(key, 1) + metadata[key] = 1 print_key_value(metadata, key) # Print a list of all the keys of the IPTC tags in the image @@ -45,7 +45,7 @@ if __name__ == '__main__': print_key_value(metadata, key) # Set the value of the Iptc.Application2.DateCreated tag - metadata[key].values = [date.today()] + metadata[key] = [date.today()] print_key_value(metadata, key) except KeyError: print '[not set]' @@ -53,7 +53,7 @@ if __name__ == '__main__': # Add a new tag key = 'Iptc.Application2.Keywords' keywords = ['little', 'big', 'man'] - metadata[key] = IptcTag(key, keywords) + metadata[key] = keywords print_key_value(metadata, key) # Print a list of all the keys of the XMP tags in the image @@ -65,15 +65,14 @@ if __name__ == '__main__': print_key_value(metadata, key) # Set the value of the Xmp.dc.subject tag - metadata[key].value = keywords + metadata[key] = keywords print_key_value(metadata, key) except KeyError: print '[not set]' # Add a new tag key = 'Xmp.dc.title' - value = {'x-default': 'Sunset', 'fr': 'Coucher de soleil'} - metadata[key] = XmpTag(key, value) + metadata[key] = {'x-default': 'Sunset', 'fr': 'Coucher de soleil'} print_key_value(metadata, key) # Write back the metadata to the file diff --git a/src/pyexiv2/metadata.py b/src/pyexiv2/metadata.py index 82fe1f9..15b32f3 100644 --- a/src/pyexiv2/metadata.py +++ b/src/pyexiv2/metadata.py @@ -170,10 +170,13 @@ class ImageMetadata(object): except AttributeError: raise KeyError(key) - def _set_exif_tag(self, tag): + def _set_exif_tag(self, key, tag_or_value): # Set an EXIF tag. If the tag already exists, its value is overwritten. - if not isinstance(tag, ExifTag): - raise TypeError('Expecting an ExifTag') + if isinstance(tag_or_value, ExifTag): + tag = tag_or_value + else: + # As a handy shortcut, accept direct value assignment. + tag = ExifTag(key, tag_or_value) self._image._setExifTagValue(tag.key, tag.raw_value) self._tags['exif'][tag.key] = tag if tag.key not in self.exif_keys: @@ -192,11 +195,14 @@ class ImageMetadata(object): raise TypeError('Expecting a string') self._image._setExifTagValue(key, value) - def _set_iptc_tag(self, tag): + def _set_iptc_tag(self, key, tag_or_values): # Set an IPTC tag. If the tag already exists, its values are # overwritten. - if not isinstance(tag, IptcTag): - raise TypeError('Expecting an IptcTag') + if isinstance(tag_or_values, IptcTag): + tag = tag_or_values + else: + # As a handy shortcut, accept direct value assignment. + tag = IptcTag(key, tag_or_values) self._image._setIptcTagValues(tag.key, tag.raw_values) self._tags['iptc'][tag.key] = tag if tag.key not in self.iptc_keys: @@ -219,10 +225,13 @@ class ImageMetadata(object): raise TypeError('Expecting a list of strings') self._image._setIptcTagValues(key, values) - def _set_xmp_tag(self, tag): + def _set_xmp_tag(self, key, tag_or_value): # Set an XMP tag. If the tag already exists, its value is overwritten. - if not isinstance(tag, XmpTag): - raise TypeError('Expecting an XmpTag') + if isinstance(tag_or_value, XmpTag): + tag = tag_or_value + else: + # As a handy shortcut, accept direct value assignment. + tag = XmpTag(key, tag_or_value) type = tag._tag._getExiv2Type() if type == 'XmpText': self._image._setXmpTagTextValue(tag.key, tag.raw_value) @@ -253,24 +262,28 @@ class ImageMetadata(object): else: raise TypeError('Expecting either a string, a list, a tuple or a dict') - def __setitem__(self, key, tag): + def __setitem__(self, key, tag_or_value): """ Set a metadata tag for a given key. If the tag was previously set, it is overwritten. + As a handy shortcut, a value may be passed instead of a fully formed + tag. The corresponding tag object will be instantiated. :param key: metadata key in the dotted form ``familyName.groupName.tagName`` where ``familyName`` may be one of ``exif``, ``iptc`` or ``xmp``. :type key: string - :param tag: an instance of the corresponding family of metadata tag - :type tag: :class:`pyexiv2.exif.ExifTag` or - :class:`pyexiv2.iptc.IptcTag` or :class:`pyexiv2.xmp.XmpTag` + :param tag_or_value: an instance of the corresponding family of metadata + tag, or a value + :type tag_or_value: :class:`pyexiv2.exif.ExifTag` or + :class:`pyexiv2.iptc.IptcTag` or + :class:`pyexiv2.xmp.XmpTag` or any valid value type :raise KeyError: if the key is invalid """ family = key.split('.')[0].lower() try: - return getattr(self, '_set_%s_tag' % family)(tag) + return getattr(self, '_set_%s_tag' % family)(key, tag_or_value) except AttributeError: raise KeyError(key) diff --git a/test/metadata.py b/test/metadata.py index 4ef933d..237a510 100644 --- a/test/metadata.py +++ b/test/metadata.py @@ -260,7 +260,7 @@ class TestImageMetadata(unittest.TestCase): tag = ExifTag('Exif.Thumbnail.Orientation', 1) self.assertEqual(tag.metadata, None) self.assert_(tag.key not in self.metadata.exif_keys) - self.metadata._set_exif_tag(tag) + self.metadata._set_exif_tag(tag.key, tag) self.assertEqual(tag.metadata, self.metadata) self.assert_(tag.key in self.metadata.exif_keys) self.assertEqual(self.metadata._tags['exif'], {tag.key: tag}) @@ -275,7 +275,7 @@ class TestImageMetadata(unittest.TestCase): # Overwrite an existing tag tag = ExifTag('Exif.Image.DateTime', datetime.datetime(2009, 3, 20, 20, 32, 0)) self.assertEqual(tag.metadata, None) - self.metadata._set_exif_tag(tag) + self.metadata._set_exif_tag(tag.key, tag) self.assertEqual(tag.metadata, self.metadata) self.assertEqual(self.metadata._tags['exif'], {tag.key: tag}) self.assert_(self.metadata._image.tags['exif'].has_key(tag.key)) @@ -292,7 +292,7 @@ class TestImageMetadata(unittest.TestCase): self.assertEqual(self.metadata._tags['exif'][key], tag) new_tag = ExifTag(key, '48 50 50 48 ', _tag=_ExifTagMock(key, 'Undefined', '48 50 50 48 ', '2.20')) self.assertEqual(new_tag.metadata, None) - self.metadata._set_exif_tag(new_tag) + self.metadata._set_exif_tag(key, new_tag) self.assertEqual(new_tag.metadata, self.metadata) self.assertEqual(self.metadata._tags['exif'], {key: new_tag}) self.assert_(self.metadata._image.tags['exif'].has_key(key)) @@ -300,6 +300,22 @@ class TestImageMetadata(unittest.TestCase): # value. self.assertEqual(self.metadata._image.tags['exif'][key], new_tag.raw_value) + def test_set_exif_tag_direct_value_assignment(self): + self.metadata.read() + self._set_exif_tags() + self.assertEqual(self.metadata._tags['exif'], {}) + # Direct value assignment: pass a value instead of a fully-formed tag + key = 'Exif.Thumbnail.Orientation' + value = 1 + self.metadata._set_exif_tag(key, value) + self.assert_(key in self.metadata.exif_keys) + self.assert_(self.metadata._image.tags['exif'].has_key(key)) + tag = self.metadata._get_exif_tag(key) + self.assertEqual(tag.value, value) + self.assertEqual(tag.metadata, self.metadata) + self.assertEqual(self.metadata._tags['exif'], {key: tag}) + self.assertEqual(self.metadata._image.tags['exif'][key], tag.raw_value) + def test_set_exif_tag_value_inexistent(self): self.metadata.read() self._set_exif_tags() @@ -396,7 +412,7 @@ class TestImageMetadata(unittest.TestCase): tag = IptcTag('Iptc.Application2.Writer', ['Nobody']) self.assertEqual(tag.metadata, None) self.assert_(tag.key not in self.metadata.iptc_keys) - self.metadata._set_iptc_tag(tag) + self.metadata._set_iptc_tag(tag.key, tag) self.assertEqual(tag.metadata, self.metadata) self.assert_(tag.key in self.metadata.iptc_keys) self.assertEqual(self.metadata._tags['iptc'], {tag.key: tag}) @@ -411,7 +427,7 @@ class TestImageMetadata(unittest.TestCase): # Overwrite an existing tag tag = IptcTag('Iptc.Application2.Caption', ['A picture.']) self.assertEqual(tag.metadata, None) - self.metadata._set_iptc_tag(tag) + self.metadata._set_iptc_tag(tag.key, tag) self.assertEqual(tag.metadata, self.metadata) self.assertEqual(self.metadata._tags['iptc'], {tag.key: tag}) self.assert_(self.metadata._image.tags['iptc'].has_key(tag.key)) @@ -428,13 +444,29 @@ class TestImageMetadata(unittest.TestCase): self.assertEqual(self.metadata._tags['iptc'][key], tag) new_tag = IptcTag(key, ['A picture.']) self.assertEqual(new_tag.metadata, None) - self.metadata._set_iptc_tag(new_tag) + self.metadata._set_iptc_tag(key, new_tag) self.assertEqual(new_tag.metadata, self.metadata) self.assertEqual(self.metadata._tags['iptc'], {key: new_tag}) self.assert_(self.metadata._image.tags['iptc'].has_key(key)) self.assertEqual(self.metadata._image.tags['iptc'][key], new_tag.raw_values) + def test_set_iptc_tag_direct_value_assignment(self): + self.metadata.read() + self._set_iptc_tags() + self.assertEqual(self.metadata._tags['iptc'], {}) + # Direct value assignment: pass a value instead of a fully-formed tag + key = 'Iptc.Application2.Writer' + values = ['Nobody'] + self.metadata._set_iptc_tag(key, values) + self.assert_(key in self.metadata.iptc_keys) + self.assert_(self.metadata._image.tags['iptc'].has_key(key)) + tag = self.metadata._get_iptc_tag(key) + self.assertEqual(tag.values, values) + self.assertEqual(tag.metadata, self.metadata) + self.assertEqual(self.metadata._tags['iptc'], {key: tag}) + self.assertEqual(self.metadata._image.tags['iptc'][key], tag.raw_values) + def test_set_iptc_tag_values_inexistent(self): self.metadata.read() self._set_iptc_tags() @@ -535,7 +567,7 @@ class TestImageMetadata(unittest.TestCase): 'fr-FR': "Ceci n'est pas un titre"}) self.assertEqual(tag.metadata, None) self.assert_(tag.key not in self.metadata.xmp_keys) - self.metadata._set_xmp_tag(tag) + self.metadata._set_xmp_tag(tag.key, tag) self.assertEqual(tag.metadata, self.metadata) self.assert_(tag.key in self.metadata.xmp_keys) self.assertEqual(self.metadata._tags['xmp'], {tag.key: tag}) @@ -550,7 +582,7 @@ class TestImageMetadata(unittest.TestCase): # Overwrite an existing tag tag = XmpTag('Xmp.dc.format', ('image', 'png')) self.assertEqual(tag.metadata, None) - self.metadata._set_xmp_tag(tag) + self.metadata._set_xmp_tag(tag.key, tag) self.assertEqual(tag.metadata, self.metadata) self.assertEqual(self.metadata._tags['xmp'], {tag.key: tag}) self.assert_(self.metadata._image.tags['xmp'].has_key(tag.key)) @@ -567,13 +599,30 @@ class TestImageMetadata(unittest.TestCase): self.assertEqual(self.metadata._tags['xmp'][key], tag) new_tag = XmpTag(key, datetime.datetime(2009, 4, 21, 20, 7, 0, tzinfo=FixedOffset('+', 1, 0))) self.assertEqual(new_tag.metadata, None) - self.metadata._set_xmp_tag(new_tag) + self.metadata._set_xmp_tag(key, new_tag) self.assertEqual(new_tag.metadata, self.metadata) self.assertEqual(self.metadata._tags['xmp'], {key: new_tag}) self.assert_(self.metadata._image.tags['xmp'].has_key(key)) self.assertEqual(self.metadata._image.tags['xmp'][key], new_tag.raw_value) + def test_set_xmp_tag_direct_value_assignment(self): + self.metadata.read() + self._set_xmp_tags() + self.assertEqual(self.metadata._tags['xmp'], {}) + # Direct value assignment: pass a value instead of a fully-formed tag + key = 'Xmp.dc.title' + value = {'x-default': 'This is not a title', + 'fr-FR': "Ceci n'est pas un titre"} + self.metadata._set_xmp_tag(key, value) + self.assert_(key in self.metadata.xmp_keys) + self.assert_(self.metadata._image.tags['xmp'].has_key(key)) + tag = self.metadata._get_xmp_tag(key) + self.assertEqual(tag.value, value) + self.assertEqual(tag.metadata, self.metadata) + self.assertEqual(self.metadata._tags['xmp'], {key: tag}) + self.assertEqual(self.metadata._image.tags['xmp'][key], tag.raw_value) + def test_set_xmp_tag_value_inexistent(self): self.metadata.read() self._set_xmp_tags() |