cleanup added class for parser context, added first cut for push mode

* python/Makefile.am python/types.c: cleanup
* python/libxml.c python/libxml.py python/libxml_wrap.h
  python/generator.py python/libxml2-python-api.xml
  python/libxml2class.txt: added class for parser context, added
  first cut for push mode support. Added a framework to generate
  accessors functions.
* python/tests/Makefile.am python/tests/push.py: added a push
  test
Daniel
diff --git a/ChangeLog b/ChangeLog
index a3c8b1d..800e435 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Sun Feb  3 16:03:55 CET 2002 Daniel Veillard <daniel@veillard.com>
+
+	* python/Makefile.am python/types.c: cleanup
+	* python/libxml.c python/libxml.py python/libxml_wrap.h
+	  python/generator.py python/libxml2-python-api.xml 
+	  python/libxml2class.txt: added class for parser context, added
+	  first cut for push mode support. Added a framework to generate
+	  accessors functions.
+	* python/tests/Makefile.am python/tests/push.py: added a push
+	  test
+
 Sun Feb  3 00:17:26 CET 2002 Daniel Veillard <daniel@veillard.com>
 
 	* python/Makefile.am python/TODO python/libxml.py: fixed a small
diff --git a/python/Makefile.am b/python/Makefile.am
index a76492a..7d02f53 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -10,6 +10,7 @@
 
 EXTRA_DIST = 			\
 	libxml.c		\
+	types.c			\
 	generator.py		\
 	libxml_wrap.h		\
 	libxml.py		\
@@ -22,8 +23,8 @@
 libxml2.py: $(srcdir)/libxml.py libxml2class.py
 	cat $(srcdir)/libxml.py libxml2class.py > libxml2.py
 
-_libxml.so: libxml.o libxml2-py.o
-	$(CC) $(LINK_FLAGS) libxml2-py.o libxml.o $(LIBS) -o _libxml.so
+_libxml.so: libxml.o libxml2-py.o types.o
+	$(CC) $(LINK_FLAGS) libxml.o libxml2-py.o types.o $(LIBS) -o _libxml.so
 else
 all: 
 endif
@@ -31,6 +32,9 @@
 libxml.o: libxml.c libxml2-export.c libxml_wrap.h
 	$(CC) $(SHCFLAGS) -c -o libxml.o $(srcdir)/libxml.c
 
+types.o: types.c libxml_wrap.h
+	$(CC) $(SHCFLAGS) -c -o types.o $(srcdir)/types.c
+
 libxml2-py.o: libxml2-py.c libxml2-py.h libxml_wrap.h
 	$(CC) $(SHCFLAGS) -c -o libxml2-py.o $(srcdir)/libxml2-py.c
 
@@ -44,9 +48,7 @@
 $(GENERATED): $(srcdir)/$(GENERATE) $(API_DESC)
 	cd $(srcdir) && $(PYTHON) $(GENERATE)
 
-dummy:
-
-tests: dummy
+tests: all
 	cd tests && $(MAKE) tests
 
 clean:
diff --git a/python/generator.py b/python/generator.py
index 80dca7b..587528a 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -129,10 +129,13 @@
 	    if self.in_function == 1:
 	        self.function_return_type = None
 	        self.function_return_info = None
+	        self.function_return_field = None
 		if attrs.has_key('type'):
 		    self.function_return_type = attrs['type']
 		if attrs.has_key('info'):
 		    self.function_return_info = attrs['info']
+		if attrs.has_key('field'):
+		    self.function_return_field = attrs['field']
 
 
     def end(self, tag):
@@ -152,7 +155,8 @@
 	elif tag == 'return':
 	    if self.in_function == 1:
 	        self.function_return = [self.function_return_type,
-		                        self.function_return_info]
+		                        self.function_return_info,
+					self.function_return_field]
 	elif tag == 'info':
 	    str = ''
 	    for c in self._data:
@@ -186,8 +190,6 @@
     'int *': "usually a return type",
     'xmlSAXHandlerPtr': "not the proper interface for SAX",
     'htmlSAXHandlerPtr': "not the proper interface for SAX",
-    'xmlParserCtxtPtr': "not the proper interface for the parser",
-    'htmlParserCtxtPtr': "not the proper interface for the parser",
     'xmlRMutexPtr': "thread specific, skipped",
     'xmlMutexPtr': "thread specific, skipped",
     'xmlGlobalStatePtr': "thread specific, skipped",
