Skip to content

Commit 09ac20c

Browse files
Merge pull request #53 from jim-easterbrook/devel
Devel
2 parents 4769e2b + 5d803d6 commit 09ac20c

File tree

136 files changed

+70696
-61116
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+70696
-61116
lines changed

.github/workflows/test-interface.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ jobs:
3131
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
3232
os: [ubuntu-latest]
3333
include:
34-
- python-version: '3.6'
35-
os: ubuntu-20.04
3634
- python-version: '3.7'
3735
os: ubuntu-22.04
3836
runs-on: ${{ matrix.os }}

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/build
1+
/build*
22
/doc
33
/dist
44
/src/doc/api

CHANGELOG.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,39 @@ You should have received a copy of the GNU General Public License
1616
along with this program. If not, see
1717
<http://www.gnu.org/licenses/>.
1818

19+
Changes in v0.18.0:
20+
1/ Removed features deprecated in v0.13.0:
21+
Value (and derived types) copy constructors
22+
Single value (such as DateValue) index methods
23+
DataBuf indexing.
24+
2/ Deprecated many BasicIo methods (read, write, seek, etc.) that should not
25+
be needed in Python scripts. Please let me know if this is a problem.
26+
3/ Deprecated copy, write, and read(buffer) methods of Value (and
27+
subclasses) that should not be needed in Python scripts. Please let me
28+
know if this is a problem.
29+
4/ Deprecated copy and write methods of Metadatum (and subclasses) that
30+
should not be needed in Python scripts. Please let me know if this is a
31+
problem.
32+
5/ Deprecated 'buffer interface' to BasicIo, DataBuf, and PreviewImage. They
33+
all have 'data()' to get their contents.
34+
6/ Added binary wheels for Linux on arm64.
35+
7/ Exiv2 struct member names with a trailing underscore have more Pythonic
36+
aliases without the underscore.
37+
8/ Add data() method to exiv2.PreviewImage, deprecate pData() method.
38+
9/ Add data() method to exiv2.Image. This will replace using Image.io().
39+
10/ Add data() method to exiv2.DataValue.
40+
11/ BasicIo.read (& readOrThrow) now extract count from the buffer size.
41+
12/ Invalidate data iterators if data is deleted. (Requires swig >= 4.4)
42+
13/ Deprecated iteration of exiv2 "data" structure types.
43+
14/ API CHANGE: exiv2.LogMsg.pythonHandler is replaced by exiv2.pythonHandler
44+
45+
Changes in v0.17.5:
46+
1/ Binary wheels incorporate libexiv2 v0.28.7.
47+
48+
Changes in v0.17.4: (yanked)
49+
1/ Binary wheels incorporate libexiv2 v0.28.6.
50+
2/ Windows binary wheels do not have localisation.
51+
1952
Changes in v0.17.3:
2053
1/ Binary wheels incorporate libexiv2 v0.28.5.
2154

INSTALL.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Use installed libexiv2
2121

2222
In the example above, pip_ installs a "binary wheel_".
2323
This is pre-compiled and includes a copy of the libexiv2_ library, which makes installation quick and easy.
24-
Wheels for `python-exiv2`_ are available for Windows, Linux, and MacOS with Python versions from 3.6 to 3.12.
24+
Wheels for `python-exiv2`_ are available for Windows, Linux, and MacOS with Python versions from 3.6 to 3.13.
2525

