pidl:Python: improve the .doc string for the get/set elements
[samba.git] / pidl / lib / Parse / Pidl / Samba4 / Python.pm
index 6488ac9c73b02dbcd834d3975de5bb72a3e188c9..c72d8fe34ec7dc59b2a157143a983c8783817e2f 100644 (file)
@@ -242,7 +242,7 @@ sub PythonStruct($$$$$$)
                        $self->pidl(".name = discard_const_p(char, \"$e->{NAME}\"),");
                        $self->pidl(".get = py_$name\_get_$e->{NAME},");
                        $self->pidl(".set = py_$name\_set_$e->{NAME},");
-                       $self->pidl(".doc = discard_const_p(char, \"PIDL-generated element $e->{NAME}\")");
+                       $self->pidl(".doc = discard_const_p(char, \"PIDL-generated element of base type $e->{TYPE}\")");
                        $self->deindent;
                        $self->pidl("},");
                }
@@ -280,7 +280,7 @@ sub PythonStruct($$$$$$)
                $self->deindent;
                $self->pidl("}");
                $self->pidl("err = ndr_push_struct_blob(&blob, tmp_ctx, object, (ndr_push_flags_fn_t)ndr_push_$name);");
-               $self->pidl("if (err != NDR_ERR_SUCCESS) {");
+               $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(err)) {");
                $self->indent;
                $self->pidl("TALLOC_FREE(tmp_ctx);");
                $self->pidl("PyErr_SetNdrError(err);");
@@ -333,7 +333,7 @@ sub PythonStruct($$$$$$)
                $self->pidl("err = ndr_pull_struct_blob_all(&blob, pytalloc_get_mem_ctx(py_obj), object, (ndr_pull_flags_fn_t)ndr_pull_$name);");
                $self->deindent;
                $self->pidl("}");
-               $self->pidl("if (err != NDR_ERR_SUCCESS) {");
+               $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(err)) {");
                $self->indent;
                $self->pidl("PyErr_SetNdrError(err);");
                $self->pidl("return NULL;");
@@ -366,7 +366,7 @@ sub PythonStruct($$$$$$)
                $self->indent;
                $self->pidl("{ \"__ndr_pack__\", (PyCFunction)py_$name\_ndr_pack, METH_NOARGS, \"S.ndr_pack(object) -> blob\\nNDR pack\" },");
                $self->pidl("{ \"__ndr_unpack__\", (PyCFunction)py_$name\_ndr_unpack, METH_VARARGS|METH_KEYWORDS, \"S.ndr_unpack(class, blob, allow_remaining=False) -> None\\nNDR unpack\" },");
-               $self->pidl("{ \"__ndr_print__\", (PyCFunction)py_$name\_ndr_print, METH_VARARGS, \"S.ndr_print(object) -> None\\nNDR print\" },");
+               $self->pidl("{ \"__ndr_print__\", (PyCFunction)py_$name\_ndr_print, METH_NOARGS, \"S.ndr_print(object) -> None\\nNDR print\" },");
                $self->pidl("{ NULL, NULL, 0, NULL }");
                $self->deindent;
                $self->pidl("};");
@@ -570,6 +570,12 @@ sub PythonFunctionPackIn($$$)
                        my $val = "PyList_GET_SIZE($py_var)";
                        if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
                                $self->pidl("r->in.$e->{NAME} = talloc_ptrtype(r, r->in.$e->{NAME});");
+                               $self->pidl("if (r->in.$e->{NAME} == NULL) {");
+                               $self->indent;
+                               $self->pidl("PyErr_NoMemory();");
+                               $self->pidl($fail);
+                               $self->deindent;
+                               $self->pidl("}");
                                $self->pidl("*r->in.$e->{NAME} = $val;");
                        } else {
                                $self->pidl("r->in.$e->{NAME} = $val;");
@@ -960,6 +966,55 @@ sub assign($$$)
        }
 }
 
