diff options
-rw-r--r-- | doc/api.rst | 2 | ||||
-rw-r--r-- | doc/tutorial.rst | 12 | ||||
-rw-r--r-- | src/pyexiv2/iptc.py | 42 | ||||
-rw-r--r-- | test/ReadMetadataTestCase.py | 4 | ||||
-rw-r--r-- | test/iptc.py | 36 | ||||
-rw-r--r-- | test/metadata.py | 12 |
6 files changed, 84 insertions, 24 deletions
diff --git a/doc/api.rst b/doc/api.rst index de6c918..c1e17b2 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -35,7 +35,7 @@ pyexiv2.iptc .. autoexception:: IptcValueError .. autoclass:: IptcTag :members: key, type, name, title, description, photoshop_name, repeatable, - record_name, record_description, raw_values, values + record_name, record_description, raw_value, value pyexiv2.xmp ########### diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 7ecf1e5..6161285 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -129,13 +129,13 @@ one value:: False As with EXIF tags, the values of an :class:`IptcTag` object can be accessed in -two different ways: with the :attr:`raw_values` and with the :attr:`values` +two different ways: with the :attr:`raw_value` and with the :attr:`value` attributes:: - >>> tag.raw_values + >>> tag.raw_value ['2004-07-13'] - >>> tag.values + >>> tag.value [datetime.date(2004, 7, 13)] Note that querying the values of a tag may raise an :exc:`IptcValueError` if the @@ -146,12 +146,12 @@ python object. Now let's modify the values of the tag and write it back to the file:: - >>> tag.values = [datetime.date.today()] + >>> tag.value = [datetime.date.today()] >>> metadata.write() Similarly to reading the values of a tag, one can set either the -:attr:`raw_values` or the :attr:`values` (which will be automatically converted +:attr:`raw_value` or the :attr:`value` (which will be automatically converted to correctly formatted byte strings by pyexiv2). You can also add new tags to the metadata by providing a valid key and values @@ -189,7 +189,7 @@ Each of those tags can be accessed with the ``[]`` operator on the metadata:: >>> tag = metadata['Xmp.xmp.ModifyDate'] -As with EXIF tags, the values of an :class:`XmpTag` object can be accessed in +As with EXIF tags, the value of an :class:`XmpTag` object can be accessed in two different ways: with the :attr:`raw_value` and with the :attr:`value` attributes:: diff --git a/src/pyexiv2/iptc.py b/src/pyexiv2/iptc.py index d34743f..e30921c 100644 --- a/src/pyexiv2/iptc.py +++ b/src/pyexiv2/iptc.py @@ -35,6 +35,7 @@ from pyexiv2.utils import ListenerInterface, NotifyingList, FixedOffset import time import datetime import re +import warnings class IptcValueError(ValueError): @@ -106,7 +107,7 @@ class IptcTag(ListenerInterface): def _from_existing_tag(_tag): # Build a tag from an already existing libexiv2python._IptcTag tag = IptcTag(_tag._getKey(), _tag=_tag) - # Do not set the raw_values property, as it would call + # Do not set the raw_value property, as it would call # _tag._setRawValues # (see https://bugs.launchpad.net/pyexiv2/+bug/582445). tag._raw_values = _tag._getRawValues() @@ -170,8 +171,23 @@ class IptcTag(ListenerInterface): self._raw_values = values self._values_cookie = True - raw_values = property(fget=_get_raw_values, fset=_set_raw_values, - doc='The raw values of the tag as a list of strings.') + raw_value = property(fget=_get_raw_values, fset=_set_raw_values, + doc='The raw values of the tag as a list of strings.') + + def _get_raw_values_deprecated(self): + msg = "The 'raw_values' property is deprecated, " \ + "use the 'raw_value' property instead." + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + return self._get_raw_values() + + def _set_raw_values_deprecated(self, values): + msg = "The 'raw_values' property is deprecated, " \ + "use the 'raw_value' property instead." + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + return self._set_raw_values(values) + + raw_values = property(fget=_get_raw_values_deprecated, + fset=_set_raw_values_deprecated) def _compute_values(self): # Lazy computation of the values from the raw values @@ -188,7 +204,7 @@ class IptcTag(ListenerInterface): def _set_values(self, values): if not isinstance(values, (list, tuple)): raise TypeError('Expecting a list of values') - self.raw_values = map(self._convert_to_string, values) + self.raw_value = map(self._convert_to_string, values) if isinstance(self._values, NotifyingList): self._values.unregister_listener(self) @@ -203,8 +219,22 @@ class IptcTag(ListenerInterface): self._values.register_listener(self) self._values_cookie = False - values = property(fget=_get_values, fset=_set_values, - doc='The values of the tag as a list of python objects.') + value = property(fget=_get_values, fset=_set_values, + doc='The values of the tag as a list of python objects.') + + def _get_values_deprecated(self): + msg = "The 'values' property is deprecated, " \ + "use the 'value' property instead." + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + return self._get_values() + + def _set_values_deprecated(self, values): + msg = "The 'values' property is deprecated, " \ + "use the 'value' property instead." + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + return self._set_values(values) + + values = property(fget=_get_values_deprecated, fset=_set_values_deprecated) def contents_changed(self): # Implementation of the ListenerInterface. diff --git a/test/ReadMetadataTestCase.py b/test/ReadMetadataTestCase.py index 5840c35..1ca9e5d 100644 --- a/test/ReadMetadataTestCase.py +++ b/test/ReadMetadataTestCase.py @@ -42,9 +42,9 @@ class ReadMetadataTestCase(unittest.TestCase): self.assertEqual(tag.value, evalue) def check_type_and_values(self, tag, etype, evalues): - for value in tag.values: + for value in tag.value: self.assertEqual(type(value), etype) - self.assertEqual(tag.values, evalues) + self.assertEqual(tag.value, evalues) def assertCorrectFile(self, filename, md5sum): """ diff --git a/test/iptc.py b/test/iptc.py index 6da1580..ead0f47 100644 --- a/test/iptc.py +++ b/test/iptc.py @@ -30,6 +30,7 @@ from pyexiv2.iptc import IptcTag, IptcValueError from pyexiv2.utils import FixedOffset import datetime +import warnings class TestIptcTag(unittest.TestCase): @@ -186,9 +187,9 @@ class TestIptcTag(unittest.TestCase): def test_set_values(self): tag = IptcTag('Iptc.Application2.City', ['Seattle']) - old_values = tag.values - tag.values = ['Barcelona'] - self.failIfEqual(tag.values, old_values) + old_values = tag.value + tag.value = ['Barcelona'] + self.failIfEqual(tag.value, old_values) def test_set_raw_values_invalid(self): tag = IptcTag('Iptc.Envelope.DateSent') @@ -200,3 +201,32 @@ class TestIptcTag(unittest.TestCase): values = [datetime.date.today(), datetime.date.today()] self.failUnlessRaises(KeyError, tag._set_values, values) + def test_deprecated_properties(self): + # The .raw_values and .values properties are deprecated in favour of + # .raw_value and .value. Check that they still work for backward + # compatibility and that they issue a deprecation warning. + # See https://launchpad.net/bugs/617557. + tag = IptcTag('Iptc.Application2.City', ['Barcelona']) + raw_value = tag.raw_value + value = tag.value + + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + + self.assertEqual(tag.raw_values, raw_value) + self.assertEqual(len(w), 1) + self.assert_(issubclass(w[-1].category, DeprecationWarning)) + + self.assertEqual(tag.values, value) + self.assertEqual(len(w), 2) + self.assert_(issubclass(w[-1].category, DeprecationWarning)) + + tag.raw_values = ['Madrid'] + self.assertEqual(len(w), 3) + self.assert_(issubclass(w[-1].category, DeprecationWarning)) + + tag.values = ['Madrid'] + self.assertEqual(len(w), 4) + self.assert_(issubclass(w[-1].category, DeprecationWarning)) + diff --git a/test/metadata.py b/test/metadata.py index 98ce689..9ee7b32 100644 --- a/test/metadata.py +++ b/test/metadata.py @@ -280,7 +280,7 @@ class TestImageMetadata(unittest.TestCase): self.assertEqual(self.metadata._tags['iptc'], {tag.key: tag}) self.assert_(tag.key in self.metadata._image._iptcKeys()) self.assertEqual(self.metadata._image._getIptcTag(tag.key)._getRawValues(), - tag.raw_values) + tag.raw_value) def test_set_iptc_tag_overwrite(self): self.metadata.read() @@ -291,7 +291,7 @@ class TestImageMetadata(unittest.TestCase): self.assertEqual(self.metadata._tags['iptc'], {tag.key: tag}) self.assert_(tag.key in self.metadata._image._iptcKeys()) self.assertEqual(self.metadata._image._getIptcTag(tag.key)._getRawValues(), - tag.raw_values) + tag.raw_value) def test_set_iptc_tag_overwrite_already_cached(self): self.metadata.read() @@ -305,7 +305,7 @@ class TestImageMetadata(unittest.TestCase): self.assertEqual(self.metadata._tags['iptc'], {key: new_tag}) self.assert_(key in self.metadata._image._iptcKeys()) self.assertEqual(self.metadata._image._getIptcTag(key)._getRawValues(), - new_tag.raw_values) + new_tag.raw_value) def test_set_iptc_tag_direct_value_assignment(self): self.metadata.read() @@ -317,10 +317,10 @@ class TestImageMetadata(unittest.TestCase): self.assert_(key in self.metadata.iptc_keys) self.assert_(key in self.metadata._image._iptcKeys()) tag = self.metadata._get_iptc_tag(key) - self.assertEqual(tag.values, values) + self.assertEqual(tag.value, values) self.assertEqual(self.metadata._tags['iptc'], {key: tag}) self.assertEqual(self.metadata._image._getIptcTag(key)._getRawValues(), - tag.raw_values) + tag.raw_value) def test_delete_iptc_tag_inexistent(self): self.metadata.read() @@ -594,7 +594,7 @@ class TestImageMetadata(unittest.TestCase): self.failUnlessEqual(self.metadata[key].value, self.other[key].value) for key in self.metadata.iptc_keys: - self.failUnlessEqual(self.metadata[key].values, self.other[key].values) + self.failUnlessEqual(self.metadata[key].value, self.other[key].value) for key in self.metadata.xmp_keys: self.failUnlessEqual(self.metadata[key].value, self.other[key].value) |