|
1 | 1 | // python-exiv2 - Python interface to libexiv2 |
2 | 2 | // http://github.com/jim-easterbrook/python-exiv2 |
3 | | -// Copyright (C) 2022-24 Jim Easterbrook [email protected] |
| 3 | +// Copyright (C) 2022-25 Jim Easterbrook [email protected] |
4 | 4 | // |
5 | 5 | // This program is free software: you can redistribute it and/or modify |
6 | 6 | // it under the terms of the GNU General Public License as published by |
@@ -167,6 +167,75 @@ static void release_ptr(Exiv2::BasicIo* self) { |
167 | 167 | } |
168 | 168 | EXPOSE_OBJECT_BUFFER(Exiv2::BasicIo, true, true) |
169 | 169 |
|
| 170 | +// Wrapper class to provide a context manager for Exiv2::BasicIo::mmap |
| 171 | +%feature("docstring") DataContext "Data context manager. |
| 172 | +
|
| 173 | +A simple context manager for *mmap* / *munmap* data access. The |
| 174 | +*__enter__* method returns a :py:class:`memoryview` of the data." |
| 175 | +%ignore DataContext::DataContext; |
| 176 | +%inline %{ |
| 177 | +class DataContext { |
| 178 | +private: |
| 179 | + Exiv2::BasicIo* parent; |
| 180 | + bool isWriteable; |
| 181 | + bool mapped; |
| 182 | +public: |
| 183 | + DataContext(Exiv2::BasicIo* parent, bool isWriteable) : |
| 184 | + parent(parent), isWriteable(isWriteable), mapped(false) {}; |
| 185 | + ~DataContext() { |
| 186 | + if (mapped) { |
| 187 | + SWIG_PYTHON_THREAD_BEGIN_ALLOW; |
| 188 | + parent->munmap(); |
| 189 | + SWIG_PYTHON_THREAD_END_ALLOW; |
| 190 | + parent->close(); |
| 191 | + } |
| 192 | + }; |
| 193 | + PyObject* __enter__() { |
| 194 | + SWIG_PYTHON_THREAD_BEGIN_ALLOW; |
| 195 | + int error = parent->open(); |
| 196 | + if (error) { |
| 197 | + SWIG_PYTHON_THREAD_END_ALLOW; |
| 198 | + return PyErr_Format( |
| 199 | + PyExc_RuntimeError, "open() returned %d", error); |
| 200 | + } |
| 201 | + char* ptr = (char*)parent->mmap(isWriteable); |
| 202 | + SWIG_PYTHON_THREAD_END_ALLOW; |
| 203 | + mapped = true; |
| 204 | + return PyMemoryView_FromMemory( |
| 205 | + ptr, ptr ? parent->size() : 0, |
| 206 | + isWriteable ? PyBUF_WRITE : PyBUF_READ); |
| 207 | + }; |
| 208 | + bool __exit__(PyObject* exc_type, PyObject* exc_val, PyObject* exc_tb) { |
| 209 | + if (mapped) { |
| 210 | + SWIG_PYTHON_THREAD_BEGIN_ALLOW; |
| 211 | + parent->munmap(); |
| 212 | + mapped = false; |
| 213 | + parent->close(); |
| 214 | + SWIG_PYTHON_THREAD_END_ALLOW; |
| 215 | + } |
| 216 | + return false; |
| 217 | + }; |
| 218 | +}; |
| 219 | +%} |
| 220 | + |
| 221 | +// Add Exiv2::BasicIo::data() method to return a context manager |
| 222 | +%feature("docstring") Exiv2::BasicIo::data "Return a data context manager. |
| 223 | +
|
| 224 | +This allows easy access to the data using a ``with`` statement. |
| 225 | +The context manager calls *mmap* when the context is entered and |
| 226 | +*munmap* when the context is exited. |
| 227 | +:type isWriteable: bool, optional |
| 228 | +:param isWriteable: Set to true if the data should be writeable |
| 229 | + (default is false). |
| 230 | +:rtype: object |
| 231 | +:return: A context manager" |
| 232 | +%newobject Exiv2::BasicIo::data; |
| 233 | +%extend Exiv2::BasicIo { |
| 234 | + DataContext* data(bool isWriteable) { |
| 235 | + return new DataContext($self, isWriteable); |
| 236 | + } |
| 237 | +} |
| 238 | + |
170 | 239 | // Make enum more Pythonic |
171 | 240 | DEFINE_CLASS_ENUM(BasicIo, Position, "Seek starting positions.", |
172 | 241 | "beg", Exiv2::BasicIo::beg, |
|
0 commit comments