+sub ConvertStringFromPythonData($$$$$)
+{
+       my ($self, $mem_ctx, $py_var, $target, $fail) = @_;
+
+       $self->pidl("{");
+       $self->indent;
+       $self->pidl("const char *test_str;");
+       $self->pidl("const char *talloc_str;");
+       $self->pidl("PyObject *unicode = NULL;");
+       $self->pidl("if (PyUnicode_Check($py_var)) {");
+       $self->indent;
+       # FIXME: Use Unix charset setting rather than utf-8
+       $self->pidl("unicode = PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\");");
+       $self->pidl("if (unicode == NULL) {");
+       $self->indent;
+       $self->pidl("PyErr_NoMemory();");
+       $self->pidl("$fail");
+       $self->deindent;
+       $self->pidl("}");
+
+       $self->pidl("test_str = PyString_AS_STRING(unicode);");
+       $self->deindent;
+       $self->pidl("} else if (PyString_Check($py_var)) {");
+       $self->indent;
+       $self->pidl("test_str = PyString_AS_STRING($py_var);");
+       $self->deindent;
+       $self->pidl("} else {");
+       $self->indent;
+       $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected string or unicode object, got %s\", Py_TYPE($py_var)->tp_name);");
+       $self->pidl("$fail");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("talloc_str = talloc_strdup($mem_ctx, test_str);");
+       $self->pidl("if (unicode != NULL) {");
+       $self->indent;
+       $self->pidl("Py_DECREF(unicode);");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("if (talloc_str == NULL) {");
+       $self->indent;
+       $self->pidl("PyErr_NoMemory();");
+       $self->pidl("$fail");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("$target = talloc_str;");
+       $self->deindent;
+       $self->pidl("}");
+}
+
 sub ConvertObjectFromPythonData($$$$$$;$)
 {
        my ($self, $mem_ctx, $cvar, $ctype, $target, $fail, $location) = @_;
@@ -978,21 +1033,21 @@ sub ConvertObjectFromPythonData($$$$$$;$)
        my $ctype_alias = "";
        my $uint_max = "";
        if ($actual_ctype->{TYPE} eq "ENUM") {
-               # Importantly, ENUM values are unsigned in pidl, and
-               # typically map to uint32
-               $ctype_alias = enum_type_fn($actual_ctype);
+               # Importantly, ENUM values are unsigned in pidl, and
+               # typically map to uint32
+               $ctype_alias = enum_type_fn($actual_ctype);
        } elsif ($actual_ctype->{TYPE} eq "BITMAP") {
-               $ctype_alias = bitmap_type_fn($actual_ctype);
+               $ctype_alias = bitmap_type_fn($actual_ctype);
        } elsif ($actual_ctype->{TYPE} eq "SCALAR") {
-               $ctype_alias = expandAlias($actual_ctype->{NAME});
+               $ctype_alias = expandAlias($actual_ctype->{NAME});
        }
 
        # This is the unsigned Python Integer -> C integer validation
-       # case.  The signed case is below.
+       # case.  The signed case is below.
        if ($ctype_alias  =~ /^(uint[0-9]*|hyper|udlong|udlongr
-                                |NTTIME_hyper|NTTIME|NTTIME_1sec
-                                |uid_t|gid_t)$/x) {
-               $self->pidl("{");
+                               |NTTIME_hyper|NTTIME|NTTIME_1sec
+                               |uid_t|gid_t)$/x) {
+               $self->pidl("{");
                $self->indent;
                $self->pidl("const unsigned long long uint_max = ndr_sizeof2uintmax(sizeof($target));");
                $self->pidl("if (PyLong_Check($cvar)) {");
@@ -1043,7 +1098,7 @@ sub ConvertObjectFromPythonData($$$$$$;$)
        # above, so while it looks like a duplicate, it is not
        # actually a duplicate.
        if ($ctype_alias  =~ /^(dlong|char|int[0-9]*|time_t)$/x) {
-               $self->pidl("{");
+               $self->pidl("{");
                $self->indent;
                $self->pidl("const long long int_max = ndr_sizeof2intmax(sizeof($target));");
                $self->pidl("const long long int_min = -int_max - 1;");
@@ -1114,33 +1169,17 @@ sub ConvertObjectFromPythonData($$$$$$;$)
        }
 
        if ($actual_ctype->{TYPE} eq "SCALAR" and
-               ($actual_ctype->{NAME} eq "string" or $actual_ctype->{NAME} eq "nbt_string" or $actual_ctype->{NAME} eq "nbt_name" or $actual_ctype->{NAME} eq "wrepl_nbt_name")) {
-               $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));");
-               return;
-       }
-
-       if ($actual_ctype->{TYPE} eq "SCALAR" and ($actual_ctype->{NAME} eq "dns_string" or $actual_ctype->{NAME} eq "dns_name")) {
-               $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));");
-               return;
-       }
-
-       if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
-               $self->pidl("$target = PyString_AS_STRING($cvar);");
-               return;
-       }
-
-       if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv6address") {
-               $self->pidl("$target = PyString_AsString($cvar);");
-               return;
-       }
-
-       if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_name") {
-               $self->pidl("$target = PyString_AS_STRING($cvar);");
-               return;
-       }
-
-       if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_string") {
-               $self->pidl("$target = PyString_AS_STRING($cvar);");
+               ($actual_ctype->{NAME} eq "string"
+                or $actual_ctype->{NAME} eq "nbt_string"
+                or $actual_ctype->{NAME} eq "nbt_name"
+                or $actual_ctype->{NAME} eq "wrepl_nbt_name"
+                or $actual_ctype->{NAME} eq "dns_string"
+                or $actual_ctype->{NAME} eq "dnsp_string"
+                or $actual_ctype->{NAME} eq "dns_name"
+                or $actual_ctype->{NAME} eq "ipv4address"
+                or $actual_ctype->{NAME} eq "ipv6address"
+                or $actual_ctype->{NAME} eq "dnsp_name")) {
+               $self->ConvertStringFromPythonData($mem_ctx, $cvar, $target, $fail);
                return;
        }
 
