def test_convert_to_python_string(self): # Valid values tag = IptcTag('Iptc.Application2.Subject') self.assertEqual(tag.type, 'String') self.assertEqual(tag._convert_to_python('Some text.'), 'Some text.') self.assertEqual(tag._convert_to_python('Some text with exotic chàräctérʐ.'), 'Some text with exotic chàräctérʐ.')
def test_setitem(metadata_ro): m = metadata_ro.metadata m.read() # Set new tags key = 'Exif.Photo.ExposureBiasValue' tag = ExifTag(key, make_fraction(0, 3)) m[key] = tag assert key in m._tags['exif'] assert m._tags['exif'][key] == tag key = 'Iptc.Application2.City' tag = IptcTag(key, ['Barcelona']) m[key] = tag assert key in m._tags['iptc'] assert m._tags['iptc'][key] == tag key = 'Xmp.dc.description' tag = XmpTag(key, {'x-default': 'Sunset picture.'}) m[key] = tag assert key in m._tags['xmp'] assert m._tags['xmp'][key] == tag # Replace existing tags key = 'Exif.Photo.ExifVersion' tag = ExifTag(key, '0220') m[key] = tag assert key in m._tags['exif'] assert m._tags['exif'][key] == tag key = 'Iptc.Application2.Caption' tag = IptcTag(key, ['Sunset on Barcelona.']) m[key] = tag assert key in m._tags['iptc'] assert m._tags['iptc'][key] == tag key = 'Xmp.dc.subject' tag = XmpTag(key, ['sunset', 'Barcelona', 'beautiful', 'beach']) m[key] = tag assert key in m._tags['xmp'] assert m._tags['xmp'][key] == tag
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))
def test_setitem(self): self.metadata.read() # Set new tags key = 'Exif.Photo.ExposureBiasValue' tag = ExifTag(key, make_fraction(0, 3)) self.metadata[key] = tag self.failUnless(key in self.metadata._tags['exif']) self.failUnlessEqual(self.metadata._tags['exif'][key], tag) key = 'Iptc.Application2.City' tag = IptcTag(key, ['Barcelona']) self.metadata[key] = tag self.failUnless(key in self.metadata._tags['iptc']) self.failUnlessEqual(self.metadata._tags['iptc'][key], tag) key = 'Xmp.dc.description' tag = XmpTag(key, {'x-default': 'Sunset picture.'}) self.metadata[key] = tag self.failUnless(key in self.metadata._tags['xmp']) self.failUnlessEqual(self.metadata._tags['xmp'][key], tag) # Replace existing tags key = 'Exif.Photo.ExifVersion' tag = ExifTag(key, '0220') self.metadata[key] = tag self.failUnless(key in self.metadata._tags['exif']) self.failUnlessEqual(self.metadata._tags['exif'][key], tag) key = 'Iptc.Application2.Caption' tag = IptcTag(key, ['Sunset on Barcelona.']) self.metadata[key] = tag self.failUnless(key in self.metadata._tags['iptc']) self.failUnlessEqual(self.metadata._tags['iptc'][key], tag) key = 'Xmp.dc.subject' tag = XmpTag(key, ['sunset', 'Barcelona', 'beautiful', 'beach']) self.metadata[key] = tag self.failUnless(key in self.metadata._tags['xmp']) self.failUnlessEqual(self.metadata._tags['xmp'][key], tag)
def test_convert_to_python_undefined(self): # Valid values tag = IptcTag('Iptc.Application2.Preview') self.assertEqual(tag.type, 'Undefined') self.assertEqual(tag._convert_to_python('Some binary data.'), 'Some binary data.') self.assertEqual(tag._convert_to_python('�lj1�eEϟ�u����ᒻ;C(�SpI]���QI�}'), '�lj1�eEϟ�u����ᒻ;C(�SpI]���QI�}')
def test_convert_to_string_short(self): # Valid values tag = IptcTag('Iptc.Envelope.FileFormat') self.assertEqual(tag.type, 'Short') self.assertEqual(tag._convert_to_string(123), '123') self.assertEqual(tag._convert_to_string(-57), '-57') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, 'invalid') self.failUnlessRaises(IptcValueError, tag._convert_to_string, 3.14)
def test_convert_to_string_string(self): # Valid values tag = IptcTag('Iptc.Application2.Subject') self.assertEqual(tag.type, 'String') self.assertEqual(tag._convert_to_string('Some text'), b'Some text') self.assertEqual(tag._convert_to_string('Some text with exotic chàräctérʐ.'), b'Some text with exotic ch\xc3\xa0r\xc3\xa4ct\xc3\xa9r\xca\x90.') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, None)
def test_convert_to_string_undefined(self): # Valid values tag = IptcTag('Iptc.Application2.Preview') self.assertEqual(tag.type, 'Undefined') self.assertEqual(tag._convert_to_string('Some binary data.'), 'Some binary data.') self.assertEqual(tag._convert_to_string('�lj1�eEϟ�u����ᒻ;C(�SpI]���QI�}'), '�lj1�eEϟ�u����ᒻ;C(�SpI]���QI�}') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, None)
def test_convert_to_string_string(self): # Valid values tag = IptcTag('Iptc.Application2.Subject') self.assertEqual(tag.type, 'String') self.assertEqual(tag._convert_to_string(u'Some text'), 'Some text') self.assertEqual(tag._convert_to_string(u'Some text with exotic chàräctérʐ.'), 'Some text with exotic chàräctérʐ.') self.assertEqual(tag._convert_to_string('Some text with exotic chàräctérʐ.'), 'Some text with exotic chàräctérʐ.') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, None)
def _set_iptc_tag(self, key, tag_or_values): # Set an IPTC tag. If the tag already exists, its values are # overwritten. 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) tag._set_owner(self) self._tags['iptc'][tag.key] = tag if tag.key not in self.iptc_keys: self._keys['iptc'].append(tag.key)
def test_convert_to_python_short(self): # Valid values tag = IptcTag('Iptc.Envelope.FileFormat') self.assertEqual(tag.type, 'Short') self.assertEqual(tag._convert_to_python('23'), 23) self.assertEqual(tag._convert_to_python('+5628'), 5628) self.assertEqual(tag._convert_to_python('-4'), -4) # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_python, 'abc') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '5,64') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '47.0001') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '1E3')
def test_convert_to_string_time_with_real_timezones(self): if pytz is None: # Poor man’s test skipping. Starting with Python 2.7, decorators are # available to implement this in a cleaner fashion # (http://docs.python.org/library/unittest.html#unittest-skipping). print 'Install python-tz to run this test. Skipping.' return tag = IptcTag('Iptc.Envelope.TimeSent') self.assertEqual(tag.type, 'Time') t = pytz.timezone('UTC').localize(datetime.datetime(2011, 2, 2, 10, 52, 4)) self.assertEqual(tag._convert_to_string(t), '10:52:04+00:00') t = pytz.timezone('CET').localize(datetime.datetime(2011, 2, 2, 10, 52, 4)) self.assertEqual(tag._convert_to_string(t), '10:52:04+01:00')
def test_convert_to_python_date(self): # Valid values tag = IptcTag('Iptc.Envelope.DateSent') self.assertEqual(tag.type, 'Date') self.assertEqual(tag._convert_to_python('1999-10-13'), datetime.date(1999, 10, 13)) # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_python, 'invalid') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '11/10/1983') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '-1000') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '2009-02') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '2009-10-32') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '2009-02-24T22:12:54')
def test_convert_to_string_date(self): # Valid values tag = IptcTag('Iptc.Envelope.DateSent') self.assertEqual(tag.type, 'Date') self.assertEqual(tag._convert_to_string(datetime.date(2009, 2, 4)), '2009-02-04') self.assertEqual(tag._convert_to_string(datetime.datetime(1999, 10, 13)), '1999-10-13') self.assertEqual(tag._convert_to_string(datetime.datetime(2009, 2, 4)), '2009-02-04') self.assertEqual(tag._convert_to_string(datetime.datetime(2009, 2, 4, 10, 52, 37)), '2009-02-04') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, 'invalid') self.failUnlessRaises(IptcValueError, tag._convert_to_string, None)
def _set_iptc_tag(self, key, tag_or_values): """Set an IPTC tag. If the tag already exists, its value is overwritten. Args: key -- the IPTC key tag_or_value -- an IptcTag instance or the value of the data """ 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) tag._set_owner(self) self._tags['iptc'][tag.key] = tag if tag.key not in self.iptc_keys: self._keys['iptc'].append(tag.key)
def test_convert_to_python_time(self): # Valid values tag = IptcTag('Iptc.Envelope.TimeSent') self.assertEqual(tag.type, 'Time') self.assertEqual(tag._convert_to_python('05:03:54+00:00'), datetime.time(5, 3, 54, tzinfo=FixedOffset())) self.assertEqual(tag._convert_to_python('05:03:54+06:00'), datetime.time(5, 3, 54, tzinfo=FixedOffset('+', 6, 0))) self.assertEqual(tag._convert_to_python('05:03:54-10:30'), datetime.time(5, 3, 54, tzinfo=FixedOffset('-', 10, 30))) # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_python, 'invalid') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '23:12:42') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '25:12:42+00:00') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '21:77:42+00:00') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '21:12:98+00:00') self.failUnlessRaises(IptcValueError, tag._convert_to_python, '081242+0000')
def test_set_iptc_tag_overwrite(metadata_ro): m = metadata_ro.metadata m.read() assert m._tags['iptc'] == {} # Overwrite an existing tag tag = IptcTag('Iptc.Application2.Caption', ['A picture.']) m._set_iptc_tag(tag.key, tag) assert m._tags['iptc'] == {tag.key: tag} assert tag.key in m._image._iptcKeys() assert m._image._getIptcTag(tag.key)._getRawValues() == [b'A picture.']
def _get_iptc_tag(self, key): # Return the IPTC tag for the given key. # Throw a KeyError if the tag doesn't exist. try: return self._tags['iptc'][key] except KeyError: _tag = self._image._getIptcTag(key) tag = IptcTag._from_existing_tag(_tag) self._tags['iptc'][key] = tag return tag
def test_set_iptc_tag_overwrite(self): self.metadata.read() self.assertEqual(self.metadata._tags['iptc'], {}) # Overwrite an existing tag tag = IptcTag('Iptc.Application2.Caption', ['A picture.']) self.metadata._set_iptc_tag(tag.key, tag) 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(), ['A picture.'])
def test_set_iptc_tag_create(metadata_ro): m = metadata_ro.metadata m.read() assert m._tags['iptc'] == {} # Create a new tag tag = IptcTag('Iptc.Application2.Writer', ['Nobody']) assert tag.key not in m.iptc_keys m._set_iptc_tag(tag.key, tag) assert tag.key in m.iptc_keys assert m._tags['iptc'] == {tag.key: tag} assert tag.key in m._image._iptcKeys() assert m._image._getIptcTag(tag.key)._getRawValues() == [b'Nobody']
def test_set_iptc_tag_overwrite_already_cached(metadata_ro): m = metadata_ro.metadata m.read() assert m._tags['iptc'] == {} # Overwrite an existing tag already cached key = 'Iptc.Application2.Caption' tag = m._get_iptc_tag(key) assert m._tags['iptc'][key] == tag new_tag = IptcTag(key, ['A picture.']) m._set_iptc_tag(key, new_tag) assert m._tags['iptc'] == {key: new_tag} assert key in m._image._iptcKeys() assert m._image._getIptcTag(key)._getRawValues() == [b'A picture.']
def test_set_iptc_tag_create(self): self.metadata.read() self.assertEqual(self.metadata._tags['iptc'], {}) # Create a new tag tag = IptcTag('Iptc.Application2.Writer', ['Nobody']) self.assert_(tag.key not in self.metadata.iptc_keys) self.metadata._set_iptc_tag(tag.key, tag) self.assert_(tag.key in self.metadata.iptc_keys) 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(), ['Nobody'])
def test_set_iptc_tag_overwrite_already_cached(self): self.metadata.read() self.assertEqual(self.metadata._tags['iptc'], {}) # Overwrite an existing tag already cached key = 'Iptc.Application2.Caption' tag = self.metadata._get_iptc_tag(key) self.assertEqual(self.metadata._tags['iptc'][key], tag) new_tag = IptcTag(key, ['A picture.']) self.metadata._set_iptc_tag(key, new_tag) 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(), ['A picture.'])
def test_pickle_iptc_tag(self): tags = [] tags.append(IptcTag('Iptc.Envelope.FileFormat', [23])) tags.append(IptcTag('Iptc.Application2.Subject', ['foo', 'bar', 'baz'])) tags.append(IptcTag('Iptc.Envelope.DateSent', [datetime.date.today()])) tags.append(IptcTag('Iptc.Envelope.TimeSent', [datetime.time(23, 37, 4, tzinfo=FixedOffset('+', 6, 0))])) tags.append(IptcTag('Iptc.Application2.Preview', ['01001101'])) for tag in tags: s = pickle.dumps(tag) t = pickle.loads(s) self.assert_(isinstance(t, IptcTag)) self.assertEqual(t.key, tag.key) self.assertEqual(t.type, tag.type) self.assertEqual(t.name, tag.name) self.assertEqual(t.title, tag.title) self.assertEqual(t.description, tag.description) self.assertEqual(t.photoshop_name, tag.photoshop_name) self.assertEqual(t.repeatable, tag.repeatable) self.assertEqual(t.record_name, tag.record_name) self.assertEqual(t.record_description, tag.record_description) self.assertEqual(t.raw_value, tag.raw_value) self.assertEqual(t.value, tag.value)
def test_convert_to_string_date(self): # Valid values tag = IptcTag('Iptc.Envelope.DateSent') self.assertEqual(tag.type, 'Date') self.assertEqual(tag._convert_to_string(datetime.date(2009, 2, 4)), '2009-02-04') self.assertEqual(tag._convert_to_string(datetime.date(1899, 12, 31)), '1899-12-31') self.assertEqual(tag._convert_to_string(datetime.datetime(1999, 10, 13)), '1999-10-13') self.assertEqual(tag._convert_to_string(datetime.datetime(2009, 2, 4)), '2009-02-04') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31)), '1899-12-31') self.assertEqual(tag._convert_to_string(datetime.datetime(2009, 2, 4, 10, 52, 37)), '2009-02-04') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31, 23, 59, 59)), '1899-12-31') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, 'invalid') self.failUnlessRaises(IptcValueError, tag._convert_to_string, None)
def test_mutablemapping(self): self._set_up_clean() self.clean.read() self.assertEqual(len(self.clean), 0) self.assertTrue('Exif.Image.DateTimeOriginal' not in self.clean) key = 'Exif.Image.DateTimeOriginal' correctDate = datetime.datetime(2007, 3, 11) incorrectDate = datetime.datetime(2009, 3, 25) tag_date = ExifTag(key, correctDate) false_tag_date = ExifTag(key, incorrectDate) self.clean[key] = tag_date self.assertEqual(len(self.clean), 1) self.assertTrue('Exif.Image.DateTimeOriginal' in self.clean) self.assertEqual( self.clean.get('Exif.Image.DateTimeOriginal', false_tag_date), tag_date) self.assertEqual(self.clean.get('Exif.Image.DateTime', tag_date), tag_date) key = 'Exif.Photo.UserComment' tag = ExifTag(key, 'UserComment') self.clean[key] = tag key = 'Iptc.Application2.Caption' tag = IptcTag(key, ['Caption']) self.clean[key] = tag key = 'Xmp.dc.subject' tag = XmpTag(key, ['subject', 'values']) self.clean[key] = tag self.assertTrue('Exif.Photo.UserComment' in self.clean) self.assertTrue('Iptc.Application2.Caption' in self.clean) self.assertTrue('Xmp.dc.subject' in self.clean) self.clean.clear() self.assertEqual(len(self.clean), 0) self.assertTrue('Exif.Photo.UserComment' not in self.clean) self.assertTrue('Iptc.Application2.Caption' not in self.clean) self.assertTrue('Xmp.dc.subject' not in self.clean)
def test_mutablemapping(): clean = ImageMetadata.from_buffer(EMPTY_JPG_DATA) clean.read() assert len(clean) == 0 assert 'Exif.Image.DateTimeOriginal' not in clean key = 'Exif.Image.DateTimeOriginal' correctDate = datetime.datetime(2007, 3, 11) incorrectDate = datetime.datetime(2009, 3, 25) tag_date = ExifTag(key, correctDate) false_tag_date = ExifTag(key, incorrectDate) clean[key] = tag_date assert len(clean) == 1 assert 'Exif.Image.DateTimeOriginal' in clean assert clean.get('Exif.Image.DateTimeOriginal', false_tag_date) == tag_date assert clean.get('Exif.Image.DateTime', tag_date) == tag_date key = 'Exif.Photo.UserComment' tag = ExifTag(key, 'UserComment') clean[key] = tag key = 'Iptc.Application2.Caption' tag = IptcTag(key, ['Caption']) clean[key] = tag key = 'Xmp.dc.subject' tag = XmpTag(key, ['subject', 'values']) clean[key] = tag assert 'Exif.Photo.UserComment' in clean assert 'Iptc.Application2.Caption' in clean assert 'Xmp.dc.subject' in clean clean.clear() assert len(clean) == 0 assert 'Exif.Photo.UserComment' not in clean assert 'Iptc.Application2.Caption' not in clean assert 'Xmp.dc.subject' not in clean
def test_convert_to_string_time(self): # Valid values tag = IptcTag('Iptc.Envelope.TimeSent') self.assertEqual(tag.type, 'Time') self.assertEqual(tag._convert_to_string(datetime.time(10, 52, 4)), '10:52:04+00:00') self.assertEqual(tag._convert_to_string(datetime.time(10, 52, 4, 574)), '10:52:04+00:00') self.assertEqual(tag._convert_to_string(datetime.time(10, 52, 4, tzinfo=FixedOffset())), '10:52:04+00:00') self.assertEqual(tag._convert_to_string(datetime.time(10, 52, 4, tzinfo=FixedOffset('+', 5, 30))), '10:52:04+05:30') self.assertEqual(tag._convert_to_string(datetime.time(10, 52, 4, tzinfo=FixedOffset('-', 4, 0))), '10:52:04-04:00') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31, 23, 59, 59)), '23:59:59+00:00') self.assertEqual(tag._convert_to_string(datetime.datetime(2007, 2, 7, 10, 52, 4)), '10:52:04+00:00') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31, 23, 59, 59, 999)), '23:59:59+00:00') self.assertEqual(tag._convert_to_string(datetime.datetime(2007, 2, 7, 10, 52, 4, 478)), '10:52:04+00:00') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31, 23, 59, 59, tzinfo=FixedOffset())), '23:59:59+00:00') self.assertEqual(tag._convert_to_string(datetime.datetime(2007, 2, 7, 10, 52, 4, tzinfo=FixedOffset())), '10:52:04+00:00') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31, 23, 59, 59, tzinfo=FixedOffset('+', 5, 30))), '23:59:59+05:30') self.assertEqual(tag._convert_to_string(datetime.datetime(2007, 2, 7, 10, 52, 4, tzinfo=FixedOffset('+', 5, 30))), '10:52:04+05:30') self.assertEqual(tag._convert_to_string(datetime.datetime(1899, 12, 31, 23, 59, 59, tzinfo=FixedOffset('-', 4, 0))), '23:59:59-04:00') self.assertEqual(tag._convert_to_string(datetime.datetime(2007, 2, 7, 10, 52, 4, tzinfo=FixedOffset('-', 4, 0))), '10:52:04-04:00') # Invalid values self.failUnlessRaises(IptcValueError, tag._convert_to_string, 'invalid')
def test_set_value(self): tag = IptcTag('Iptc.Application2.City', ['Seattle']) old_value = tag.value tag.value = ['Barcelona'] self.failIfEqual(tag.value, old_value)
def test_set_single_value_raises(self): tag = IptcTag('Iptc.Application2.City', ['Seattle']) self.failUnlessRaises(TypeError, setattr, tag, 'value', 'Barcelona')
def test_set_raw_value_invalid(self): tag = IptcTag('Iptc.Envelope.DateSent') value = ['foo'] self.failUnlessRaises(ValueError, setattr, tag, 'raw_value', value)
def test_set_value_non_repeatable(self): tag = IptcTag('Iptc.Application2.ReleaseDate') value = [datetime.date.today(), datetime.date.today()] self.failUnlessRaises(KeyError, setattr, tag, 'value', value)