Browse Source

interrogate: allow passing None for args that have NULL as default value

rdb 7 years ago
parent
commit
7125a3e587
1 changed files with 56 additions and 8 deletions
  1. 56 8
      dtool/src/interrogate/interfaceMakerPythonNative.cxx

+ 56 - 8
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -5414,6 +5414,18 @@ write_function_instance(ostream &out, FunctionRemap *remap,
         parameter_list += ", &" + param_name;
       }
 
+      // If the default value is NULL, we also accept a None value.
+      bool maybe_none = false;
+      if (default_value != nullptr && (return_flags & RF_coerced) == 0) {
+        CPPExpression::Result res = param->get_default_value()->evaluate();
+        if (res._type == CPPExpression::RT_integer ||
+            res._type == CPPExpression::RT_pointer) {
+          if (res.as_integer() == 0) {
+            maybe_none = true;
+          }
+        }
+      }
+
       string class_name = obj_type->get_local_name(&parser);
 
       // need to a forward scope for this class..
@@ -5464,17 +5476,27 @@ write_function_instance(ostream &out, FunctionRemap *remap,
 
           type->output_instance(extra_convert, param_name + "_this", &parser);
 
-          if (is_optional) {
+          if (is_optional && maybe_none) {
+            extra_convert
+              << default_expr << ";\n"
+              << "if (" << param_name << " != NULL && " << param_name << " != Py_None) {\n"
+              << "  " << param_name << "_this";
+          } else if (is_optional) {
             extra_convert
               << default_expr << ";\n"
               << "if (" << param_name << " != NULL) {\n"
               << "  " << param_name << "_this";
+          } else if (maybe_none) {
+            extra_convert
+              << " = NULL;\n"
+              << "if (" << param_name << " != Py_None) {\n"
+              << "  " << param_name << "_this";
           }
 
           extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) +
             "(" + param_name + ", " + param_name + "_local);\n";
 
-          if (is_optional) {
+          if (is_optional || maybe_none) {
             extra_convert << "}\n";
           }
 
@@ -5485,8 +5507,12 @@ write_function_instance(ostream &out, FunctionRemap *remap,
 
         if (report_errors) {
           // We were asked to report any errors.  Let's do it.
-          if (is_optional) {
+          if (is_optional && maybe_none) {
+            extra_convert << "if (" << param_name << " != NULL && " << param_name << " != Py_None && !" << coerce_call << ") {\n";
+          } else if (is_optional) {
             extra_convert << "if (" << param_name << " != NULL && !" << coerce_call << ") {\n";
+          } else if (maybe_none) {
+            extra_convert << "if (" << param_name << " != Py_None && !" << coerce_call << ") {\n";
           } else {
             extra_convert << "if (!" << coerce_call << ") {\n";
           }
@@ -5509,19 +5535,35 @@ write_function_instance(ostream &out, FunctionRemap *remap,
           }
           extra_convert << "}\n";
 
+        } else if (is_optional && maybe_none) {
+          extra_param_check << " && (" << param_name << " == NULL || " << param_name << " == Py_None || " << coerce_call << ")";
+
         } else if (is_optional) {
           extra_param_check << " && (" << param_name << " == NULL || " << coerce_call << ")";
 
+        } else if (maybe_none) {
+          extra_param_check << " && (" << param_name << " == Py_None || " << coerce_call << ")";
+
         } else {
           extra_param_check << " && " << coerce_call;
         }
 
-      } else {
+      } else { // The regular, non-coercion case.
         type->output_instance(extra_convert, param_name + "_this", &parser);
-        if (is_optional) {
+        if (is_optional && maybe_none) {
+          extra_convert
+            << default_expr << ";\n"
+            << "if (" << param_name << " != NULL && " << param_name << " != Py_None) {\n"
+            << "  " << param_name << "_this";
+        } else if (is_optional) {
           extra_convert
             << default_expr << ";\n"
-            << "if (" << param_name << " != (PyObject *)NULL) {\n"
+            << "if (" << param_name << " != NULL) {\n"
+            << "  " << param_name << "_this";
+        } else if (maybe_none) {
+          extra_convert
+            << " = NULL;\n"
+            << "if (" << param_name << " != Py_None) {\n"
             << "  " << param_name << "_this";
         }
         if (const_ok && !report_errors) {
@@ -5529,7 +5571,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
           // simpler.  But maybe we should just reorganize these functions
           // entirely?
           extra_convert << " = NULL;\n";
-          int indent_level = is_optional ? 2 : 0;
+          int indent_level = (is_optional || maybe_none) ? 2 : 0;
           indent(extra_convert, indent_level)
             << "DtoolInstance_GetPointer(" << param_name
             << ", " << param_name << "_this"
@@ -5545,9 +5587,15 @@ write_function_instance(ostream &out, FunctionRemap *remap,
             << "\", " << const_ok << ", " << report_errors << ");\n";
         }
 
-        if (is_optional) {
+        if (is_optional && maybe_none) {
+          extra_convert << "}\n";
+          extra_param_check << " && (" << param_name << " == NULL || " << param_name << " == Py_None || " << param_name << "_this != NULL)";
+        } else if (is_optional) {
           extra_convert << "}\n";
           extra_param_check << " && (" << param_name << " == NULL || " << param_name << "_this != NULL)";
+        } else if (maybe_none) {
+          extra_convert << "}\n";
+          extra_param_check << " && (" << param_name << " == Py_None || " << param_name << "_this != NULL)";
         } else {
           extra_param_check << " && " << param_name << "_this != NULL";
         }