Progressing through the TODOs, class description output, extra XML API,

* libxml.spec.in python/Makefile.am python/TODO python/generator.py
  python/libxml.c python/libxml2-python-api.xml
  python/libxml2class.txt: Progressing through the TODOs, class
  description output, extra XML API, RPM now builds the wrappers
  for all python installed versions
Daniel
diff --git a/python/Makefile.am b/python/Makefile.am
index 43bc4b0..c9d9f84 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -34,7 +34,7 @@
 	$(CC) $(SHCFLAGS) -c -o libxml2-py.o $(srcdir)/libxml2-py.c
 
 GENERATE = generator.py
-API_DESC = $(top_srcdir)/doc/libxml2-api.xml
+API_DESC = $(top_srcdir)/doc/libxml2-api.xml $(srcdir)/libxml2-python-api.xml
 GENERATED= $(srcdir)/libxml2class.py \
            $(srcdir)/libxml2-export.c \
 	   $(srcdir)/libxml2-py.c \
diff --git a/python/TODO b/python/TODO
index b1fa734..0fc997b 100644
--- a/python/TODO
+++ b/python/TODO
@@ -1,6 +1,6 @@
              TODO for the libxml2 Python wrappers
 
-               $Id$
+         $Id$
 
 Things to do:
 -------------
@@ -8,13 +8,8 @@
 - handling of node.content
 - SAX interfaces
 - error redirections and preformat
-- class hierarchy:
-  + get the generator to output a classes.txt description
-- extensions based on a python.xml description of the new specific
-  interfaces
 - memory debug interfaces
 - enums -> libxml.py
-- spec file: automatically generate for pythonX.Y if found
 - access to XPath variables
 - parserCtxt exposure:
   - entry points
@@ -33,9 +28,18 @@
 -----
 - class hierarchy:
   + make specific node type inherit from xmlNode
+    done, had to sort the classes in the output
+  + get the generator to output a classes.txt description
+    done libxml2class.txt
 - add regression tests
    - tests/Makefile.am: export the Python class path
    - xpath queries
    - xpath extension
+- extensions based on a python.xml description of the new specific
+  interfaces
+   file libxml2-python-api.xml , first entry is xmlRegisterXPathFunction
+- spec file: automatically generate for pythonX.Y if found
+  Done, a bit ugly by running new makes in %install for each level
+  found.
 
 Daniel Veillard
diff --git a/python/generator.py b/python/generator.py
index ee477b0..80dca7b 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -361,7 +361,13 @@
 
     include.write("PyObject * ")
     include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name))
+
     export.write("    { \"%s\", libxml_%s, METH_VARARGS },\n" % (name, name))
+
+    if file == "python":
+        # Those have been manually generated
+	return 1
+
     output.write("PyObject *\n")
     output.write("libxml_%s(PyObject *self, PyObject *args) {\n" % (name))
     if ret[0] != 'void':
@@ -391,7 +397,22 @@
 except IOError, msg:
     print file, ":", msg
 
-print "Found %d functions in libxml2-api.xml" % (len(functions.keys()))
+n = len(functions.keys())
+print "Found %d functions in libxml2-api.xml" % (n)
+
+py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
+try:
+    f = open("libxml2-python-api.xml")
+    data = f.read()
+    (parser, target)  = getparser()
+    parser.feed(data)
+    parser.close()
+except IOError, msg:
+    print file, ":", msg
+
+
+print "Found %d functions in libxml2-python-api.xml" % (
+      len(functions.keys()) - n)
 nb_wrap = 0
 failed = 0
 skipped = 0
@@ -487,8 +508,12 @@
 # Build the list of C types to look for ordered to start with primary classes
 #
 ctypes = []
+classes_list = []
 ctypes_processed = {}
+classes_processed = {}
 for classe in primary_classes:
+    classes_list.append(classe)
+    classes_processed[classe] = ()
     for type in classes_type.keys():
         tinfo = classes_type[type]
 	if tinfo[2] == classe:
