Skip to content

Commit 7b0d7d0

Browse files
committed
fix: conversion to string in python bindings
If provided `PyObject` can't be converted to string `TypeError` is reported instead of `SytemError` without any message.
1 parent a9edcc1 commit 7b0d7d0

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

modules/core/include/opencv2/core/bindings_utils.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ String dumpCString(const char* argument)
5858
return cv::format("String: %s", argument);
5959
}
6060

61+
CV_WRAP static inline
62+
String dumpString(const String& argument)
63+
{
64+
return cv::format("String: %s", argument.c_str());
65+
}
66+
6167
CV_WRAP static inline
6268
AsyncArray testAsyncArray(InputArray argument)
6369
{

modules/python/src2/cv2.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,15 +963,31 @@ PyObject* pyopencv_from(const std::string& value)
963963
template<>
964964
bool pyopencv_to(PyObject* obj, String &value, const ArgInfo& info)
965965
{
966-
CV_UNUSED(info);
967966
if(!obj || obj == Py_None)
967+
{
968968
return true;
969+
}
969970
std::string str;
970971
if (getUnicodeString(obj, str))
971972
{
972973
value = str;
973974
return true;
974975
}
976+
else
977+
{
978+
// If error hasn't been already set by Python conversion functions
979+
if (!PyErr_Occurred())
980+
{
981+
// Direct access to underlying slots of PyObjectType is not allowed
982+
// when limited API is enabled
983+
#ifdef Py_LIMITED_API
984+
failmsg("Can't convert object to 'str' for '%s'", info.name);
985+
#else
986+
failmsg("Can't convert object of type '%s' to 'str' for '%s'",
987+
obj->ob_type->tp_name, info.name);
988+
#endif
989+
}
990+
}
975991
return false;
976992
}
977993

modules/python/test/test_misc.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def test_parse_to_double_not_convertible_extra(self):
314314

315315
def test_parse_to_cstring_convertible(self):
316316
try_to_convert = partial(self._try_to_convert, cv.utils.dumpCString)
317-
for convertible in ('s', 'str', str(123), ('char'), np.str('test1'), np.str_('test2')):
317+
for convertible in ('', 's', 'str', str(123), ('char'), np.str('test1'), np.str_('test2')):
318318
expected = 'string: ' + convertible
319319
actual = try_to_convert(convertible)
320320
self.assertEqual(expected, actual,
@@ -326,6 +326,20 @@ def test_parse_to_cstring_not_convertible(self):
326326
with self.assertRaises((TypeError), msg=get_no_exception_msg(not_convertible)):
327327
_ = cv.utils.dumpCString(not_convertible)
328328

329+
def test_parse_to_string_convertible(self):
330+
try_to_convert = partial(self._try_to_convert, cv.utils.dumpString)
331+
for convertible in (None, '', 's', 'str', str(123), np.str('test1'), np.str_('test2')):
332+
expected = 'string: ' + (convertible if convertible else '')
333+
actual = try_to_convert(convertible)
334+
self.assertEqual(expected, actual,
335+
msg=get_conversion_error_msg(convertible, expected, actual))
336+
337+
def test_parse_to_string_not_convertible(self):
338+
for not_convertible in ((12,), ('t', 'e', 's', 't'), np.array(['123', ]),
339+
np.array(['t', 'e', 's', 't']), 1, True, False):
340+
with self.assertRaises((TypeError), msg=get_no_exception_msg(not_convertible)):
341+
_ = cv.utils.dumpString(not_convertible)
342+
329343

330344
class SamplesFindFile(NewOpenCVTests):
331345

0 commit comments

Comments
 (0)