@@ -257,6 +259,10 @@
     'const htmlNode *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
     'xmlXPathContextPtr':  ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
     'xmlXPathContext *':  ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
+    'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
+    'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
+    'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
+    'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
 }
 
 py_return_types = {
@@ -340,7 +346,10 @@
     elif py_types.has_key(ret[0]):
 	(f, t, n, c) = py_types[ret[0]]
 	c_return = "    %s c_retval;\n" % (ret[0])
-        c_call = "\n    c_retval = %s(%s);\n" % (name, c_call);
+	if file == "python_accessor":
+	    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);
 	ret_convert = "    py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c)
 	ret_convert = ret_convert + "    return(py_retval);\n"
     elif py_return_types.has_key(ret[0]):
@@ -476,6 +485,8 @@
     "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
     "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
     "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
+    "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
+    "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
 }
 
 converter_type = {
@@ -496,6 +507,7 @@
 }
 classes_destructors = {
     "xpathContext": "xmlXPathFreeContext",
+    "parserCtxt": "xmlFreeParserCtxt",
 }
 
 function_classes = {}
@@ -530,13 +542,16 @@
     ctypes.append(type)
     ctypes_processed[type] = ()
 
-def nameFixup(function, classe, type):
+def nameFixup(function, classe, type, file):
     listname = classe + "List"
     ll = len(listname)
     l = len(classe)
     if name[0:l] == listname:
 	func = name[l:]
 	func = string.lower(func[0:1]) + func[1:]
+    elif name[0:12] == "xmlParserGet" and file == "python_accessor":
+        func = name[12:]
+        func = string.lower(func[0:1]) + func[1:]
     elif name[0:l] == classe:
 	func = name[l:]
 	func = string.lower(func[0:1]) + func[1:]
@@ -573,22 +588,22 @@
 
 	if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type:
 	    found = 1
-	    func = nameFixup(name, classe, type)
+	    func = nameFixup(name, classe, type, file)
 	    info = (0, func, name, ret, args, file)
 	    function_classes[classe].append(info)
 	elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type:
 	    found = 1
-	    func = nameFixup(name, classe, type)
+	    func = nameFixup(name, classe, type, file)
 	    info = (1, func, name, ret, args, file)
 	    function_classes[classe].append(info)
 	elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type:
 	    found = 1
-	    func = nameFixup(name, classe, type)
+	    func = nameFixup(name, classe, type, file)
 	    info = (0, func, name, ret, args, file)
 	    function_classes[classe].append(info)
 	elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type:
 	    found = 1
-	    func = nameFixup(name, classe, type)
+	    func = nameFixup(name, classe, type, file)
 	    info = (1, func, name, ret, args, file)
 	    function_classes[classe].append(info)
 	if found == 1:
@@ -601,7 +616,7 @@
         continue
     if name[0:10] == "xmlCharStr":
         continue
-    func = nameFixup(name, "None", file)
+    func = nameFixup(name, "None", file, file)
     info = (0, func, name, ret, args, file)
     function_classes['None'].append(info)
 
@@ -612,6 +627,10 @@
 def functionCompare(info1, info2):
     (index1, func1, name1, ret1, args1, file1) = info1
     (index2, func2, name2, ret2, args2, file2) = info2
+    if file1 == "python_accessor":
+        return -1
+    if file2 == "python_accessor":
+        return 1
     if file1 < file2:
         return -1
     if file1 > file2:
@@ -701,6 +720,12 @@
 	    classes.write("        self._o = None\n")
 	    classes.write("        %s.__init__(self, _obj=_obj)\n\n" % (
 	                  classes_ancestor[classname]))
+	    if classes_ancestor[classname] == "xmlCore" or \
+	       classes_ancestor[classname] == "xmlNode":
+		classes.write("    def __repr__(self):\n")
+		format = "%s:%%s" % (classname)
+		classes.write("        return \"%s\" %% (self.name)\n\n" % (
+			      format))
 	else:
 	    txt.write("Class %s()\n" % (classname))
 	    classes.write("class %s:\n" % (classname))
@@ -713,21 +738,21 @@
 	    classes.write("            _libxml.%s(self._o)\n" %
 	                  classes_destructors[classname]);
 	    classes.write("        self._o = None\n\n");
-	classes.write("    def __repr__(self):\n")
-	format = "%s:%%s" % (classname)
-	classes.write("        return \"%s\" %% (self.name)\n\n" % (
-	              format))
 	flist = function_classes[classname]
 	flist.sort(functionCompare)
 	oldfile = ""
 	for info in flist:
 	    (index, func, name, ret, args, file) = info
 	    if file != oldfile:
-		classes.write("    #\n")
-		classes.write("    # %s functions from module %s\n" % (
-		              classname, file))
-		txt.write("\n    # functions from module %s\n" % file)
-		classes.write("    #\n\n")
+	        if file == "python_accessor":
+		    classes.write("    # accessors for %s\n" % (classname))
+		    txt.write("    # accessors\n")
+		else:
+		    classes.write("    #\n")
+		    classes.write("    # %s functions from module %s\n" % (
+				  classname, file))
+		    txt.write("\n    # functions from module %s\n" % file)
+		    classes.write("    #\n\n")
 	    oldfile = file
 	    classes.write("    def %s(self" % func)
 	    txt.write("    %s()\n" % func);
diff --git a/python/libxml.c b/python/libxml.c
index cca2b04..57e370f 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -1,5 +1,14 @@
+/*
+ * libxml.c: this modules implements the main part of the glue of the
+ *           libxml2 library and the Python interpreter. It provides the
+ *           entry points where an automatically generated stub is either
+ *           unpractical or would not match cleanly the Python model.
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
 #include <Python.h>
-
 #include <libxml/xmlmemory.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -15,277 +24,48 @@
 
 /************************************************************************
  *									*
- *			Per type specific glue				*
+ *		Handling SAX/xmllib/sgmlop callback interfaces		*
  *									*
  ************************************************************************/
-PyObject *
-libxml_intWrap(int val) {
-    PyObject *ret;
 
-#ifdef DEBUG
-    printf("libxml_intWrap: val = %d\n", val);
-#endif
-    ret = PyInt_FromLong((long) val);
-    return(ret);
-}
+typedef struct pySAXhandler {
+    PyObject *startDocument;
+    /* TODO !!! */
+} pySAXhandler, *pySAXhandlerPtr;
+
+/************************************************************************
+ *									*
+ *		Handling of specific parser context			*
+ *									*
+ ************************************************************************/
 
 PyObject *