@@ -498,6 +523,10 @@
     if ctypes_processed.has_key(type):
         continue
     tinfo = classes_type[type]
+    if not classes_processed.has_key(tinfo[2]):
+        classes_list.append(tinfo[2])
+	classes_processed[tinfo[2]] = ()
+	
     ctypes.append(type)
     ctypes_processed[type] = ()
 
@@ -511,6 +540,9 @@
     elif name[0:l] == classe:
 	func = name[l:]
 	func = string.lower(func[0:1]) + func[1:]
+    elif name[0:7] == "libxml_":
+	func = name[7:]
+	func = string.lower(func[0:1]) + func[1:]
     elif name[0:6] == "xmlGet":
 	func = name[6:]
 	func = string.lower(func[0:1]) + func[1:]
@@ -656,7 +688,7 @@
 	classes.write("\n");
 
 txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
-for classname in function_classes.keys():
+for classname in classes_list:
     if classname == "None":
         pass
     else:
diff --git a/python/libxml.c b/python/libxml.c
index 61992c6..fcd8df8 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -419,6 +419,7 @@
         libxml_xpathCallbacks[i].name = xmlStrdup(name);
         libxml_xpathCallbacks[i].ns_uri = xmlStrdup(ns_uri);
 	libxml_xpathCallbacks[i].function = pyobj_f;
+	c_retval = 1;
     }
 done:
     py_retval = libxml_intWrap((int) c_retval);
diff --git a/python/libxml2-python-api.xml b/python/libxml2-python-api.xml
new file mode 100644
index 0000000..29dca23
--- /dev/null
+++ b/python/libxml2-python-api.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<api name='libxml2-python'>
+  <files>
+    <file name='python'>
+     <exports symbol='libxml_registerXPathFunction'/>
+    </file>
+  </files>
+  <symbols>
+    <function name='xmlRegisterXPathFunction' file='python'>
+      <info>Register a Python written function to the XPath interpreter</info>
+      <return type='int' info="1 in case of success, 0 or -1 in case of error"/>
+      <arg name='ctx' type='xmlXPathContextPtr' info='the xpathContext'/>
+      <arg name='name' type='xmlChar *' info='the function name'/>
+      <arg name='ns_uri' type='xmlChar *' info='the namespace or NULL'/>
+      <arg name='f' type='pythonObject' info='the python function'/>
+    </function>
+  </symbols>
+</api>
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index c8e2359..a5c45d3 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -131,85 +131,6 @@
 # Set of classes of the module
 #
 
-Class xpathContext()
-
-    # functions from module xpath
-    xpathEval()
-    xpathEvalExpression()
-
-    # functions from module xpathInternals
-    xpathFreeContext()
-    xpathNsLookup()
-    xpathRegisterAllFunctions()
-    xpathRegisterNs()
-    xpathRegisteredFuncsCleanup()
-    xpathRegisteredNsCleanup()
-    xpathRegisteredVariablesCleanup()
-    xpathVariableLookup()
-    xpathVariableLookupNS()
-
-
-Class xmlDoc(xmlNode)
-
-    # functions from module HTMLparser
-    htmlAutoCloseTag()
-    htmlIsAutoClosed()
-
-    # functions from module HTMLtree
-    htmlGetMetaEncoding()
-    htmlSaveFile()
-    htmlSaveFileEnc()
-    htmlSaveFileFormat()
-    htmlSetMetaEncoding()
-
-    # functions from module entities
-    addDocEntity()
-    addDtdEntity()
-    docEntity()
-    dtdEntity()
-    encodeEntities()
-    encodeEntitiesReentrant()
-    encodeSpecialChars()
-    parameterEntity()
-
-    # functions from module tree
-    copyDoc()
-    createIntSubset()
-    docCompressMode()
-    freeDoc()
-    getRootElement()
-    intSubset()
-    newCDataBlock()
-    newCharRef()
-    newDocComment()
-    newDocFragment()
-    newDocNode()
-    newDocProp()
-    newDocRawNode()
-    newDocText()
-    newDocTextLen()
-    newDtd()
-    newGlobalNs()
-    newReference()
-    saveFile()
-    saveFileEnc()
-    saveFormatFile()
-    saveFormatFileEnc()
-    setDocCompressMode()
-    stringGetNodeList()
-    stringLenGetNodeList()
-
-    # functions from module valid
-    ID()
-    isMixedElement()
-    removeID()
-    removeRef()
-
-    # functions from module xinclude
-    xincludeProcess()
-
-    # functions from module xpathInternals
-    xpathNewContext()
 
 
 Class xmlNode(xmlCore)
