Skip to content

Commit

Permalink
Merge pull request #42 from jim-easterbrook/devel
Browse files Browse the repository at this point in the history
Devel
  • Loading branch information
jim-easterbrook authored Sep 19, 2024
2 parents 6eb6ce4 + 3a4bd4e commit 12fda05
Show file tree
Hide file tree
Showing 42 changed files with 943 additions and 432 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.

Changes in v0.17.1:
1/ Fix crash when using localised exceptions on Windows.

Changes in v0.17.0:
1/ API change: derived classes of BasicIo are omitted from Python.
2/ Binary wheels incorporate libexiv2 v0.28.3.
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
python-exiv2 v\ 0.17.0
python-exiv2 v\ 0.17.1
======================

python-exiv2 is a low level interface (or binding) to the exiv2_ C++ library.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dynamic = ["version"]
[project.urls]
Homepage = "https://github.com/jim-easterbrook/python-exiv2"
Changelog = "https://github.com/jim-easterbrook/python-exiv2/blob/main/CHANGELOG.txt"
Documentation = "https://github.com/jim-easterbrook/python-exiv2/blob/main/USAGE.rst"
Documentation = "https://python-exiv2.readthedocs.io/"

[tool.setuptools]
platforms = ["POSIX", "MacOS", "Windows"]
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ def get_mod_src_dir(exiv2_version):
packages.append('exiv2.lib')
if platform == 'linux':
path = os.path.join(exiv2_root, 'lib64')
if not os.path.exists(path):
path = os.path.join(exiv2_root, 'lib')
library_dirs = [path]
package_dir['exiv2.lib'] = path
package_data['exiv2.lib'] = [x for x in os.listdir(path)
Expand Down
2 changes: 1 addition & 1 deletion src/doc/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
exiv2 <= 0.17.0
exiv2 <= 0.17.1
sphinx == 7.2.6
sphinx-rtd-theme == 2.0.0
5 changes: 3 additions & 2 deletions src/interface/error.i
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@
static PyObject* logger = NULL;
static void log_to_python(int level, const char* msg) {
std::string copy = msg;
utf8_to_wcp(&copy, false);
if (wcp_to_utf8(&copy))
copy = msg;
Py_ssize_t len = copy.size();
while (len > 0 && copy[len-1] == '\n')
len--;
PyGILState_STATE gstate = PyGILState_Ensure();
PyObject* res = PyObject_CallMethod(
logger, "log", "(is#)", (level + 1) * 10, copy.c_str(), len);
logger, "log", "(is#)", (level + 1) * 10, copy.data(), len);
Py_XDECREF(res);
PyGILState_Release(gstate);
};
Expand Down
8 changes: 6 additions & 2 deletions src/interface/shared/exception.i
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,20 @@ static void _set_python_exception() {
#if EXIV2_VERSION_HEX < 0x001c0000
catch(Exiv2::AnyError const& e) {
std::string msg = e.what();
utf8_to_wcp(&msg, false);
if (wcp_to_utf8(&msg))
msg = e.what();
PyObject* args = Py_BuildValue(
"Ns", py_from_enum((Exiv2::ErrorCode)e.code()), msg.c_str());
PyErr_SetObject(PyExc_Exiv2Error, args);
Py_DECREF(args);
}
#else
catch(Exiv2::Error const& e) {
std::string msg = e.what();
if (wcp_to_utf8(&msg))
msg = e.what();
PyObject* args = Py_BuildValue(
"Ns", py_from_enum(e.code()), e.what());
"Ns", py_from_enum((Exiv2::ErrorCode)e.code()), msg.c_str());
PyErr_SetObject(PyExc_Exiv2Error, args);
Py_DECREF(args);
}
Expand Down
33 changes: 22 additions & 11 deletions src/interface/shared/windows_cp.i
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,45 @@
#include <windows.h>
#endif

