Skip to content

Commit 483df3f

Browse files
Update tests to work on Python 3.14
The refcount checks were previously disabled as Python 3.14 has refcount optimisation that changes the absolute values. Now uses relative values which work on all Python versions.
1 parent b560cc7 commit 483df3f

6 files changed

Lines changed: 85 additions & 96 deletions

File tree

tests/test_basicio.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## python-exiv2 - Python interface to libexiv2
22
## http://github.com/jim-easterbrook/python-exiv2
3-
## Copyright (C) 2023-25 Jim Easterbrook jim@jim-easterbrook.me.uk
3+
## Copyright (C) 2023-26 Jim Easterbrook jim@jim-easterbrook.me.uk
44
##
55
## This program is free software: you can redistribute it and/or
66
## modify it under the terms of the GNU General Public License as
@@ -224,8 +224,6 @@ def test_MemIo(self):
224224
with self.assertWarns(DeprecationWarning):
225225
self.assertEqual(memoryview(io), self.data + b'+fred+jim')
226226

227-
@unittest.skipIf(sys.version_info >= (3, 14),
228-
'cannot test optimised ref counts')
229227
def test_ref_counts(self):
230228
# MemIo keeps a reference to the data buffer
231229
count = sys.getrefcount(self.data)

tests/test_exif.py

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## python-exiv2 - Python interface to libexiv2
22
## http://github.com/jim-easterbrook/python-exiv2
3-
## Copyright (C) 2023-25 Jim Easterbrook jim@jim-easterbrook.me.uk
3+
## Copyright (C) 2023-26 Jim Easterbrook jim@jim-easterbrook.me.uk
44
##
55
## This program is free software: you can redistribute it and/or
66
## modify it under the terms of the GNU General Public License as
@@ -310,61 +310,58 @@ def test_pointers(self):
310310
self.assertEqual(datum_pointer, datum)
311311
self.assertEqual(datum_pointer, datum_iter)
312312

