aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Tilloy <olivier@tilloy.net>2010-02-18 00:01:04 +0100
committerOlivier Tilloy <olivier@tilloy.net>2010-02-18 00:01:04 +0100
commitf5cdc26f8283fc727ebd3861f74f87a3df937541 (patch)
treeca6c46c44c8e78ab842491c6ea9faa472dcfc44f
parent6f165359c2e67e35b328fdb5b6ad6aa8f22cdab9 (diff)
parent314907a2796b09d25c99933f6f2c765ac9784784 (diff)
downloadpyexiv2-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.rst21
-rwxr-xr-xsrc/examples.py15
-rw-r--r--src/pyexiv2/metadata.py41
-rw-r--r--test/metadata.py67
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()