@@ -1185,6 +1224,14 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
                $pl = GetPrevLevel($e, $pl);
        }
 
+        $self->pidl("if ($py_var == NULL) {");
+        $self->indent;
+        $self->pidl("PyErr_Format(PyExc_AttributeError, \"Cannot delete NDR object: " .
+                    mapTypeName($var_name) . "\");");
+        $self->pidl($fail);
+        $self->deindent;
+        $self->pidl("}");
+
        if ($l->{TYPE} eq "POINTER") {
                if ($l->{POINTER_TYPE} ne "ref") {
                        $self->pidl("if ($py_var == Py_None) {");
@@ -1198,9 +1245,21 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
                # then this is where we would need to allocate it
                if ($l->{POINTER_TYPE} eq "ref") {
                        $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);");
+                       $self->pidl("if ($var_name == NULL) {");
+                       $self->indent;
+                       $self->pidl("PyErr_NoMemory();");
+                       $self->pidl($fail);
+                       $self->deindent;
+                       $self->pidl("}");
                } elsif ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::is_scalar($nl->{DATA_TYPE})
                         and not Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) {
                        $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);");
+                       $self->pidl("if ($var_name == NULL) {");
+                       $self->indent;
+                       $self->pidl("PyErr_NoMemory();");
+                       $self->pidl($fail);
+                       $self->deindent;
+                       $self->pidl("}");
                } else {
                        $self->pidl("$var_name = NULL;");
                }
@@ -1218,21 +1277,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
                }
 
                if (is_charset_array($e, $l)) {
-                       $self->pidl("if (PyUnicode_Check($py_var)) {");
-                       $self->indent;
-                       # FIXME: Use Unix charset setting rather than utf-8
-                       $self->pidl($var_name . " = PyString_AS_STRING(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));");
-                       $self->deindent;
-                       $self->pidl("} else if (PyString_Check($py_var)) {");
-                       $self->indent;
-                       $self->pidl($var_name . " = PyString_AS_STRING($py_var);");
-                       $self->deindent;
-                       $self->pidl("} else {");
-                       $self->indent;
-                       $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected string or unicode object, got %s\", Py_TYPE($py_var)->tp_name);");
-                       $self->pidl("$fail");
-                       $self->deindent;
-                       $self->pidl("}");
+                       $self->ConvertStringFromPythonData($mem_ctx, $py_var, $var_name, $fail);
                } else {
                        my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}";
                        $self->pidl("PY_CHECK_TYPE(&PyList_Type, $py_var, $fail);");
@@ -1520,7 +1565,7 @@ sub Parse($$$$$)
 #include \"$ndr_hdr\"
 
 /*
- * These functions are here to ensure they can be optomised out by
+ * These functions are here to ensure they can be optimized out by
  * the compiler based on the constant input values
  */