-libxml_doubleWrap(double val) {
-    PyObject *ret;
+libxml_xmlCreatePushParser(PyObject *self, PyObject *args) {
+    xmlChar *chunk;
+    int size;
+    xmlChar *URI;
+    PyObject *pyobj_SAX;
+    xmlSAXHandlerPtr SAX = NULL;
+    pySAXhandlerPtr SAXdata = NULL; 
+    xmlParserCtxtPtr ret;
+    PyObject *pyret;
 
-#ifdef DEBUG
-    printf("libxml_doubleWrap: val = %f\n", val);
+    if (!PyArg_ParseTuple(args, "Oziz:xmlCreatePushParser", &pyobj_SAX,
+		          &chunk, &size, &URI))
+        return(NULL);
+
+#ifdef DEBUG_ERROR
+    printf("libxml_xmlCreatePushParser(%p, %s, %d, %s) called\n",
+	   pyobj_SAX, chunk, size, URI);
 #endif
-    ret = PyFloat_FromDouble((double) val);
-    return(ret);
-}
-
-PyObject *
-libxml_charPtrWrap(char *str) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlcharPtrWrap: str = %s\n", str);
-#endif
-    if (str == NULL) {
+    if (pyobj_SAX != Py_None) {
+	printf("xmlCreatePushParser: event interface not supported yet !\n");
 	Py_INCREF(Py_None);
 	return(Py_None);
     }
-    /* TODO: look at deallocation */
-    ret = PyString_FromString(str);
-    xmlFree(str);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlCharPtrWrap(xmlChar *str) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlCharPtrWrap: str = %s\n", str);
-#endif
-    if (str == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    /* TODO: look at deallocation */
-    ret = PyString_FromString(str);
-    xmlFree(str);
-    return(ret);
-}
-
-PyObject *
-libxml_constcharPtrWrap(const char *str) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlcharPtrWrap: str = %s\n", str);
-#endif
-    if (str == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    /* TODO: look at deallocation */
-    ret = PyString_FromString(str);
-    return(ret);
-}
-
-PyObject *
-libxml_constxmlCharPtrWrap(const xmlChar *str) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlCharPtrWrap: str = %s\n", str);
-#endif
-    if (str == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    /* TODO: look at deallocation */
-    ret = PyString_FromString(str);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlDocPtrWrap(xmlDocPtr doc) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlDocPtrWrap: doc = %p\n", doc);
-#endif
-    if (doc == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    /* TODO: look at deallocation */
-    ret = PyCObject_FromVoidPtrAndDesc((void *) doc, "xmlDocPtr", NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlNodePtrWrap(xmlNodePtr node) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlNodePtrWrap: node = %p\n", node);
-#endif
-    if (node == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    ret = PyCObject_FromVoidPtrAndDesc((void *) node, "xmlNodePtr", NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlNsPtrWrap(xmlNsPtr ns) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlNsPtrWrap: node = %p\n", ns);
-#endif
-    if (ns == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    ret = PyCObject_FromVoidPtrAndDesc((void *) ns, "xmlNsPtr", NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlAttrPtrWrap(xmlAttrPtr attr) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlAttrNodePtrWrap: attr = %p\n", attr);
-#endif
-    if (attr == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttrPtr", NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlAttributePtrWrap(xmlAttributePtr attr) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlAttributePtrWrap: attr = %p\n", attr);
-#endif
-    if (attr == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttributePtr", NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlElementPtrWrap(xmlElementPtr elem) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlElementNodePtrWrap: elem = %p\n", elem);
-#endif
-    if (elem == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    ret = PyCObject_FromVoidPtrAndDesc((void *) elem, "xmlElementPtr", NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlXPathContextPtrWrap: ctxt = %p\n", ctxt);
-#endif
-    if (ctxt == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, "xmlXPathContextPtr",
-	                               NULL);
-    return(ret);
-}
-
-PyObject *
-libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj) {
-    PyObject *ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlXPathObjectPtrWrap: ctxt = %p\n", obj);
-#endif
-    if (obj == NULL) {
-	Py_INCREF(Py_None);
-	return(Py_None);
-    }
-    switch(obj->type) {
-        case XPATH_XSLT_TREE:
-	    /* TODO !!!! Allocation problems */
-        case XPATH_NODESET:
-	    if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0))
-		ret = PyList_New(0);
-	    else {
-		int i;
-		xmlNodePtr node;
-
-		ret = PyList_New(obj->nodesetval->nodeNr);
-		for (i = 0;i < obj->nodesetval->nodeNr;i++) {
-		    node = obj->nodesetval->nodeTab[i];
-		    /* TODO: try to cast directly to the proper node type */
-		    PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
-		}
-	    }
-	    break;
-        case XPATH_BOOLEAN:
-	    ret = PyInt_FromLong((long) obj->boolval);
-	    break;
-        case XPATH_NUMBER:
-	    ret = PyFloat_FromDouble(obj->floatval);
-	    break;
-        case XPATH_STRING:
-	    ret = PyString_FromString(obj->stringval);
-	    break;
-        case XPATH_POINT:
-        case XPATH_RANGE:
-        case XPATH_LOCATIONSET:
-	default:
-	    printf("Unable to convert XPath object type %d\n", obj->type);
-	    Py_INCREF(Py_None);
-	    ret = Py_None;
-    }
-    xmlXPathFreeObject(obj);
-    return(ret);
-}
-
-xmlXPathObjectPtr
-libxml_xmlXPathObjectPtrConvert(PyObject * obj) {
-    xmlXPathObjectPtr ret;
-
-#ifdef DEBUG
-    printf("libxml_xmlXPathObjectPtrConvert: obj = %p\n", obj);
-#endif
-    if (obj == NULL) {
-	return(NULL);
-    }
-    if PyFloat_Check(obj) {
-	ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj));
-    } else if PyString_Check(obj) {
-	xmlChar *str;
-
-	str = xmlStrndup((const xmlChar *)PyString_AS_STRING(obj),
-		         PyString_GET_SIZE(obj));
-	ret = xmlXPathWrapString(str);
-    } else {
-	printf("Unable to convert Python Object to XPath");
-    }
-    Py_DECREF(obj);
-    return(ret);
+    ret = xmlCreatePushParserCtxt(SAX, SAXdata, chunk, size, URI);
+    pyret = libxml_xmlParserCtxtPtrWrap(ret);
+    return(pyret);
 }
 
 /************************************************************************
@@ -534,131 +314,6 @@
 
 /************************************************************************
  *									*
- *		The PyxmlNode type					*
- *									*
- ************************************************************************/
-static void
-PyxmlNode_dealloc(PyxmlNode_Object * self)
-{
-    printf("TODO PyxmlNode_dealloc\n");
-    PyMem_DEL(self);
-}
-
-static int
-PyxmlNode_compare(PyxmlNode_Object * self, PyxmlNode_Object * v)
-{
-    if (self->obj == v->obj)
-        return 0;
-    if (self->obj > v->obj)
-        return -1;
-    return 1;
-}
-
-static long
-PyxmlNode_hash(PyxmlNode_Object * self)
-{
-    return (long) self->obj;
-}
-
-static PyObject *
-PyxmlNode_repr(PyxmlNode_Object * self)
-{
-    char buf[100];
-
-    sprintf(buf, "<xmlNode of type %d at %lx>",
-            PyxmlNode_Get(self)->type,
-            (long) PyxmlNode_Get(self));
-    return PyString_FromString(buf);
-}
-
-static char PyxmlNode_Type__doc__[] = "This is the type of libxml Nodes";
-
-static PyTypeObject PyxmlNode_Type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-        0,                      /*ob_size */
-    "xmlNode",                  /*tp_name */
-    sizeof(PyxmlNode_Object),   /*tp_basicsize */
-    0,                          /*tp_itemsize */
-    (destructor) PyxmlNode_dealloc,/*tp_dealloc */
-    (printfunc) 0,              /*tp_print */
-    (getattrfunc) 0,            /*tp_getattr */
-    (setattrfunc) 0,            /*tp_setattr */
-    (cmpfunc) PyxmlNode_compare,/*tp_compare */
-    (reprfunc) PyxmlNode_repr,  /*tp_repr */
-    0,                          /*tp_as_number */
-    0,                          /*tp_as_sequence */
-    0,                          /*tp_as_mapping */
-    (hashfunc) PyxmlNode_hash,  /*tp_hash */
-    (ternaryfunc) 0,            /*tp_call */
-    (reprfunc) 0,               /*tp_str */
-    0L, 0L, 0L, 0L,
-    PyxmlNode_Type__doc__
-};
-
-/************************************************************************
- *									*
- *		The PyxmlXPathContext type					*
- *									*
- ************************************************************************/
-static void
-PyxmlXPathContext_dealloc(PyxmlXPathContext_Object * self)
-{
-    printf("TODO PyxmlXPathContext_dealloc\n");
-    PyMem_DEL(self);
-}
-
-static int
-PyxmlXPathContext_compare(PyxmlXPathContext_Object * self, PyxmlXPathContext_Object * v)
-{
-    if (self->obj == v->obj)
-        return 0;
-    if (self->obj > v->obj)
-        return -1;
-    return 1;
-}
-
-static long
-PyxmlXPathContext_hash(PyxmlXPathContext_Object * self)
-{
-    return (long) self->obj;
-}
-
-static PyObject *
-PyxmlXPathContext_repr(PyxmlXPathContext_Object * self)
-{
-    char buf[100];
-
-    sprintf(buf, "<xmlXPathContext at %lx>",
-            (long) PyxmlXPathContext_Get(self));
-    return PyString_FromString(buf);
-}
-
-static char PyxmlXPathContext_Type__doc__[] = "This is the type of XPath evaluation contexts";
-
-PyTypeObject PyxmlXPathContext_Type = {
-    PyObject_HEAD_INIT(&PyType_Type)
-        0,                      /*ob_size */
-    "xmlXPathContext",                  /*tp_name */
-    sizeof(PyxmlXPathContext_Object),   /*tp_basicsize */
-    0,                          /*tp_itemsize */
-    (destructor) PyxmlXPathContext_dealloc,/*tp_dealloc */
-    (printfunc) 0,              /*tp_print */
-    (getattrfunc) 0,            /*tp_getattr */
-    (setattrfunc) 0,            /*tp_setattr */
-    (cmpfunc) PyxmlXPathContext_compare,/*tp_compare */
-    (reprfunc) PyxmlXPathContext_repr,  /*tp_repr */
-    0,                          /*tp_as_number */
-    0,                          /*tp_as_sequence */
-    0,                          /*tp_as_mapping */
-    (hashfunc) PyxmlXPathContext_hash,  /*tp_hash */
-    (ternaryfunc) 0,            /*tp_call */
-    (reprfunc) 0,               /*tp_str */
-    0L, 0L, 0L, 0L,
-    PyxmlXPathContext_Type__doc__
-};
-
-/************************************************************************
- *									*
  *			Global properties access			*
  *									*
  ************************************************************************/
@@ -1055,11 +710,8 @@
 };
 
 void init_libxml(void) {
-    PyObject *m, *d;
+    PyObject *m;
     m = Py_InitModule("_libxml", libxmlMethods);
-    d = PyModule_GetDict(m);
-    PyDict_SetItemString(d, "xmlNodeType", (PyObject *)&PyxmlNode_Type);
-    PyDict_SetItemString(d, "xmlXPathContextType", (PyObject *)&PyxmlXPathContext_Type);
     libxml_xmlErrorInitialize();
 }
 
diff --git a/python/libxml.py b/python/libxml.py
index 6f5197b..22749f8 100644
--- a/python/libxml.py
+++ b/python/libxml.py
@@ -148,14 +148,6 @@
     ret = _libxml.xmlRegisterXPathFunction(ctxt, name, ns_uri, f)
 
 #
-# A parser context
-#
-class parserCtxt:
-    def __init__(self, _obj=None):
-        self._o = _obj
-    
-
-#
 # Everything below this point is automatically generated
 #
 
diff --git a/python/libxml2-python-api.xml b/python/libxml2-python-api.xml
index 5cdc992..ec76f6e 100644
--- a/python/libxml2-python-api.xml
+++ b/python/libxml2-python-api.xml
@@ -20,5 +20,18 @@
       <arg name='f' type='pythonObject' info='the python function'/>
       <arg name='ctx' type='pythonObject' info='a context for the callback'/>
     </function>
+    <function name='xmlCreatePushParser' file='python'>
+      <info>Create a progressive parser context to build either an event flow if the SAX object is not None, or a DOM tree otherwise.</info>
+      <return type='xmlParserCtxtPtr' info="the parser context or None in case of error"/>
+      <arg name='SAX' type='pythonObject' info='the SAX callback object or None'/>
+      <arg name='chunk' type='xmlChar *' info='the initial data'/>
+      <arg name='size' type='int' info='the size of the initial data'/>
+      <arg name='URI' type='xmlChar *' info='The URI used for base computations'/>
+    </function>
+    <function name='xmlParserGetDoc' file='python_accessor'>
+      <info>Get the document tree from a parser context.</info>
+      <return type='xmlDocPtr' info="the document tree" field="myDoc"/>
+      <arg name='ctxt' type='xmlParserCtxtPtr' info='the SAX callback object or None'/>
+    </function>
   </symbols>
 </api>
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
index 0411124..d952c2c 100644
--- a/python/libxml2class.txt
+++ b/python/libxml2class.txt
@@ -6,9 +6,13 @@
 
 
 # functions from module HTMLparser
+htmlFreeParserCtxt()
 htmlHandleOmittedElem()
 htmlIsScriptAttribute()
+htmlParseCharRef()
+htmlParseChunk()
 htmlParseDoc()
+htmlParseElement()
 htmlParseFile()
 
 # functions from module HTMLtree
@@ -68,6 +72,7 @@
 
 # functions from module parser
 cleanupParser()
+createDocParserCtxt()
 defaultSAXHandlerInit()
 htmlDefaultSAXHandlerInit()
 initParser()
@@ -88,6 +93,10 @@
 checkLanguageID()
 copyChar()
 copyCharMultiByte()
+createEntityParserCtxt()
+createFileParserCtxt()
+createMemoryParserCtxt()
+htmlCreateFileParserCtxt()
 htmlInitAutoClose()
 isBaseChar()
 isBlank()
@@ -98,8 +107,14 @@
 isIdeographic()
 isLetter()
 isPubidChar()
+namePop()
+namePush()
+newParserCtxt()
+nodePop()
+nodePush()
 
 # functions from module python
+createPushParser()
 registerErrorHandler()
 
 # functions from module tree
@@ -315,6 +330,66 @@
 
 
 Class xmlElement(xmlNode)
+Class parserCtxt()
+    # accessors
+    doc()
+
+    # functions from module parser
+    clearParserCtxt()
+    initParserCtxt()
+    parseChunk()
+    parseDocument()
+    parseExtParsedEnt()
+    stopParser()
+
+    # functions from module parserInternals
+    decodeEntities()
+    freeParserCtxt()
+    handleEntity()
+    namespaceParseNCName()
+    namespaceParseNSDef()
+    nextChar()
+    parseAttValue()
+    parseAttributeListDecl()
+    parseCDSect()
+    parseCharData()
+    parseCharRef()
+    parseComment()
+    parseContent()
+    parseDocTypeDecl()
+    parseElement()
+    parseElementDecl()
+    parseEncName()
+    parseEncodingDecl()
+    parseEndTag()
+    parseEntityDecl()
+    parseEntityRef()
+    parseExternalSubset()
+    parseMarkupDecl()
+    parseMisc()
+    parseName()
+    parseNamespace()
+    parseNmtoken()
+    parseNotationDecl()
+    parsePEReference()
+    parsePI()
+    parsePITarget()
+    parsePubidLiteral()
+    parseQuotedString()
+    parseReference()
+    parseSDDecl()
+    parseStartTag()
+    parseSystemLiteral()
+    parseTextDecl()
+    parseVersionInfo()
+    parseVersionNum()
+    parseXMLDecl()
+    parserHandlePEReference()
+    parserHandleReference()
+    popInput()
+    scanName()
+    skipBlankChars()
+    stringDecodeEntities()
 Class xpathContext()
 
     # functions from module python
diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h
index 972e871..d6d89aa 100644
--- a/python/libxml_wrap.h
+++ b/python/libxml_wrap.h
@@ -1,3 +1,4 @@
+#include <Python.h>
 #include <libxml/tree.h>
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
@@ -27,6 +28,12 @@
     xmlXPathContextPtr obj;
 } PyxmlXPathContext_Object;
 
+#define PyparserCtxt_Get(v) (((PyparserCtxt_Object *)(v))->obj)
+typedef struct {
+    PyObject_HEAD
+    xmlParserCtxtPtr obj;
+} PyparserCtxt_Object;
+
 PyObject * libxml_intWrap(int val);
 PyObject * libxml_xmlCharPtrWrap(xmlChar *str);
 PyObject * libxml_constxmlCharPtrWrap(const xmlChar *str);
@@ -40,5 +47,7 @@
 PyObject * libxml_xmlElementPtrWrap(xmlElementPtr ns);
 PyObject * libxml_doubleWrap(double val);
 PyObject * libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt);
+PyObject * libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt);
 PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj);
 
+xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
index 79d5456..b8e9cec 100644
--- a/python/tests/Makefile.am
+++ b/python/tests/Makefile.am
@@ -4,6 +4,7 @@
     tst.py	\
     tstxpath.py	\
     xpathext.py	\
+    push.py	\
     error.py	\
     xpath.py
 
@@ -20,6 +21,9 @@
 tests:
 endif
 
+clean:
+	rm -f *.pyc core
+
 install-data-local:
 	$(mkinstalldirs) $(DESTDIR)$(EXAMPLE_DIR)
 	-(for test in $(TESTS) $(XMLS); \
diff --git a/python/tests/push.py b/python/tests/push.py
new file mode 100755
index 0000000..738d3e9
--- /dev/null
+++ b/python/tests/push.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python -u
+import sys
+import libxml2
+
+ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml")
+ctxt.parseChunk("/>", 2, 1)
+doc = ctxt.doc()
+ctxt=None
+if doc.name != "test.xml":
+    print "document name error"
+    sys.exit(1)
+root = doc.children
+if root.name != "foo":
+    print "root element name error"
+    sys.exit(1)
+doc.freeDoc()
+i = 10000
+while i > 0:
+    ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml")
+    ctxt.parseChunk("/>", 2, 1)
+    doc = ctxt.doc()
+    doc.freeDoc()
+    i = i -1
+ctxt=None
+print "OK"
diff --git a/python/types.c b/python/types.c
new file mode 100644
index 0000000..07a178e
--- /dev/null
+++ b/python/types.c
@@ -0,0 +1,297 @@
+/*
+ * types.c: converter functions between the internal representation
+ *          and the Python objects
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+#include "libxml_wrap.h"
+
+PyObject *
+libxml_intWrap(int val) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_intWrap: val = %d\n", val);
+#endif
+    ret = PyInt_FromLong((long) val);
+    return(ret);
+}
+
+PyObject *
+libxml_doubleWrap(double val) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_doubleWrap: val = %f\n", val);
+#endif
+    ret = PyFloat_FromDouble((double) val);
+    return(ret);
+}
+
+PyObject *
+libxml_charPtrWrap(char *str) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlcharPtrWrap: str = %s\n", str);
+#endif
+    if (str == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyString_FromString(str);
+    xmlFree(str);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlCharPtrWrap(xmlChar *str) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlCharPtrWrap: str = %s\n", str);
+#endif
+    if (str == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyString_FromString(str);
+    xmlFree(str);
+    return(ret);
+}
+
+PyObject *
+libxml_constcharPtrWrap(const char *str) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlcharPtrWrap: str = %s\n", str);
+#endif
+    if (str == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyString_FromString(str);
+    return(ret);
+}
+
+PyObject *
+libxml_constxmlCharPtrWrap(const xmlChar *str) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlCharPtrWrap: str = %s\n", str);
+#endif
+    if (str == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyString_FromString(str);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlDocPtrWrap(xmlDocPtr doc) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlDocPtrWrap: doc = %p\n", doc);
+#endif
+    if (doc == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    /* TODO: look at deallocation */
+    ret = PyCObject_FromVoidPtrAndDesc((void *) doc, "xmlDocPtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlNodePtrWrap(xmlNodePtr node) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlNodePtrWrap: node = %p\n", node);
+#endif
+    if (node == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) node, "xmlNodePtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlNsPtrWrap(xmlNsPtr ns) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlNsPtrWrap: node = %p\n", ns);
+#endif
+    if (ns == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) ns, "xmlNsPtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlAttrPtrWrap(xmlAttrPtr attr) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlAttrNodePtrWrap: attr = %p\n", attr);
+#endif
+    if (attr == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttrPtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlAttributePtrWrap(xmlAttributePtr attr) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlAttributePtrWrap: attr = %p\n", attr);
+#endif
+    if (attr == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttributePtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlElementPtrWrap(xmlElementPtr elem) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlElementNodePtrWrap: elem = %p\n", elem);
+#endif
+    if (elem == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) elem, "xmlElementPtr", NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlXPathContextPtrWrap: ctxt = %p\n", ctxt);
+#endif
+    if (ctxt == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, "xmlXPathContextPtr",
+	                               NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlParserCtxtPtrWrap: ctxt = %p\n", ctxt);
+#endif
+    if (ctxt == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, "xmlParserCtxtPtr",
+	                               NULL);
+    return(ret);
+}
+
+PyObject *
+libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj) {
+    PyObject *ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlXPathObjectPtrWrap: ctxt = %p\n", obj);
+#endif
+    if (obj == NULL) {
+	Py_INCREF(Py_None);
+	return(Py_None);
+    }
+    switch(obj->type) {
+        case XPATH_XSLT_TREE:
+	    /* TODO !!!! Allocation problems */
+        case XPATH_NODESET:
+	    if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0))
+		ret = PyList_New(0);
+	    else {
+		int i;
+		xmlNodePtr node;
+
+		ret = PyList_New(obj->nodesetval->nodeNr);
+		for (i = 0;i < obj->nodesetval->nodeNr;i++) {
+		    node = obj->nodesetval->nodeTab[i];
+		    /* TODO: try to cast directly to the proper node type */
+		    PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
+		}
+	    }
+	    break;
+        case XPATH_BOOLEAN:
+	    ret = PyInt_FromLong((long) obj->boolval);
+	    break;
+        case XPATH_NUMBER:
+	    ret = PyFloat_FromDouble(obj->floatval);
+	    break;
+        case XPATH_STRING:
+	    ret = PyString_FromString(obj->stringval);
+	    break;
+        case XPATH_POINT:
+        case XPATH_RANGE:
+        case XPATH_LOCATIONSET:
+	default:
+	    printf("Unable to convert XPath object type %d\n", obj->type);
+	    Py_INCREF(Py_None);
+	    ret = Py_None;
+    }
+    xmlXPathFreeObject(obj);
+    return(ret);
+}
+
+xmlXPathObjectPtr
+libxml_xmlXPathObjectPtrConvert(PyObject * obj) {
+    xmlXPathObjectPtr ret;
+
+#ifdef DEBUG
+    printf("libxml_xmlXPathObjectPtrConvert: obj = %p\n", obj);
+#endif
+    if (obj == NULL) {
+	return(NULL);
+    }
+    if PyFloat_Check(obj) {
+	ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj));
+    } else if PyString_Check(obj) {
+	xmlChar *str;
+
+	str = xmlStrndup((const xmlChar *)PyString_AS_STRING(obj),
+		         PyString_GET_SIZE(obj));
+	ret = xmlXPathWrapString(str);
+    } else {
+	printf("Unable to convert Python Object to XPath");
+    }
+    Py_DECREF(obj);
+    return(ret);
+}
+
+