313-
@unittest.skipIf(sys.version_info >= (3, 14),
314-
'cannot test optimised ref counts')
315313
def test_ref_counts(self):
316314
self.image.readMetadata()
317315
# exifData keeps a reference to image
318-
self.assertEqual(sys.getrefcount(self.image), 2)
316+
rc_1 = sys.getrefcount(self.image)
319317
data = self.image.exifData()
320-
self.assertEqual(sys.getrefcount(self.image), 3)
318+
self.assertEqual(sys.getrefcount(self.image), rc_1 + 1)
321319
# thumbnail keeps a reference to exifData
322-
self.assertEqual(sys.getrefcount(data), 2)
320+
rc_2 = sys.getrefcount(data)
323321
thumb = exiv2.ExifThumb(data)
324-
self.assertEqual(sys.getrefcount(data), 3)
322+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
325323
del thumb
326-
self.assertEqual(sys.getrefcount(data), 2)
324+
self.assertEqual(sys.getrefcount(data), rc_2)
327325
# iterator keeps a reference to data
328-
self.assertEqual(sys.getrefcount(data), 2)
329326
b = data.begin()
330-
self.assertEqual(sys.getrefcount(data), 3)
327+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
331328
e = data.end()
332-
self.assertEqual(sys.getrefcount(data), 4)
329+
self.assertEqual(sys.getrefcount(data), rc_2 + 2)
333330
i = iter(data)
334-
self.assertEqual(sys.getrefcount(data), 5)
331+
self.assertEqual(sys.getrefcount(data), rc_2 + 3)
335332
k = data.findKey(exiv2.ExifKey('Exif.Photo.FocalLength'))
336-
self.assertEqual(sys.getrefcount(data), 6)
333+
self.assertEqual(sys.getrefcount(data), rc_2 + 4)
337334
k2 = data.erase(k)
338335
with self.assertRaises(RuntimeError):
339336
k.key()
340-
self.assertEqual(sys.getrefcount(data), 7)
337+
self.assertEqual(sys.getrefcount(data), rc_2 + 5)
341338
del b, e, i, k, k2
342-
self.assertEqual(sys.getrefcount(data), 2)
339+
self.assertEqual(sys.getrefcount(data), rc_2)
343340
# iterator of an iterator keeps a reference to iterator
344341
b = data.begin()
345-
self.assertEqual(sys.getrefcount(b), 2)
342+
rc_2 = sys.getrefcount(b)
346343
i = iter(b)
347-
self.assertEqual(sys.getrefcount(b), 3)
344+
self.assertEqual(sys.getrefcount(b), rc_2 + 1)
348345
del i
349-
self.assertEqual(sys.getrefcount(b), 2)
346+
self.assertEqual(sys.getrefcount(b), rc_2)
350347
# iterator value keeps a reference to iterator
351348
v = b.value()
352-
self.assertEqual(sys.getrefcount(b), 3)
349+
self.assertEqual(sys.getrefcount(b), rc_2 + 1)
353350
del v
354-
self.assertEqual(sys.getrefcount(b), 2)
351+
self.assertEqual(sys.getrefcount(b), rc_2)
355352
del b
356353
# datum keeps a reference to data
357-
self.assertEqual(sys.getrefcount(data), 2)
354+
rc_2 = sys.getrefcount(data)
358355
datum = data['Exif.Image.ImageDescription']
359-
self.assertEqual(sys.getrefcount(data), 3)
356+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
360357
# value keeps a reference to datum
361-
self.assertEqual(sys.getrefcount(datum), 2)
358+
rc_3 = sys.getrefcount(datum)
362359
v = datum.value()
363-
self.assertEqual(sys.getrefcount(datum), 3)
360+
self.assertEqual(sys.getrefcount(datum), rc_3 + 1)
364361
del v
365-
self.assertEqual(sys.getrefcount(datum), 2)
362+
self.assertEqual(sys.getrefcount(datum), rc_3)
366363
del datum
367-
self.assertEqual(sys.getrefcount(data), 2)
364+
self.assertEqual(sys.getrefcount(data), rc_2)
368365
del data
369366
self.assertEqual(sys.getrefcount(self.image), 2)
370367

tests/test_image.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## python-exiv2 - Python interface to libexiv2
22
## http://github.com/jim-easterbrook/python-exiv2
3-
## Copyright (C) 2023-25 Jim Easterbrook jim@jim-easterbrook.me.uk
3+
## Copyright (C) 2023-26 Jim Easterbrook jim@jim-easterbrook.me.uk
44
##
55
## This program is free software: you can redistribute it and/or
66
## modify it under the terms of the GNU General Public License as
@@ -187,34 +187,32 @@ def test_ImageFactory(self):
187187
exiv2.ImageType, exiv2.ImageType.jpeg)
188188
self.assertIsInstance(factory.open(self.image_path), exiv2.Image)
189189

