hardened the addChild function added accessors needed for xmlNode, a bit

* tree.c: hardened the addChild function
* python/generator.py python/libxml.c python/libxml2-python-api.xml
  python/libxml2class.txt python/libxml_wrap.h python/TODO:
  added accessors needed for xmlNode, a bit more testing and
  extension of interfaces
* python/tests/Makefile.am python/tests/build.py: added a test
  build from scratch/save/load/check
Daniel
diff --git a/python/generator.py b/python/generator.py
index 3d28200..e665a87 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -350,7 +350,7 @@
     elif py_types.has_key(ret[0]):
 	(f, t, n, c) = py_types[ret[0]]
 	c_return = "    %s c_retval;\n" % (ret[0])
-	if file == "python_accessor":
+	if file == "python_accessor" and ret[2] != None:
 	    c_call = "\n    c_retval = %s->%s;\n" % (args[0][0], ret[2])
 	else:
 	    c_call = "\n    c_retval = %s(%s);\n" % (name, c_call);
@@ -380,6 +380,9 @@
     if file == "python":
         # Those have been manually generated
 	return 1
+    if file == "python_accessor" and ret[0] != "void" and ret[2] == None:
+        # Those have been manually generated
+	return 1
 
     output.write("PyObject *\n")
     output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name))
@@ -559,6 +562,9 @@
     elif name[0:12] == "xmlParserSet" and file == "python_accessor":
         func = name[12:]
         func = string.lower(func[0:1]) + func[1:]
+    elif name[0:10] == "xmlNodeGet" and file == "python_accessor":
+        func = name[10:]
+        func = string.lower(func[0:1]) + func[1:]
     elif name[0:l] == classe:
 	func = name[l:]
 	func = string.lower(func[0:1]) + func[1:]
@@ -690,6 +696,13 @@
 	    n = n + 1
 	classes.write("):\n")
 	writeDoc(name, args, '    ', classes);
+
+	for arg in args:
+	    if classes_type.has_key(arg[1]):
+		classes.write("    if %s == None: %s__o = None\n" %
+		              (arg[0], arg[0]))
+		classes.write("    else: %s__o = %s%s\n" %
+		              (arg[0], arg[0], classes_type[arg[1]][0]))
 	if ret[0] != "void":
 	    classes.write("    ret = ");
 	else:
@@ -701,7 +714,7 @@
 		classes.write(", ");
 	    classes.write("%s" % arg[0])
 	    if classes_type.has_key(arg[1]):
-		classes.write(classes_type[arg[1]][0])
+		classes.write("__o");
 	    n = n + 1
 	classes.write(")\n");
 	if ret[0] != "void":
@@ -771,6 +784,15 @@
 		n = n + 1
 	    classes.write("):\n")
 	    writeDoc(name, args, '        ', classes);
+	    n = 0
+	    for arg in args:
+		if classes_type.has_key(arg[1]):
+		    if n != index:
+			classes.write("        if %s == None: %s__o = None\n" %
+				      (arg[0], arg[0]))
+			classes.write("        else: %s__o = %s%s\n" %
+				      (arg[0], arg[0], classes_type[arg[1]][0]))
+		n = n + 1
 	    if ret[0] != "void":
 	        classes.write("        ret = ");
 	    else:
@@ -782,10 +804,12 @@
 		    classes.write(", ");
 	        if n != index:
 		    classes.write("%s" % arg[0])
+		    if classes_type.has_key(arg[1]):
+			classes.write("__o");
 		else:
 		    classes.write("self");
-		if classes_type.has_key(arg[1]):
-		    classes.write(classes_type[arg[1]][0])
+		    if classes_type.has_key(arg[1]):
+			classes.write(classes_type[arg[1]][0])
 		n = n + 1
 	    classes.write(")\n");
 	    if ret[0] != "void":
diff --git a/python/libxml.c b/python/libxml.c
index e37038a..e167fcf 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -810,6 +810,51 @@
 
 /************************************************************************
  *									*
+ *			Specific accessor functions			*
+ *									*
+ ************************************************************************/
+PyObject *
+libxml_xmlNodeGetNsDefs(PyObject *self, PyObject *args) {
+    PyObject *py_retval;
+    xmlNsPtr c_retval;
+    xmlNodePtr node;
+    PyObject *pyobj_node;
+
+    if (!PyArg_ParseTuple(args, "O:xmlNodeGetNsDefs", &pyobj_node))
+        return(NULL);
+    node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
+
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    c_retval = node->nsDef;
+    py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
+    return(py_retval);
+}
+
+PyObject *
+libxml_xmlNodeGetNs(PyObject *self, PyObject *args) {
+    PyObject *py_retval;
+    xmlNsPtr c_retval;
+    xmlNodePtr node;
+    PyObject *pyobj_node;
+
+    if (!PyArg_ParseTuple(args, "O:xmlNodeGetNs", &pyobj_node))
+        return(NULL);
+    node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
+
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    c_retval = node->ns;
+    py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
+    return(py_retval);
+}
+
+/************************************************************************
+ *									*
  *			The registration stuff				*
  *									*
  ************************************************************************/