2626
If your computer already has libexiv2_ installed (typically by your operating system's "package manager") then pip_ might be able to compile `python-exiv2`_ to use it.
2727
First you need to check what version of python-exiv2 you have::

README.rst

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
python-exiv2 v\ 0.17.3
1+
python-exiv2 v\ 0.18.0
22
======================
33

44
python-exiv2 is a low level interface (or binding) to the exiv2_ C++ library.
@@ -47,15 +47,17 @@ Please see `USAGE.rst`_ for more help with using the Python interface to libexiv
4747
Transition to libexiv2 v0.28.x
4848
------------------------------
4949
50-
Before python-exiv2 v0.16 the "binary wheels" available from PyPI_ incorporated libexiv2 v0.27.7 or earlier.
51-
Binary wheels for python-exiv2 v0.16.3 incorporate libexiv2 v0.28.2, and those for python-exiv2 v0.16.2 incorporate libexiv2 v0.27.7.
52-
Binary wheels for python-exiv2 v0.17.0 incorporate libexiv2 v0.28.3.
53-
If your software is currently incompatible with libexiv2 v0.28.x you can use the older version of libexiv2 by explicitly installing python-exiv2 v0.16.2::
50+
Since python-exiv2 v0.16.3 the "binary wheels" available from PyPI_ incorporate libexiv2 v0.28.2 or later.
51+
If your software is currently incompatible with libexiv2 v0.28.x you can use an older version of libexiv2 by explicitly installing python-exiv2 v0.16.2::
5452
55-
$ pip install --user exiv2==0.16.2
53+
$ pip install --user exiv2==0.16.2 --only-binary :all:
54+
55+
Alternatively, if you have libexiv2 v0.27.x and its "development headers" installed on your computer, you can install python-exiv2 from source using your system libexiv2::
56+
57+
$ pip install --user exiv2 --no-binary :all:
5658
5759
There are some changes in the libexiv2 API between v0.27.7 and v0.28.x.
58-
Future versions of python-exiv2 will all incorporate libexiv2 v0.28.x, so please update your software to use the changed API.
60+
Eventually python-exiv2 will no longer support libexiv2 v0.27.x, so please update your software to use the changed API.
5961
6062
Documentation
6163
-------------
@@ -97,6 +99,7 @@ Installation
9799

98100
Python "binary wheels" are available for Windows, Linux, and MacOS.
99101
These include the libexiv2 library and should not need any other software to be installed.
102+
(Although on Windows you might need to update your `MSVC redistributable`_.)
100103
They can be installed with Python's pip_ package.
101104
For example, on Windows::
102105

@@ -119,6 +122,8 @@ Please email [email protected] if you find any problems (or solutions!).
119122
.. _gexiv2: https://wiki.gnome.org/Projects/gexiv2
120123
.. _GitHub: https://github.com/jim-easterbrook/python-exiv2
121124
.. _libexiv2: https://www.exiv2.org/doc/index.html
125+
.. _MSVC redistributable:
126+
https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version
122127
.. _pip: https://pip.pypa.io/
123128
.. _pyexiv2 (new): https://github.com/LeoHsiao1/pyexiv2
124129
.. _pyexiv2 (old): https://launchpad.net/pyexiv2

USAGE.rst

Lines changed: 53 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ libexiv2 library version
1313
------------------------
1414

1515
Python-exiv2 can be used with any version of libexiv2 from 0.27.0 onwards.
16-
The "binary wheels" available from PyPI_ currently include a copy of libexiv2 v0.27.7, but if you install from source then python-exiv2 will use whichever version of libexiv2 is installed on your computer.
16+
The "binary wheels" available from PyPI_ currently include a copy of libexiv2 v0.28.5, but if you install from source then python-exiv2 will use whichever version of libexiv2 is installed on your computer.
1717

1818
There are some differences in the API of libexiv2 v0.28.x and v0.27.y.
1919
Some of these have been "backported" in the Python interface so you can start using the v0.28 methods, e.g. the ``exiv2.DataBuf.data()`` function replaces the ``exiv2.DataBuf.pData_`` attribute.
@@ -51,27 +51,20 @@ Some parts of the interface are deprecated and will eventually be removed.
5151
Please use Python's ``-Wd`` flag when testing your software to ensure it isn't using deprecated features.
5252
(Do let me know if I've deprecated a feature you need and can't replace with an alternative.)
5353

54-
Enums
55-
-----
56-
57-
The C++ libexiv2 library often uses ``enum`` classes to list related data, such as the value type identifiers stored in `Exiv2::TypeId`_.
58-
SWIG's default processing of such enums is to add all the values as named constants to the top level of the module, e.g. ``exiv2.asciiString``.
59-
In python-exiv2 most of the C++ enums are represented by Python enum_ classes, e.g. ``exiv2.TypeId.asciiString`` is a member of ``exiv2.TypeId``.
60-
61-
Unfortunately there is no easy way to deprecate the SWIG generated top level constants, but they will eventually be removed from python-exiv2.
62-
Please ensure you only use the enum classes in your use of python-exiv2.
63-
6454
Data structures
6555
---------------
6656

6757
Some parts of the Exiv2 API use structures to hold several related data items.
6858
For example, the `Exiv2::ExifTags`_ class has a ``tagList()`` method that returns a list of `Exiv2::TagInfo`_ structs.
69-
In python-exiv2 (since v0.16.2) these structs have dict_ like behaviour, so the members can be accessed more easily:
59+
Since python-exiv2 v0.18.0 struct member names ending with an underscore ``_`` have aliases without the underscore.
60+
Since v0.16.2 these structs also have dict_ like behaviour, so the members can be accessed more easily:
7061

7162
.. code:: python
7263
7364
>>> import exiv2
7465
>>> info = exiv2.ExifTags.tagList('Image')[0]
66+
>>> print(info.title)
67+
Processing Software
7568
>>> print(info.title_)
7669
Processing Software
7770
>>> print(info['title'])
@@ -90,7 +83,8 @@ In python-exiv2 (since v0.16.2) these structs have dict_ like behaviour, so the
9083
'title': 'Processing Software',
9184
'typeId': <TypeId.asciiString: 2>}
9285
93-
Note that struct member names ending with an underscore have the underscore removed in the dict_ like interface.
86+
In general it's more efficient to use attribute access (``info.title``) than dict_ access (``info['title']``).
87+
It is sometimes useful to be able to iterate over the members though, as shown above.
9488