static int utf8_to_wcp(std::string *str, bool to_cp) {
#ifdef _WIN32
UINT cp_in = CP_UTF8;
UINT cp_out = GetACP();
static int _transcode(std::string *str, UINT cp_in, UINT cp_out) {
if (cp_out == cp_in)
return 0;
if (!to_cp) {
cp_in = cp_out;
cp_out = CP_UTF8;
}
int size = MultiByteToWideChar(cp_in, 0, &(*str)[0], (int)str->size(),
NULL, 0);
if (!size)
return -1;
return GetLastError();
std::wstring wide_str;
wide_str.resize(size);
if (!MultiByteToWideChar(cp_in, 0, &(*str)[0], (int)str->size(),
&wide_str[0], size))
return -1;
return GetLastError();
size = WideCharToMultiByte(cp_out, 0, &wide_str[0], (int)wide_str.size(),
NULL, 0, NULL, NULL);
if (!size)
return -1;
return GetLastError();
str->resize(size);
if (!WideCharToMultiByte(cp_out, 0, &wide_str[0], (int)wide_str.size(),
&(*str)[0], size, NULL, NULL))
return -1;
return GetLastError();
return 0;
};
#endif

static int utf8_to_wcp(std::string *str) {
#ifdef _WIN32
return _transcode(str, CP_UTF8, GetACP());
#else
return 0;
#endif
};

static int wcp_to_utf8(std::string *str) {
#ifdef _WIN32
return _transcode(str, GetACP(), CP_UTF8);
#else
return 0;
#endif
};

%}
18 changes: 12 additions & 6 deletions src/interface/shared/windows_path.i
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
%define WINDOWS_PATH(signature)
%typemap(check, fragment="utf8_to_wcp") signature {
%#ifdef _WIN32
if (utf8_to_wcp($1, true) < 0) {
SWIG_exception_fail(SWIG_ValueError, "failed to transcode path");
int error = utf8_to_wcp($1);
if (error) {
PyErr_SetFromWindowsErr(error);
SWIG_fail;
}
%#endif
}
Expand All @@ -33,17 +35,21 @@
%define WINDOWS_PATH_OUT(function)
%typemap(out, fragment="utf8_to_wcp") std::string function {
%#ifdef _WIN32
if (utf8_to_wcp(&$1, false) < 0) {
SWIG_exception_fail(SWIG_ValueError, "failed to transcode result");
int error = wcp_to_utf8(&$1);
if (error) {
PyErr_SetFromWindowsErr(error);
SWIG_fail;
}
%#endif
$result = SWIG_FromCharPtrAndSize($1.data(), $1.size());
}
%typemap(out, fragment="utf8_to_wcp") const std::string& function {
std::string copy = *$1;
%#ifdef _WIN32
if (utf8_to_wcp(&copy, false) < 0) {
SWIG_exception_fail(SWIG_ValueError, "failed to transcode result");
int error = wcp_to_utf8(&copy);
if (error) {
PyErr_SetFromWindowsErr(error);
SWIG_fail;
}
%#endif
$result = SWIG_FromCharPtrAndSize(copy.data(), copy.size());
Expand Down
4 changes: 2 additions & 2 deletions src/swig-0_27_7/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ def __init__(self, code, message):
self.message = message

#: python-exiv2 version as a string
__version__ = "0.17.0"
__version__ = "0.17.1"
#: python-exiv2 version as a tuple of ints
__version_tuple__ = tuple((0, 17, 0))
__version_tuple__ = tuple((0, 17, 1))

__all__ = ["Exiv2Error"]
from exiv2.basicio import *
Expand Down
45 changes: 31 additions & 14 deletions src/swig-0_27_7/basicio_wrap.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4200,46 +4200,58 @@ static PyObject* py_from_enum(Exiv2::ErrorCode value) {
#include <windows.h>
#endif

static int utf8_to_wcp(std::string *str, bool to_cp) {
#ifdef _WIN32
UINT cp_in = CP_UTF8;
UINT cp_out = GetACP();
static int _transcode(std::string *str, UINT cp_in, UINT cp_out) {
if (cp_out == cp_in)
return 0;
if (!to_cp) {
cp_in = cp_out;
cp_out = CP_UTF8;
}
int size = MultiByteToWideChar(cp_in, 0, &(*str)[0], (int)str->size(),
NULL, 0);
if (!size)
return -1;
return GetLastError();
std::wstring wide_str;
wide_str.resize(size);
if (!MultiByteToWideChar(cp_in, 0, &(*str)[0], (int)str->size(),
&wide_str[0], size))
return -1;
return GetLastError();
size = WideCharToMultiByte(cp_out, 0, &wide_str[0], (int)wide_str.size(),
NULL, 0, NULL, NULL);
if (!size)
return -1;
return GetLastError();
str->resize(size);
if (!WideCharToMultiByte(cp_out, 0, &wide_str[0], (int)wide_str.size(),
&(*str)[0], size, NULL, NULL))
return -1;
return GetLastError();
return 0;
};
#endif

static int utf8_to_wcp(std::string *str) {
#ifdef _WIN32
return _transcode(str, CP_UTF8, GetACP());
#else
return 0;
#endif
};

static int wcp_to_utf8(std::string *str) {
#ifdef _WIN32
return _transcode(str, GetACP(), CP_UTF8);
#else
return 0;
#endif
};



static void _set_python_exception() {
try {
throw;
}

catch(Exiv2::AnyError const& e) {
std::string msg = e.what();
utf8_to_wcp(&msg, false);
if (wcp_to_utf8(&msg))
msg = e.what();
PyObject* args = Py_BuildValue(
"Ns", py_from_enum((Exiv2::ErrorCode)e.code()), msg.c_str());
PyErr_SetObject(PyExc_Exiv2Error, args);
Expand All @@ -4253,6 +4265,9 @@ static void _set_python_exception() {






/*@SWIG:/usr/local/share/swig/4.2.1/typemaps/exception.swg,59,SWIG_CATCH_STDEXCEPT@*/ /* catching std::exception */
catch (std::invalid_argument& e) {
SWIG_exception_fail(SWIG_ValueError, e.what() );
Expand Down Expand Up @@ -5524,8 +5539,10 @@ SWIGINTERN PyObject *_wrap_BasicIo_path(PyObject *self, PyObject *args) {
result = ((Exiv2::BasicIo const *)arg1)->path();
{
#ifdef _WIN32
if (utf8_to_wcp(&result, false) < 0) {
SWIG_exception_fail(SWIG_ValueError, "failed to transcode result");
int error = wcp_to_utf8(&result);
if (error) {
PyErr_SetFromWindowsErr(error);
SWIG_fail;
}
#endif
resultobj = SWIG_FromCharPtrAndSize((&result)->data(), (&result)->size());
Expand Down
39 changes: 27 additions & 12 deletions src/swig-0_27_7/datasets_wrap.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4222,46 +4222,58 @@ static PyObject* py_from_enum(Exiv2::ErrorCode value) {
#include <windows.h>
#endif

static int utf8_to_wcp(std::string *str, bool to_cp) {
#ifdef _WIN32
UINT cp_in = CP_UTF8;
UINT cp_out = GetACP();
static int _transcode(std::string *str, UINT cp_in, UINT cp_out) {
if (cp_out == cp_in)
return 0;
if (!to_cp) {
cp_in = cp_out;
cp_out = CP_UTF8;
}
int size = MultiByteToWideChar(cp_in, 0, &(*str)[0], (int)str->size(),
NULL, 0);
if (!size)
return -1;
return GetLastError();
std::wstring wide_str;
wide_str.resize(size);
if (!MultiByteToWideChar(cp_in, 0, &(*str)[0], (int)str->size(),
&wide_str[0], size))
return -1;
return GetLastError();
size = WideCharToMultiByte(cp_out, 0, &wide_str[0], (int)wide_str.size(),
NULL, 0, NULL, NULL);
if (!size)
return -1;
return GetLastError();
str->resize(size);
if (!WideCharToMultiByte(cp_out, 0, &wide_str[0], (int)wide_str.size(),
&(*str)[0], size, NULL, NULL))
return -1;
return GetLastError();
return 0;
};
#endif

static int utf8_to_wcp(std::string *str) {
#ifdef _WIN32
return _transcode(str, CP_UTF8, GetACP());
#else
return 0;
#endif
};

static int wcp_to_utf8(std::string *str) {
#ifdef _WIN32
return _transcode(str, GetACP(), CP_UTF8);
#else
return 0;
#endif
};



static void _set_python_exception() {
try {
throw;
}

catch(Exiv2::AnyError const& e) {
std::string msg = e.what();
utf8_to_wcp(&msg, false);
if (wcp_to_utf8(&msg))
msg = e.what();
PyObject* args = Py_BuildValue(
"Ns", py_from_enum((Exiv2::ErrorCode)e.code()), msg.c_str());
PyErr_SetObject(PyExc_Exiv2Error, args);
Expand All @@ -4275,6 +4287,9 @@ static void _set_python_exception() {






/*@SWIG:/usr/local/share/swig/4.2.1/typemaps/exception.swg,59,SWIG_CATCH_STDEXCEPT@*/ /* catching std::exception */
catch (std::invalid_argument& e) {
SWIG_exception_fail(SWIG_ValueError, e.what() );
Expand Down
Loading

0 comments on commit 12fda05

Please sign in to comment.