pyapi FEATURE finished NETCONF error-reply wrapper

- includes example
diff --git a/python/err.c b/python/err.c
index 61f9e83..461086f 100644
--- a/python/err.c
+++ b/python/err.c
@@ -33,7 +33,73 @@
 static PyObject *
 ncErrStr(ncErrObject *self)
 {
-    return PyUnicode_FromFormat("NETCONF error-reply: %s", self->err->message);
+    uint16_t u, f = 0;
+    char *str = NULL;
+
+    if (self->err->type) {
+        asprintf(&str, "\"type\":\"%s\"", self->err->type);
+    }
+    if (self->err->tag) {
+        asprintf(&str, "%s%s\"tag\":\"%s\"", str ? str : "", str ? "," : "", self->err->tag);
+    }
+    if (self->err->severity) {
+        asprintf(&str, "%s%s\"severity\":\"%s\"", str ? str : "", str ? "," : "", self->err->severity);
+    }
+    if (self->err->apptag) {
+        asprintf(&str, "%s%s\"app-tag\":\"%s\"", str ? str : "", str ? "," : "", self->err->apptag);
+    }
+    if (self->err->path) {
+        asprintf(&str, "%s%s\"path\":\"%s\"", str ? str : "", str ? "," : "", self->err->path);
+    }
+    if (self->err->message) {
+        asprintf(&str, "%s%s\"message\":\"%s", str ? str : "", str ? "," : "", self->err->message);
+        if (self->err->message_lang) {
+            asprintf(&str, "%s (%s)\"", str, self->err->message_lang);
+        } else {
+            asprintf(&str, "%s\"", str);
+        }
+    }
+    if (self->err->sid || self->err->attr || self->err->elem || self->err->ns || self->err->other) {
+        asprintf(&str, "%s%s\"info\":{", str ? str : "", str ? "," : "");
+
+        if (self->err->sid) {
+            asprintf(&str, "%s%s\"session-id\":\"%s\"", str, f ? "," : "", self->err->sid);
+            f = 1;
+        }
+        if (self->err->attr_count) {
+            asprintf(&str, "%s%s\"bad-attr\":[", str, f ? "," : "");
+            for (u = 0; u < self->err->attr_count; u++) {
+                asprintf(&str, "%s%s\"%s\"", str, u ? "," : "", self->err->attr[u]);
+            }
+            asprintf(&str, "%s]", str);
+            f = 1;
+        }
+        if (self->err->elem_count) {
+            asprintf(&str, "%s%s\"bad-element\":[", str, f ? "," : "");
+            for (u = 0; u < self->err->elem_count; u++) {
+                asprintf(&str, "%s%s\"%s\"", str, u ? "," : "", self->err->elem[u]);
+            }
+            asprintf(&str, "%s]", str);
+            f = 1;
+        }
+        if (self->err->ns_count) {
+            asprintf(&str, "%s%s\"bad-namespace\":[", str, f ? "," : "");
+            for (u = 0; u < self->err->ns_count; u++) {
+                asprintf(&str, "%s%s\"%s\"", str, u ? "," : "", self->err->ns[u]);
+            }
+            asprintf(&str, "%s]", str);
+            f = 1;
+        }
+        if (self->err->other_count) {
+            for (u = 0; u < self->err->other_count; u++) {
+                asprintf(&str, "%s%s\"%s\":\"%s\"", str, f ? "," : "", self->err->other[u]->name, self->err->other[u]->content);
+            }
+            f = 1;
+        }
+
+        asprintf(&str, "%s}", str);
+    }
+    return PyUnicode_FromFormat("{%s}", str);
 }
 
 /*
@@ -59,6 +125,33 @@
 }
 
 static PyObject *
+ncErrGetSeverity(ncErrObject *self, void *closure)
+{
+    if (!self->err->severity) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromString(self->err->severity);
+}
+
+static PyObject *
+ncErrGetAppTag(ncErrObject *self, void *closure)
+{
+    if (!self->err->apptag) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromString(self->err->apptag);
+}
+
+static PyObject *
+ncErrGetPath(ncErrObject *self, void *closure)
+{
+    if (!self->err->path) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromString(self->err->path);
+}
+
+static PyObject *
 ncErrGetMessage(ncErrObject *self, void *closure)
 {
     if (!self->err->message) {
@@ -67,6 +160,87 @@
     return PyUnicode_FromString(self->err->message);
 }
 
+static PyObject *
+ncErrGetMessageLang(ncErrObject *self, void *closure)
+{
+    if (!self->err->message_lang) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromString(self->err->message_lang);
+}
+
+static PyObject *
+ncErrGetSID(ncErrObject *self, void *closure)
+{
+    if (!self->err->sid) {
+        Py_RETURN_NONE;
+    }
+    return PyUnicode_FromString(self->err->sid);
+}
+
+static PyObject *
+ncErrGetBadAttr(ncErrObject *self, void *closure)
+{
+    PyObject *list;
+    uint16_t u;
+
+    if (!self->err->attr_count) {
+        Py_RETURN_NONE;
+    }
+
+    list = PyList_New(self->err->attr_count);
+    if (!list) {
+        return NULL;
+    }
+    for (u = 0; u < self->err->attr_count; u++) {
+        PyList_SET_ITEM(list, u, PyUnicode_FromString(self->err->attr[u]));
+    }
+
+    return list;
+}
+
+static PyObject *
+ncErrGetBadElem(ncErrObject *self, void *closure)
+{
+    PyObject *list;
+    uint16_t u;
+
+    if (!self->err->elem_count) {
+        Py_RETURN_NONE;
+    }
+
+    list = PyList_New(self->err->elem_count);
+    if (!list) {
+        return NULL;
+    }
+    for (u = 0; u < self->err->elem_count; u++) {
+        PyList_SET_ITEM(list, u, PyUnicode_FromString(self->err->elem[u]));
+    }
+
+    return list;
+}
+
+static PyObject *
+ncErrGetBadNS(ncErrObject *self, void *closure)
+{
+    PyObject *list;
+    uint16_t u;
+
+    if (!self->err->ns_count) {
+        Py_RETURN_NONE;
+    }
+
+    list = PyList_New(self->err->ns_count);
+    if (!list) {
+        return NULL;
+    }
+    for (u = 0; u < self->err->ns_count; u++) {
+        PyList_SET_ITEM(list, u, PyUnicode_FromString(self->err->ns[u]));
+    }
+
+    return list;
+}
+
 /*
  * Callback structures
  */