@@ -290,6 +211,90 @@
     xpathNewValueTree()
 
 
+Class xmlDoc(xmlNode)
+
+    # functions from module HTMLparser
+    htmlAutoCloseTag()
+    htmlIsAutoClosed()
+
+    # functions from module HTMLtree
+    htmlGetMetaEncoding()
+    htmlSaveFile()
+    htmlSaveFileEnc()
+    htmlSaveFileFormat()
+    htmlSetMetaEncoding()
+
+    # functions from module entities
+    addDocEntity()
+    addDtdEntity()
+    docEntity()
+    dtdEntity()
+    encodeEntities()
+    encodeEntitiesReentrant()
+    encodeSpecialChars()
+    parameterEntity()
+
+    # functions from module tree
+    copyDoc()
+    createIntSubset()
+    docCompressMode()
+    freeDoc()
+    getRootElement()
+    intSubset()
+    newCDataBlock()
+    newCharRef()
+    newDocComment()
+    newDocFragment()
+    newDocNode()
+    newDocProp()
+    newDocRawNode()
+    newDocText()
+    newDocTextLen()
+    newDtd()
+    newGlobalNs()
+    newReference()
+    saveFile()
+    saveFileEnc()
+    saveFormatFile()
+    saveFormatFileEnc()
+    setDocCompressMode()
+    stringGetNodeList()
+    stringLenGetNodeList()
+
+    # functions from module valid
+    ID()
+    isMixedElement()
+    removeID()
+    removeRef()
+
+    # functions from module xinclude
+    xincludeProcess()
+
+    # functions from module xpathInternals
+    xpathNewContext()
+
+
+Class xmlEntity(xmlNode)
+
+
+Class xmlNs(xmlNode)
+
+    # functions from module tree
+    copyNamespace()
+    copyNamespaceList()
+    freeNs()
+    freeNsList()
+    newNode()
+
+
+Class xmlAttr(xmlNode)
+
+    # functions from module tree
+    freeProp()
+    freePropList()
+    removeProp()
+
+
 Class xmlAttribute(xmlNode)
 
 
@@ -306,25 +311,23 @@
     dtdQElementDesc()
 
 
-Class xmlAttr(xmlNode)
-
-    # functions from module tree
-    freeProp()
-    freePropList()
-    removeProp()
-
-
-Class xmlEntity(xmlNode)
-
-
 Class xmlElement(xmlNode)
+Class xpathContext()
 
+    # functions from module python
+    registerXPathFunction()
 
-Class xmlNs(xmlNode)
+    # functions from module xpath
+    xpathEval()
+    xpathEvalExpression()
 
-    # functions from module tree
-    copyNamespace()
-    copyNamespaceList()
-    freeNs()
-    freeNsList()
-    newNode()
+    # functions from module xpathInternals
+    xpathFreeContext()
+    xpathNsLookup()
+    xpathRegisterAllFunctions()
+    xpathRegisterNs()
+    xpathRegisteredFuncsCleanup()
+    xpathRegisteredNsCleanup()
+    xpathRegisteredVariablesCleanup()
+    xpathVariableLookup()
+    xpathVariableLookupNS()