190-
@unittest.skipIf(sys.version_info >= (3, 14),
191-
'cannot test optimised ref counts')
192190
def test_ref_counts(self):
193191
# opening from data keeps reference to buffer
194-
self.assertEqual(sys.getrefcount(self.image_data), 2)
192+
count = sys.getrefcount(self.image_data)
195193
image = exiv2.ImageFactory.open(self.image_data)
196-
self.assertEqual(sys.getrefcount(self.image_data), 3)
194+
self.assertEqual(sys.getrefcount(self.image_data), count + 1)
197195
# writeMetadata releases buffer
198196
image.writeMetadata()
199-
self.assertEqual(sys.getrefcount(self.image_data), 2)
197+
self.assertEqual(sys.getrefcount(self.image_data), count)
200198
# getting metadata and buffers keeps reference to image
201199
image = exiv2.ImageFactory.open(self.image_data)
202200
image.readMetadata()
203-
self.assertEqual(sys.getrefcount(image), 2)
201+
count = sys.getrefcount(image)
204202
data = [image.exifData()]
205-
self.assertEqual(sys.getrefcount(image), 3)
203+
self.assertEqual(sys.getrefcount(image), count + 1)
206204
data.append(image.iptcData())
207-
self.assertEqual(sys.getrefcount(image), 4)
205+
self.assertEqual(sys.getrefcount(image), count + 2)
208206
data.append(image.xmpData())
209-
self.assertEqual(sys.getrefcount(image), 5)
207+
self.assertEqual(sys.getrefcount(image), count + 3)
210208
data.append(image.iccProfile())
211-
self.assertEqual(sys.getrefcount(image), 6)
209+
self.assertEqual(sys.getrefcount(image), count + 4)
212210
data.append(image.io())
213-
self.assertEqual(sys.getrefcount(image), 7)
211+
self.assertEqual(sys.getrefcount(image), count + 5)
214212
data.append(image.data())
215-
self.assertEqual(sys.getrefcount(image), 8)
213+
self.assertEqual(sys.getrefcount(image), count + 6)
216214
del data
217-
self.assertEqual(sys.getrefcount(image), 2)
215+
self.assertEqual(sys.getrefcount(image), count)
218216

219217

220218
if __name__ == '__main__':

tests/test_iptc.py

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## python-exiv2 - Python interface to libexiv2
22
## http://github.com/jim-easterbrook/python-exiv2
3-
## Copyright (C) 2023-25 Jim Easterbrook jim@jim-easterbrook.me.uk
3+
## Copyright (C) 2023-26 Jim Easterbrook jim@jim-easterbrook.me.uk
44
##
55
## This program is free software: you can redistribute it and/or
66
## modify it under the terms of the GNU General Public License as
@@ -204,57 +204,55 @@ def test_IptcDatum(self):
204204
del datum2
205205
self._test_datum(datum)
206206

207-
@unittest.skipIf(sys.version_info >= (3, 14),
208-
'cannot test optimised ref counts')
209207
def test_ref_counts(self):
210208
self.image.readMetadata()
211209
# iptcData keeps a reference to image
212-
self.assertEqual(sys.getrefcount(self.image), 2)
210+
rc_1 = sys.getrefcount(self.image)
213211
data = self.image.iptcData()
214-
self.assertEqual(sys.getrefcount(self.image), 3)
212+
self.assertEqual(sys.getrefcount(self.image), rc_1 + 1)
215213
# iterator keeps a reference to data
216-
self.assertEqual(sys.getrefcount(data), 2)
214+
rc_2 = sys.getrefcount(data)
217215
b = data.begin()
218-
self.assertEqual(sys.getrefcount(data), 3)
216+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
219217
e = data.end()
220-
self.assertEqual(sys.getrefcount(data), 4)
218+
self.assertEqual(sys.getrefcount(data), rc_2 + 2)
221219
i = iter(data)
222-
self.assertEqual(sys.getrefcount(data), 5)
220+
self.assertEqual(sys.getrefcount(data), rc_2 + 3)
223221
k = data.findKey(exiv2.IptcKey('Iptc.Application2.Caption'))
224-
self.assertEqual(sys.getrefcount(data), 6)
222+
self.assertEqual(sys.getrefcount(data), rc_2 + 4)
225223
k2 = data.erase(k)
226224
with self.assertRaises(RuntimeError):
227225
k.key()
228-
self.assertEqual(sys.getrefcount(data), 7)
226+
self.assertEqual(sys.getrefcount(data), rc_2 + 5)
229227
del b, e, i, k, k2
230-
self.assertEqual(sys.getrefcount(data), 2)
228+
self.assertEqual(sys.getrefcount(data), rc_2)
231229
# iterator of an iterator keeps a reference to iterator
232230
b = data.begin()
233-
self.assertEqual(sys.getrefcount(b), 2)
231+
rc_2 = sys.getrefcount(b)
234232
i = iter(b)
235-
self.assertEqual(sys.getrefcount(b), 3)
233+
self.assertEqual(sys.getrefcount(b), rc_2 + 1)
236234
del i
237-
self.assertEqual(sys.getrefcount(b), 2)
235+
self.assertEqual(sys.getrefcount(b), rc_2)
238236
# iterator value keeps a reference to iterator
239237
v = b.value()
240-
self.assertEqual(sys.getrefcount(b), 3)
238+
self.assertEqual(sys.getrefcount(b), rc_2 + 1)
241239
del v
242-
self.assertEqual(sys.getrefcount(b), 2)
240+
self.assertEqual(sys.getrefcount(b), rc_2)
243241
del b
244242
# datum keeps a reference to data
245-
self.assertEqual(sys.getrefcount(data), 2)
243+
rc_2 = sys.getrefcount(data)
246244
datum = data['Iptc.Application2.Contact']
247-
self.assertEqual(sys.getrefcount(data), 3)
245+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
248246
# value keeps a reference to datum
249-
self.assertEqual(sys.getrefcount(datum), 2)
247+
rc_3 = sys.getrefcount(datum)
250248
v = datum.value()
251-
self.assertEqual(sys.getrefcount(datum), 3)
249+
self.assertEqual(sys.getrefcount(datum), rc_3 + 1)
252250
del v
253-
self.assertEqual(sys.getrefcount(datum), 2)
251+
self.assertEqual(sys.getrefcount(datum), rc_3)
254252
del datum
255-
self.assertEqual(sys.getrefcount(data), 2)
253+
self.assertEqual(sys.getrefcount(data), rc_2)
256254
del data
257-
self.assertEqual(sys.getrefcount(self.image), 2)
255+
self.assertEqual(sys.getrefcount(self.image), rc_1)
258256