@@ -74,7 +248,15 @@
 static PyGetSetDef ncErrGetSetters[] = {
     {"type", (getter)ncErrGetType, NULL, "<error-type>", NULL},
     {"tag", (getter)ncErrGetTag, NULL, "<error-tag>", NULL},
+    {"severity", (getter)ncErrGetSeverity, NULL, "<error-severity>", NULL},
+    {"app-tag", (getter)ncErrGetAppTag, NULL, "<error-app-tag>", NULL},
+    {"path", (getter)ncErrGetPath, NULL, "<error-path>", NULL},
     {"message", (getter)ncErrGetMessage, NULL, "<error-message>", NULL},
+    {"lang", (getter)ncErrGetMessageLang, NULL, "<error-message xml:lang=\" \">", NULL},
+    {"session-id", (getter)ncErrGetSID, NULL, "<error-info><session-id/></error-info>", NULL},
+    {"bad-attr", (getter)ncErrGetBadAttr, NULL, "<error-info><bad-attr/></error-info>", NULL},
+    {"bad-elem", (getter)ncErrGetBadElem, NULL, "<error-info><bad-element/></error-info>", NULL},
+    {"bad-namespace", (getter)ncErrGetBadNS, NULL, "<error-info><bad-namespace/></error-info>", NULL},
     {NULL} /* Sentinel */
 };
 
diff --git a/python/examples/get.py b/python/examples/get.py
new file mode 100755
index 0000000..5fa0bc4
--- /dev/null
+++ b/python/examples/get.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python3
+
+import sys
+import os
+import getpass
+import libyang as ly
+import netconf2 as nc
+
+def interactive_auth(name, instruct, prompt, data):
+	print(name)
+	return getpass.getpass(prompt)
+
+def password_auth(user, host, data):
+	return getpass.getpass((user if user else os.getlogin()) + '@' + host + ' password : ')
+
+#
+# get know where to connect
+#
+host = input("hostname: ")
+try:
+	port = int(input("port    : "))
+except:
+	port = 0;
+user = input("username: ")
+
+#
+# set SSH settings
+#
+if user:
+	ssh = nc.SSH(username=user)
+else:
+	ssh = nc.SSH()
+ssh.setAuthInteractiveClb(interactive_auth)
+ssh.setAuthPasswordClb(password_auth)
+
+#
+# create NETCONF session to the server
+#
+try:
+	session = nc.Session(host, port, ssh)
+except Exception as e:
+	print(e)
+	sys.exit(1)
+
+# perform <get> and print result
+try:
+        data = session.rpcGet()
+except nc.ReplyError as e:
+        reply = {'success':False, 'error': []}
+        for err in e.args[0]:
+                reply['error'].append(json.loads(str(err)))
+        print(json.dumps(reply))
+        sys.exit(1)
+
+print(data.print_mem(ly.LYD_XML, ly.LYP_FORMAT | ly.LYP_WITHSIBLINGS))