9589
Reading data values
9690
-------------------
@@ -107,7 +101,7 @@ The Python interface uses the value's ``typeId()`` method to determine its type
107101
Recasting data values
108102
^^^^^^^^^^^^^^^^^^^^^
109103

110-
In earlier versions of python-gphoto2 you could set the type of value returned by ``value()`` or ``getValue()`` by passing an ``exiv2.TypeId`` parameter:
104+
In old versions of python-gphoto2 you could set the type of value returned by ``value()`` or ``getValue()`` by passing an ``exiv2.TypeId`` parameter:
111105

112106
.. code:: python
113107
@@ -231,14 +225,16 @@ If you don't want to use the data numerically then you can just use strings for
231225
value = str(datum.value())
232226
exifData['Exif.GPSInfo.GPSLatitude'] = '47/1 49/1 31822/1000'
233227
234-
Iterators
235-
---------
228+
Iterators & references
229+
----------------------
236230

237231
The ``Exiv2::ExifData``, ``Exiv2::IptcData``, and ``Exiv2::XmpData`` classes use C++ iterators to expose private data, for example the ``ExifData`` class has a private member of ``std::list<Exifdatum>`` type.
238232
The classes have public ``begin()``, ``end()``, and ``findKey()`` methods that return ``std::list`` iterators.
239-
In C++ you can dereference one of these iterators to access the ``Exifdatum`` object, but Python doesn't have a dereference operator.
233+
They also have ``[key]`` operators that return a pointer to an ``Exifdatum`` object.
234+
235+
In C++ you can dereference one of these pointers to access the ``Exifdatum`` object, but Python doesn't have a dereference operator.
240236

241-
This Python interface converts the ``std::list`` iterator to a Python object that has access to all the ``Exifdatum`` object's methods without dereferencing.
237+
In python-exiv2 the iterators (and references since v0.18.0) are wrapped in a Python object that has access to all the ``Exifdatum`` object's methods without dereferencing.
242238
For example:
243239

244240
.. code:: python
@@ -311,29 +307,11 @@ This allows them to be used in a very Pythonic style:
311307
Warning: segmentation faults
312308
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
313309

314-
If an iterator is invalidated, e.g. by deleting the datum it points to, then your Python program may crash with a segmentation fault if you try to use the invalid iterator.
315-
Just as in C++, there is no way to detect that an iterator has become invalid.
316-
317-
Segmentation faults
318-
-------------------
319-
320-
There are many places in the libexiv2 C++ API where objects hold references to data in other objects.
321-
This is more efficient than copying the data, but can cause segmentation faults if an object is deleted while another objects refers to its data.
322-
323-
The Python interface tries to protect the user from this but in some cases this is not possible.
324-
For example, an `Exiv2::Metadatum`_ object holds a reference to data that can easily be invalidated:
310+
If a pointer is invalidated, e.g. by deleting the datum it points to, then your Python program may crash with a segmentation fault if you try to use the invalid pointer.
311+
Just as in C++, there is no way to detect that a pointer has become invalid.
325312

326-
.. code:: python
327-
328-
exifData = image.exifData()
329-
datum = exifData['Exif.GPSInfo.GPSLatitude']
330-
print(str(datum.value())) # no problem
331-
del exifData['Exif.GPSInfo.GPSLatitude']
332-
print(str(datum.value())) # segfault!
333-
334-
Segmentation faults are also easily caused by careless use of iterators or memory blocks, as discussed below.
335-
There may be other cases where the Python interface doesn't prevent segfaults.
336-
Please let me know if you find any.
313+
Since v0.18.0 python-exiv2 (if built with swig >= 4.4) tries to invalidate pointers if the data they point to is deleted.
314+
Please let me know if you encounter any problems with segmentation faults.
337315