259257

260258
if __name__ == '__main__':

tests/test_preview.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## python-exiv2 - Python interface to libexiv2
22
## http://github.com/jim-easterbrook/python-exiv2
3-
## Copyright (C) 2022-25 Jim Easterbrook jim@jim-easterbrook.me.uk
3+
## Copyright (C) 2022-26 Jim Easterbrook jim@jim-easterbrook.me.uk
44
##
55
## This program is free software: you can redistribute it and/or
66
## modify it under the terms of the GNU General Public License as
@@ -118,13 +118,13 @@ def test_PreviewProperties(self):
118118
with self.assertRaises(TypeError):
119119
properties['fred'] = 123
120120

121-
@unittest.skipIf(sys.version_info >= (3, 14),
122-
'cannot test optimised ref counts')
123121
def test_ref_counts(self):
124122
# manager keeps reference to image
125-
self.assertEqual(sys.getrefcount(self.image), 2)
123+
count = sys.getrefcount(self.image)
126124
manager = exiv2.PreviewManager(self.image)
127-
self.assertEqual(sys.getrefcount(self.image), 3)
125+
self.assertEqual(sys.getrefcount(self.image), count + 1)
126+
del manager
127+
self.assertEqual(sys.getrefcount(self.image), count)
128128

129129

130130
if __name__ == '__main__':

tests/test_xmp.py

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## python-exiv2 - Python interface to libexiv2
22
## http://github.com/jim-easterbrook/python-exiv2
3-
## Copyright (C) 2023-25 Jim Easterbrook jim@jim-easterbrook.me.uk
3+
## Copyright (C) 2023-26 Jim Easterbrook jim@jim-easterbrook.me.uk
44
##
55
## This program is free software: you can redistribute it and/or
66
## modify it under the terms of the GNU General Public License as
@@ -246,57 +246,55 @@ def test_pointers(self):
246246
self.assertEqual(datum_pointer, datum)
247247
self.assertEqual(datum_pointer, datum_iter)
248248

