fix: add _ suffix to properties having reserved keyword names
authorVadim Levin <vadim.levin@xperience.ai>
Tue, 13 Dec 2022 17:24:57 +0000 (20:24 +0300)
committerVadim Levin <vadim.levin@xperience.ai>
Tue, 13 Dec 2022 17:56:39 +0000 (20:56 +0300)
modules/core/include/opencv2/core/bindings_utils.hpp
modules/python/src2/gen2.py
modules/python/test/test_misc.py

index 6e825ec816815aa7ae6c2a7c6415fe3b5a0eb5ff..5de2f7022e03305466db14d0ccbdd612b9a8f290 100644 (file)
@@ -213,6 +213,17 @@ AsyncArray testAsyncException()
     return p.getArrayResult();
 }
 
+struct CV_EXPORTS_W_SIMPLE ClassWithKeywordProperties {
+    CV_PROP_RW int lambda;
+    CV_PROP int except;
+
+    CV_WRAP explicit ClassWithKeywordProperties(int lambda_arg = 24, int except_arg = 42)
+    {
+        lambda = lambda_arg;
+        except = except_arg;
+    }
+};
+
 namespace nested {
 CV_WRAP static inline bool testEchoBooleanFunction(bool flag) {
     return flag;
index 1a9239c07f2dcf3e99175f6c6b8fc1f38eba624e..14508761fb94c9e9792a4334a35c4ebfee6431d5 100755 (executable)
@@ -169,10 +169,10 @@ static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value
 
 
 gen_template_prop_init = Template("""
-    {(char*)"${member}", (getter)pyopencv_${name}_get_${member}, NULL, (char*)"${member}", NULL},""")
+    {(char*)"${export_member_name}", (getter)pyopencv_${name}_get_${member}, NULL, (char*)"${export_member_name}", NULL},""")
 
 gen_template_rw_prop_init = Template("""
-    {(char*)"${member}", (getter)pyopencv_${name}_get_${member}, (setter)pyopencv_${name}_set_${member}, (char*)"${member}", NULL},""")
+    {(char*)"${export_member_name}", (getter)pyopencv_${name}_get_${member}, (setter)pyopencv_${name}_set_${member}, (char*)"${export_member_name}", NULL},""")
 
 gen_template_overloaded_function_call = Template("""
     {
@@ -242,6 +242,13 @@ class ClassProp(object):
         if "/RW" in decl[3]:
             self.readonly = False
 
+    @property
+    def export_name(self):
+        if self.name in python_reserved_keywords:
+            return self.name + "_"
+        return self.name
+
+
 class ClassInfo(object):
     def __init__(self, name, decl=None, codegen=None):
         # Scope name can be a module or other class e.g. cv::SimpleBlobDetector::Params
@@ -357,13 +364,13 @@ class ClassInfo(object):
             else:
                 getset_code.write(gen_template_get_prop.substitute(name=self.name, member=pname, membertype=p.tp, access=access_op))
             if p.readonly:
-                getset_inits.write(gen_template_prop_init.substitute(name=self.name, member=pname))
+                getset_inits.write(gen_template_prop_init.substitute(name=self.name, member=pname, export_member_name=p.export_name))
             else:
                 if self.isalgorithm:
                     getset_code.write(gen_template_set_prop_algo.substitute(name=self.name, cname=self.cname, member=pname, membertype=p.tp, access=access_op))
                 else:
                     getset_code.write(gen_template_set_prop.substitute(name=self.name, member=pname, membertype=p.tp, access=access_op))
-                getset_inits.write(gen_template_rw_prop_init.substitute(name=self.name, member=pname))
+                getset_inits.write(gen_template_rw_prop_init.substitute(name=self.name, member=pname, export_member_name=p.export_name))
 
         methods_code = StringIO()
         methods_inits = StringIO()
index ec56585aceb4ada8c81cda071628b2955f9b5d0a..71e7f41bb5ae35abeeec1cd9096eb3c5286a96fd 100644 (file)
@@ -119,6 +119,23 @@ class Bindings(NewOpenCVTests):
         test_overload_resolution('rect with float coordinates', (4.5, 4, 2, 1))
         test_overload_resolution('rect with wrong number of coordinates', (4, 4, 1))
 
+    def test_properties_with_reserved_keywords_names_are_transformed(self):
+        obj = cv.utils.ClassWithKeywordProperties(except_arg=23)
+        self.assertTrue(hasattr(obj, "lambda_"),
+                        msg="Class doesn't have RW property with converted name")
+        try:
+            obj.lambda_ = 32
+        except Exception as e:
+            self.fail("Failed to set value to RW property. Error: {}".format(e))
+
+        self.assertTrue(hasattr(obj, "except_"),
+                        msg="Class doesn't have readonly property with converted name")
+        self.assertEqual(obj.except_, 23,
+                         msg="Can't access readonly property value")
+        with self.assertRaises(AttributeError):
+            obj.except_ = 32
+
+
 
 class Arguments(NewOpenCVTests):