338316
Binary data input
339317
-----------------
@@ -366,23 +344,36 @@ In some cases this includes writing to the data.
366344
buf = thumb.copy()
367345
thumb_im = PIL.Image.open(io.BytesIO(buf.data()))
368346
369-
In python-exiv2 before v0.15.0 the memory block is converted to an object with a buffer interface.
370-
A Python memoryview_ can be used to access the data without copying.
371-
(Converting to bytes_ would make a copy of the data, which we don't usually want.)
347+
Since version 0.18.0 python-exiv2 releases the memoryview_ if the memory is invalidated (e.g. if the memory block is resized) to prevent problems such as segmentation faults:
372348

373-
Warning: segmentation faults
374-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
349+
.. code:: python
350+
351+
>>> buf = exiv2.DataBuf(b'fred')
352+
>>> data = buf.data()
353+
>>> print(bytes(data))
354+
b'fred'
355+
>>> buf.resize(128)
356+
>>> print(bytes(data))
357+
Traceback (most recent call last):
358+
File "<stdin>", line 1, in <module>
359+
ValueError: operation forbidden on released memoryview object
360+
>>>
375361
376-
Note that the memory block must not be deleted or resized while the memoryview exists.
377-
Doing so will invalidate the memoryview and may cause a segmentation fault:
362+
Although memoryview_ objects can be used in a with_ statement this has no benefit with python-exiv2.
363+
The memory view's ``release`` method does nothing.
364+
Releasing any associated resources only happens when the memory view is deleted:
378365

379366
.. code:: python
380367
381-
buf = exiv2.DataBuf(b'fred')
382-
data = buf.data()
383-
print(bytes(data)) # Prints b'fred'
384-
buf.alloc(128)
385-
print(bytes(data)) # Prints random values, may segfault
368+
with buf.data() as data:
369+
file.write(data)
370+
del data
371+
372+
is equivalent to
373+
374+
.. code:: python
375+
376+
file.write(buf.data())
386377
387378
Buffer interface
388379
----------------
@@ -398,6 +389,8 @@ For example, you could save a photograph's thumbnail in a separate file like thi
398389
with open('thumbnail.jpg', 'wb') as out_file:
399390
out_file.write(thumb.copy())
400391
392+
Use of this buffer interface is deprecated (since python-exiv2 v0.18.0) and the ``data()`` methods described above should be used instead.
393+
401394
Image data in memory
402395
--------------------
403396

@@ -408,51 +401,19 @@ The buffered data isn't actually read until ``Image::readMetadata`` is called, s
408401
When ``Image::writeMetadata`` is called exiv2 allocates a new block of memory to store the modified data.
409402
The ``Image::io`` method returns an `Exiv2::BasicIo`_ object that provides access to this data.
410403

411-
The ``BasicIo::mmap`` method allows access to the image file data without unnecessary copying.
412-
However it is rather error prone, crashing your Python program with a segmentation fault if anything goes wrong.
404+
The ``BasicIo::mmap`` and ``BasicIo::munmap`` methods allow access to the image file data without unnecessary copying.
405+
However they are rather error prone, crashing your Python program with a segmentation fault if anything goes wrong.
413406

414-
The ``Exiv2::BasicIo`` object must be opened before calling ``mmap()``.
415-
A Python `context manager`_ can be used to ensure that the ``open()`` and ``mmap()`` calls are paired with ``munmap()`` and ``close()`` calls:
407+
Since python-exiv2 v0.18.0 it is much easier to use the image's ``data()`` method:
416408

417409
.. code:: python
418410
419-
from contextlib import contextmanager
420-
421-
@contextmanager
422-
def get_file_data(image):
423-
exiv_io = image.io()
424-
exiv_io.open()
425-
try:
426-
yield exiv_io.mmap()
427-
finally:
428-
exiv_io.munmap()
429-
exiv_io.close()
430-
431411
# after setting some metadata
432412
image.writeMetadata()
433-
with get_file_data(image) as data:
434-
rsp = requests.post(url, files={'file': io.BytesIO(data)})
435-
436-
The ``exiv2.BasicIo`` Python type exposes a `buffer interface`_ which is a lot easier to use.
437-
It allows the ``exiv2.BasicIo`` object to be used anywhere that a `bytes-like object`_ is expected:
438-
439-
.. code:: python
440-
441-
# after setting some metadata
442-
image.writeMetadata()
443-
exiv_io = image.io()
444-
rsp = requests.post(url, files={'file': io.BytesIO(exiv_io)})
445-
446-
Since python-exiv2 v0.15.0 this buffer can be writeable:
447-
448-
.. code:: python
449-
450-
exiv_io = image.io()
451-
with memoryview(exiv_io) as data:
452-
data[23] = 157 # modifies data buffer
453-
image.readMetadata() # reads modified buffer data
413+
rsp = requests.post(url, files={'file': io.BytesIO(image.data())})
454414
455-
The modified data is written back to the file or memory buffer when the memoryview_ is released.
415+
The ``data()`` method returns a Python memoryview_ that can be used in most places where a `bytes-like object`_ is expected.
416+
This allows copy free access to the image data.
456417

457418
.. _bytearray:
458419
https://docs.python.org/3/library/stdtypes.html#bytearray
@@ -502,3 +463,5 @@ The modified data is written back to the file or memory buffer when the memoryvi
502463
https://docs.python.org/3/library/stdtypes.html#memoryview
503464
.. _PyPI:
504465
https://pypi.org/project/exiv2/
466+
.. _with:
467+
https://docs.python.org/3/reference/compound_stmts.html#with

0 commit comments

Comments
 (0)