diff --git a/python/libxml2-python-api.xml b/python/libxml2-python-api.xml
index a830c75..94d8f84 100644
--- a/python/libxml2-python-api.xml
+++ b/python/libxml2-python-api.xml
@@ -90,5 +90,15 @@
       <info>dump the memory allocated in the file .memdump</info>
       <return type='void'/>
     </function>
+    <function name='xmlNodeGetNs' file='python_accessor'>
+      <info>Get the namespace of a node</info>
+      <return type='xmlNsPtr' info="The namespace or None"/>
+      <arg name='node' type='xmlNodePtr' info='the node'/>
+    </function>
+    <function name='xmlNodeGetNsDefs' file='python_accessor'>
+      <info>Get the namespace of a node</info>
+      <return type='xmlNsPtr' info="The namespace or None"/>
+      <arg name='node' type='xmlNodePtr' info='the node'/>
+    </function>
   </symbols>
 </api>
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index cb12a2f..749efdc 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -155,6 +155,9 @@
 
 
 Class xmlNode(xmlCore)
+    # accessors
+    ns()
+    nsDefs()
 
     # functions from module debugXML
     lsCountNode()
diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h
index 68daf01..679260a 100644
--- a/python/libxml_wrap.h
+++ b/python/libxml_wrap.h
@@ -15,20 +15,25 @@
 #include <libxml/xinclude.h>
 #include <libxml/xpointer.h>
 
-#define PyxmlNode_Get(v) (((PyxmlNode_Object *)(v))->obj)
+#define PyxmlNode_Get(v) (((v) == Py_None) ? NULL : \
+	(((PyxmlNode_Object *)(v))->obj))
 
 typedef struct {
     PyObject_HEAD
     xmlNodePtr obj;
 } PyxmlNode_Object;
 
-#define PyxmlXPathContext_Get(v) (((PyxmlXPathContext_Object *)(v))->obj)
+#define PyxmlXPathContext_Get(v) (((v) == Py_None) ? NULL : \
+	(((PyxmlXPathContext_Object *)(v))->obj))
+
 typedef struct {
     PyObject_HEAD
     xmlXPathContextPtr obj;
 } PyxmlXPathContext_Object;
 
-#define PyparserCtxt_Get(v) (((PyparserCtxt_Object *)(v))->obj)
+#define PyparserCtxt_Get(v) (((v) == Py_None) ? NULL : \
+        (((PyparserCtxt_Object *)(v))->obj))
+
 typedef struct {
     PyObject_HEAD
     xmlParserCtxtPtr obj;
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
index 76bf897..e468e6c 100644
--- a/python/tests/Makefile.am
+++ b/python/tests/Makefile.am
@@ -1,6 +1,7 @@
 EXAMPLE_DIR = $(prefix)/share/doc/libxml2-python-$(LIBXML_VERSION)/examples
 
 TESTS=		\
+    build.py	\
     tst.py	\
     tstxpath.py	\
     xpathext.py	\
diff --git a/python/tests/build.py b/python/tests/build.py
new file mode 100755
index 0000000..bfc776c
--- /dev/null
+++ b/python/tests/build.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python -u
+import libxml2
+import sys
+
+# Memory debug specific
+libxml2.debugMemory(1)
+
+doc = libxml2.newDoc("1.0")
+comment = doc.newDocComment("This is a generated document")
+doc.addChild(comment)
+pi = libxml2.newPI("test", "PI content")
+doc.addChild(pi)
+root = doc.newChild(None, "doc", None)
+ns = root.newNs("http://example.com/doc", "my")
+root.setNs(ns)
+elem = root.newChild(None, "foo", "bar")
+elem.setBase("http://example.com/imgs")
+elem.setProp("img", "image.gif")
+doc.saveFile("tmp.xml")
+doc.freeDoc()
+
+doc = libxml2.parseFile("tmp.xml")
+comment = doc.children
+if comment.type != "comment" or \
+   comment.content != "This is a generated document":
+   print "error rereading comment"
+   sys.exit(1)
+pi = comment.next
+if pi.type != "pi" or pi.name != "test" or pi.content != "PI content":
+   print "error rereading PI"
+   sys.exit(1)
+root = pi.next
+if root.name != "doc":
+   print "error rereading root"
+   sys.exit(1)
+ns = root.ns()
+if ns.name != "my" or ns.content != "http://example.com/doc":
+   print "error rereading namespace"
+   sys.exit(1)
+elem = root.children
+if elem.name != "foo":
+   print "error rereading elem"
+   sys.exit(1)
+if elem.getBase(None) != "http://example.com/imgs":
+   print "error rereading base"
+   sys.exit(1)
+if elem.prop("img") != "image.gif":
+   print "error rereading property"
+   sys.exit(1)
+
+doc.freeDoc()
+
+# Memory debug specific
+libxml2.cleanupParser()
+if libxml2.debugMemory(1) == 0:
+    print "OK"
+else:
+    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
+    libxml2.dumpMemory()