249-
@unittest.skipIf(sys.version_info >= (3, 14),
250-
'cannot test optimised ref counts')
251249
def test_ref_counts(self):
252250
self.image.readMetadata()
253251
# xmpData keeps a reference to image
254-
self.assertEqual(sys.getrefcount(self.image), 2)
252+
rc_1 = sys.getrefcount(self.image)
255253
data = self.image.xmpData()
256-
self.assertEqual(sys.getrefcount(self.image), 3)
254+
self.assertEqual(sys.getrefcount(self.image), rc_1 + 1)
257255
# iterator keeps a reference to data
258-
self.assertEqual(sys.getrefcount(data), 2)
256+
rc_2 = sys.getrefcount(data)
259257
b = data.begin()
260-
self.assertEqual(sys.getrefcount(data), 3)
258+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
261259
e = data.end()
262-
self.assertEqual(sys.getrefcount(data), 4)
260+
self.assertEqual(sys.getrefcount(data), rc_2 + 2)
263261
i = iter(data)
264-
self.assertEqual(sys.getrefcount(data), 5)
262+
self.assertEqual(sys.getrefcount(data), rc_2 + 3)
265263
k = data.findKey(exiv2.XmpKey('Xmp.xmp.Rating'))
266-
self.assertEqual(sys.getrefcount(data), 6)
264+
self.assertEqual(sys.getrefcount(data), rc_2 + 4)
267265
k2 = data.erase(k)
268266
with self.assertRaises(RuntimeError):
269267
k.key()
270-
self.assertEqual(sys.getrefcount(data), 7)
268+
self.assertEqual(sys.getrefcount(data), rc_2 + 5)
271269
del b, e, i, k, k2
272-
self.assertEqual(sys.getrefcount(data), 2)
270+
self.assertEqual(sys.getrefcount(data), rc_2)
273271
# iterator of an iterator keeps a reference to iterator
274272
b = data.begin()
275-
self.assertEqual(sys.getrefcount(b), 2)
273+
rc_3 = sys.getrefcount(b)
276274
i = iter(b)
277-
self.assertEqual(sys.getrefcount(b), 3)
275+
self.assertEqual(sys.getrefcount(b), rc_3 + 1)
278276
del i
279-
self.assertEqual(sys.getrefcount(b), 2)
277+
self.assertEqual(sys.getrefcount(b), rc_3)
280278
# iterator value keeps a reference to iterator
281279
v = b.value()
282-
self.assertEqual(sys.getrefcount(b), 3)
280+
self.assertEqual(sys.getrefcount(b), rc_3 + 1)
283281
del v
284-
self.assertEqual(sys.getrefcount(b), 2)
282+
self.assertEqual(sys.getrefcount(b), rc_3)
285283
del b
286284
# datum keeps a reference to data
287-
self.assertEqual(sys.getrefcount(data), 2)
285+
rc_2 = sys.getrefcount(data)
288286
datum = data['Xmp.dc.description']
289-
self.assertEqual(sys.getrefcount(data), 3)
287+
self.assertEqual(sys.getrefcount(data), rc_2 + 1)
290288
# value keeps a reference to datum
291-
self.assertEqual(sys.getrefcount(datum), 2)
289+
rc_3 = sys.getrefcount(datum)
292290
v = datum.value()
293-
self.assertEqual(sys.getrefcount(datum), 3)
291+
self.assertEqual(sys.getrefcount(datum), rc_3 + 1)
294292
del v
295-
self.assertEqual(sys.getrefcount(datum), 2)
293+
self.assertEqual(sys.getrefcount(datum), rc_3)
296294
del datum
297-
self.assertEqual(sys.getrefcount(data), 2)
295+
self.assertEqual(sys.getrefcount(data), rc_2)
298296
del data
299-
self.assertEqual(sys.getrefcount(self.image), 2)
297+
self.assertEqual(sys.getrefcount(self.image), rc_1)
300298

301299

302300
if __name__ == '__main__':

0 commit comments

Comments
 (0)