added more informations in the libxml2-python package including docs.

* configure.in libxml.spec.in python/Makefile.am python/TODO
  python/generator.py python/libxml2class.txt: added more informations
  in the libxml2-python package including docs. Slightly changed
  the class hierarchy
* python/tests/*: added basic regression tests infrastructure too
Daniel
diff --git a/ChangeLog b/ChangeLog
index 1437577..32db962 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Sat Feb  2 10:13:52 CET 2002 Daniel Veillard <daniel@veillard.com>
+
+	* configure.in libxml.spec.in python/Makefile.am python/TODO
+	  python/generator.py python/libxml2class.txt: added more informations
+	  in the libxml2-python package including docs. Slightly changed
+	  the class hierarchy
+	* python/tests/*: added basic regression tests infrastructure too
+
+Fri Feb  1 23:11:58 CET 2002 Daniel Veillard <daniel@veillard.com>
+
+	* configure.in libxml.spec.in example/Makefile.am python/Makefile.am:
+	  added libxml2-python as part of the packages installed
+
 Fri Feb  1 18:48:19 CET 2002 Daniel Veillard <daniel@veillard.com>
 
 	* python/Makefile.am python/generator.py python/libxml.c
diff --git a/configure.in b/configure.in
index 491ba18..e4955ff 100644
--- a/configure.in
+++ b/configure.in
@@ -192,6 +192,7 @@
 PYTHON=
 PYTHON_VERSION=
 PYTHON_INCLUDES=
+PYTHON_SITE_PACKAGES=
 AC_ARG_WITH(python, [  --with-python[=DIR]    Build Python bindings if found])
 if test "$with_python" != "no" ; then
     if test -x "$with_python/bin/python"
@@ -208,17 +209,21 @@
     fi
     if test "$PYTHON_VERSION" != ""
     then
-	if test -r $with_python/include/python$PYTHON_VERSION/Python.h
+	if test -r $with_python/include/python$PYTHON_VERSION/Python.h -a \
+	   -d $with_python/lib/python$PYTHON_VERSION/site-packages
 	then
 	    PYTHON_INCLUDES=$with_python/include/python$PYTHON_VERSION
+	    PYTHON_SITE_PACKAGES=$with_python/lib/python$PYTHON_VERSION/site-packages
 	else
 	    if test -r $prefix/include/python$PYTHON_VERSION/Python.h
 	    then
-	        PYTHON_INCLUDES=$prefix/include/python$PYTHON_VERSION
+	        PYTHON_INCLUDES='$(prefix)/include/python$(PYTHON_VERSION)'
+		PYTHON_SITE_PACKAGES='$(prefix)/lib/python$(PYTHON_VERSION)/site-packages'
 	    else
 		if test -r /usr/include/python$PYTHON_VERSION/Python.h
 		then
 		    PYTHON_INCLUDES=/usr/include/python$PYTHON_VERSION
+		    PYTHON_SITE_PACKAGES=/usr/lib/python$PYTHON_VERSION/site-packages
 		else
 		    echo could not find python$PYTHON_VERSION/Python.h
 		fi
@@ -528,9 +533,10 @@
 AC_SUBST(PYTHON)
 AC_SUBST(PYTHON_VERSION)
 AC_SUBST(PYTHON_INCLUDES)
+AC_SUBST(PYTHON_SITE_PACKAGES)
 
 AC_SUBST(M_LIBS)
 AC_SUBST(RDL_LIBS)
 
-AC_OUTPUT(libxml.spec Makefile include/Makefile include/libxml/Makefile doc/Makefile example/Makefile python/Makefile include/libxml/xmlversion.h include/libxml/xmlwin32version.h xml2-config libxml-2.0.pc xml2Conf.sh)
+AC_OUTPUT(libxml.spec Makefile include/Makefile include/libxml/Makefile doc/Makefile example/Makefile python/Makefile python/tests/Makefile include/libxml/xmlversion.h include/libxml/xmlwin32version.h xml2-config libxml-2.0.pc xml2Conf.sh)
 
diff --git a/example/Makefile.am b/example/Makefile.am
index cb73e72..b78e05f 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -1,4 +1,4 @@
-AUTOMAKE_OPTIONS=no-dependencies
+# AUTOMAKE_ OPTIONS=no-dependencies
 
 noinst_PROGRAMS	= gjobread
 
diff --git a/libxml.spec.in b/libxml.spec.in
index ce4de6e..943a415 100644
--- a/libxml.spec.in
+++ b/libxml.spec.in
@@ -6,6 +6,7 @@
 Group: Development/Libraries
 Source: ftp://xmlsoft.org/libxml2-%{version}.tar.gz
 BuildRoot: %{_tmppath}/%{name}-%{version}-root
+BuildRequires: python python-devel
 URL: http://xmlsoft.org/
 Prefix: %{_prefix}
 Docdir: %{_docdir}
@@ -38,6 +39,21 @@
 available, with existing HTTP and FTP modules and combined to an
 URI library.
 
+%package python
+Summary: Python bindings for the libxml2 library
+Group: Development/Libraries
+Requires: libxml2 = %{version}
+Requires: python
+
+%description python
+The libxml2-python package contains a module that permits applications
+written in the Python programming language to use the interface
+supplied by the libxml2 library to manipulate XML files.
+
+This library allows to manipulate XML files. It includes support 
+to read, modify and write XML and HTML files. There is DTDs support
+this includes parsing and validation even with complex DTDs, either
+at parse time or later once the document has been modified.
 %prep
 %setup -q
 
@@ -103,8 +119,19 @@
 %{prefix}/bin/xml2-config
 %{prefix}/share/aclocal/libxml.m4
 %{prefix}/lib/pkgconfig/libxml-2.0.pc
+%files python
+%defattr(-, root, root)
+
+%{prefix}/lib/python*/site-packages/libxml2.py
+%{prefix}/lib/python*/site-packages/_libxml.so
+%doc python/TODO
+%doc python/libxml2class.txt
+%doc python/tests/*.py
 
 %changelog
+* Fri Feb  1 2002 Daniel Veillard <veillard@redhat.com>
+
+- Added the python package
 
 * Sun Nov  4 2001 Daniel Veillard <veillard@redhat.com>
 
diff --git a/python/Makefile.am b/python/Makefile.am
index 158f149..43bc4b0 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -1,19 +1,25 @@
+SUBDIRS= . tests
+
 LIBS=-L../.libs -L.. $(XML_LIBS)
-INCLUDES=-I$(PYTHON_INCLUDES) -I$(top_srcdir)/include
+INCLUDES=-I/usr/include/python$(PYTHON_VERSION) -I$(PYTHON_INCLUDES) -I$(top_srcdir)/include
 SHCFLAGS=$(INCLUDES) -Wall -fPIC
 LINK_FLAGS= -shared
+DOCS_DIR = $(prefix)/share/doc/libxml2-python-$(LIBXML_VERSION)
+
+DOCS = TODO libxml2class.txt
 
 EXTRA_DIST = \
 	libxml.c	\
 	generator.py	\
 	libxml_wrap.h	\
-	libxml.py
+	libxml.py	\
+	$(DOCS)
 
 if WITH_PYTHON
 all: _libxml.so libxml2.py
 
-libxml2.py: libxml.py libxml2class.py
-	cat libxml.py libxml2class.py > libxml2.py
+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
@@ -39,3 +45,12 @@
 
 clean:
 	rm -f $(GENERATED) *.o _libxml.so *.pyc libxml2.py
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(PYTHON_SITE_PACKAGES)
+	-@INSTALL@ -m 0644 libxml2.py $(DESTDIR)$(PYTHON_SITE_PACKAGES)
+	-@INSTALL@ -m 0755 _libxml.so $(DESTDIR)$(PYTHON_SITE_PACKAGES)
+	$(mkinstalldirs) $(DESTDIR)$(DOCS_DIR)
+	-@(for doc in $(DOCS) ; \
+	   do @INSTALL@ -m 0644 $$doc $(DESTDIR)$(DOCS_DIR) ; done)
+
diff --git a/python/TODO b/python/TODO
new file mode 100644
index 0000000..b1fa734
--- /dev/null
+++ b/python/TODO
@@ -0,0 +1,41 @@
+             TODO for the libxml2 Python wrappers
+
+               $Id$
+
+Things to do:
+-------------
+
+- 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
+  - wrappers
+  - decent interface for setting/getting behaviour
+- xmlBuffer exposure
+- xpathContext, being able to set/get info and clean it up
+- add regression tests
+   - check memory
+   - build tree
+   - saving
+   - SAX flow
+
+
+Done:
+-----
+- class hierarchy:
+  + make specific node type inherit from xmlNode
+- add regression tests
+   - tests/Makefile.am: export the Python class path
+   - xpath queries
+   - xpath extension
+
+Daniel Veillard
diff --git a/python/generator.py b/python/generator.py
index 13a5ae7..ee477b0 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -210,11 +210,11 @@
     'double':  ('d', None, "double", "double"),
     'unsigned int':  ('i', None, "int", "int"),
     'xmlChar':  ('c', None, "int", "int"),
-    'unsigned char *':  ('s', None, "charPtr", "char *"),
-    'char *':  ('s', None, "charPtr", "char *"),
-    'const char *':  ('s', None, "charPtr", "char *"),
-    'xmlChar *':  ('s', None, "xmlCharPtr", "xmlChar *"),
-    'const xmlChar *':  ('s', None, "xmlCharPtr", "xmlChar *"),
+    'unsigned char *':  ('z', None, "charPtr", "char *"),
+    'char *':  ('z', None, "charPtr", "char *"),
+    'const char *':  ('z', None, "charPtr", "char *"),
+    'xmlChar *':  ('z', None, "xmlCharPtr", "xmlChar *"),
+    'const xmlChar *':  ('z', None, "xmlCharPtr", "xmlChar *"),
     'xmlNodePtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
     'const xmlNodePtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
     'xmlNode *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"),
@@ -465,13 +465,13 @@
 
 classes_ancestor = {
     "xmlNode" : "xmlCore",
-    "xmlDoc" : "xmlCore",
-    "xmlAttr" : "xmlCore",
-    "xmlNs" : "xmlCore",
-    "xmlDtd" : "xmlCore",
-    "xmlEntity" : "xmlCore",
-    "xmlElement" : "xmlCore",
-    "xmlAttribute" : "xmlCore",
+    "xmlDtd" : "xmlNode",
+    "xmlDoc" : "xmlNode",
+    "xmlAttr" : "xmlNode",
+    "xmlNs" : "xmlNode",
+    "xmlEntity" : "xmlNode",
+    "xmlElement" : "xmlNode",
+    "xmlAttribute" : "xmlNode",
 }
 classes_destructors = {
     "xpathContext": "xmlXPathFreeContext",
@@ -574,6 +574,8 @@
     function_classes['None'].append(info)
 
 classes = open("libxml2class.py", "w")
+txt = open("libxml2class.txt", "w")
+txt.write("          Generated Classes for libxml2-python\n\n")
 
 def functionCompare(info1, info2):
     (index1, func1, name1, ret1, args1, file1) = info1
@@ -608,6 +610,7 @@
      output.write(val);
      output.write('"""\n')
 
+txt.write("#\n# Global functions of the module\n#\n\n")
 if function_classes.has_key("None"):
     flist = function_classes["None"]
     flist.sort(functionCompare)
@@ -616,8 +619,10 @@
 	(index, func, name, ret, args, file) = info
 	if file != oldfile:
 	    classes.write("#\n# Functions from module %s\n#\n\n" % file)
+	    txt.write("\n# functions from module %s\n" % file)
 	    oldfile = file
 	classes.write("def %s(" % func)
+	txt.write("%s()\n" % func);
 	n = 0
 	for arg in args:
 	    if n != 0:
@@ -650,11 +655,14 @@
 		classes.write("    return ret\n");
 	classes.write("\n");
 
+txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
 for classname in function_classes.keys():
     if classname == "None":
         pass
     else:
         if classes_ancestor.has_key(classname):
+	    txt.write("\n\nClass %s(%s)\n" % (classname,
+	              classes_ancestor[classname]))
 	    classes.write("class %s(%s):\n" % (classname,
 	                  classes_ancestor[classname]))
 	    classes.write("    def __init__(self, _obj=None):\n")
@@ -662,6 +670,7 @@
 	    classes.write("        %s.__init__(self, _obj=_obj)\n\n" % (
 	                  classes_ancestor[classname]))
 	else:
+	    txt.write("Class %s()\n" % (classname))
 	    classes.write("class %s:\n" % (classname))
 	    classes.write("    def __init__(self, _obj=None):\n")
 	    classes.write("        if _obj != None:self._o = _obj;return\n")
@@ -685,9 +694,11 @@
 		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);
 	    n = 0
 	    for arg in args:
 	        if n != index:
@@ -727,4 +738,5 @@
 		    classes.write("        return ret\n");
 	    classes.write("\n");
 
+txt.close()
 classes.close()
diff --git a/python/libxml2class.txt b/python/libxml2class.txt
new file mode 100644
index 0000000..c8e2359
--- /dev/null
+++ b/python/libxml2class.txt
@@ -0,0 +1,330 @@
+          Generated Classes for libxml2-python
+
+#
+# Global functions of the module
+#
+
+
+# functions from module HTMLparser
+htmlHandleOmittedElem()
+htmlIsScriptAttribute()
+htmlParseDoc()
+htmlParseFile()
+
+# functions from module HTMLtree
+htmlNewDoc()
+htmlNewDocNoDtD()
+
+# functions from module catalog
+catalogAdd()
+catalogCleanup()
+catalogConvert()
+catalogGetPublic()
+catalogGetSystem()
+catalogRemove()
+catalogResolve()
+catalogResolvePublic()
+catalogResolveSystem()
+catalogResolveURI()
+catalogSetDebug()
+initializeCatalog()
+loadCatalog()
+loadCatalogs()
+parseCatalogFile()
+
+# functions from module debugXML
+shellPrintXPathError()
+
+# functions from module encoding
+UTF8Strlen()
+UTF8Strloc()
+UTF8Strndup()
+UTF8Strpos()
+UTF8Strsize()
+UTF8Strsub()
+addEncodingAlias()
+checkUTF8()
+cleanupCharEncodingHandlers()
+cleanupEncodingAliases()
+delEncodingAlias()
+encodingAlias()
+initCharEncodingHandlers()
+
+# functions from module entities
+cleanupPredefinedEntities()
+initializePredefinedEntities()
+predefinedEntity()
+
+# functions from module nanoftp
+nanoFTPCleanup()
+nanoFTPInit()
+nanoFTPProxy()
+nanoFTPScanProxy()
+
+# functions from module nanohttp
+nanoHTTPCleanup()
+nanoHTTPInit()
+nanoHTTPScanProxy()
+
+# functions from module parser
+cleanupParser()
+defaultSAXHandlerInit()
+htmlDefaultSAXHandlerInit()
+initParser()
+keepBlanksDefault()
+lineNumbersDefault()
+parseDTD()
+parseDoc()
+parseEntity()
+parseFile()
+parseMemory()
+pedanticParserDefault()
+recoverDoc()
+recoverFile()
+recoverMemory()
+substituteEntitiesDefault()
+
+# functions from module parserInternals
+checkLanguageID()
+copyChar()
+copyCharMultiByte()
+htmlInitAutoClose()
+isBaseChar()
+isBlank()
+isChar()
+isCombining()
+isDigit()
+isExtender()
+isIdeographic()
+isLetter()
+isPubidChar()
+
+# functions from module tree
+compressMode()
+newComment()
+newDoc()
+newPI()
+newText()
+newTextLen()
+setCompressMode()
+
+# functions from module uri
+URIEscape()
+URIEscapeStr()
+URIUnescapeString()
+buildURI()
+normalizeURIPath()
+
+# functions from module xmlIO
+cleanupInputCallbacks()
+cleanupOutputCallbacks()
+parserGetDirectory()
+registerDefaultInputCallbacks()
+registerDefaultOutputCallbacks()
+registerHTTPPostCallbacks()
+
+# functions from module xmlversion
+checkVersion()
+
+
+#
+# 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)
+
+    # functions from module debugXML
+    lsCountNode()
+    shellPrintNode()
+
+    # functions from module tree
+    addChild()
+    addChildList()
+    addContent()
+    addContentLen()
+    addNextSibling()
+    addPrevSibling()
+    addSibling()
+    copyNode()
+    copyNodeList()
+    copyProp()
+    copyPropList()
+    docCopyNode()
+    docSetRootElement()
+    freeNode()
+    freeNodeList()
+    getBase()
+    getContent()
+    getLang()
+    getSpacePreserve()
+    hasNsProp()
+    hasProp()
+    isBlankNode()
+    isText()
+    lastChild()
+    lineNo()
+    listGetRawString()
+    listGetString()
+    newChild()
+    newNs()
+    newNsProp()
+    newProp()
+    newTextChild()
+    nodePath()
+    nsProp()
+    prop()
+    reconciliateNs()
+    replaceNode()
+    searchNs()
+    searchNsByHref()
+    setBase()
+    setContent()
+    setContentLen()
+    setLang()
+    setListDoc()
+    setName()
+    setNs()
+    setNsProp()
+    setProp()
+    setSpacePreserve()
+    setTreeDoc()
+    textConcat()
+    textMerge()
+    unlinkNode()
+    unsetNsProp()
+    unsetProp()
+
+    # functions from module valid
+    isID()
+    isRef()
+    validNormalizeAttributeValue()
+
+    # functions from module xpath
+    xpathCastNodeToNumber()
+    xpathCastNodeToString()
+    xpathCmpNodes()
+
+    # functions from module xpathInternals
+    xpathNewNodeSet()
+    xpathNewValueTree()
+
+
+Class xmlAttribute(xmlNode)
+
+
+Class xmlDtd(xmlNode)
+
+    # functions from module tree
+    copyDtd()
+    freeDtd()
+
+    # functions from module valid
+    dtdAttrDesc()
+    dtdElementDesc()
+    dtdQAttrDesc()
+    dtdQElementDesc()
+
+
+Class xmlAttr(xmlNode)
+
+    # functions from module tree
+    freeProp()
+    freePropList()
+    removeProp()
+
+
+Class xmlEntity(xmlNode)
+
+
+Class xmlElement(xmlNode)
+
+
+Class xmlNs(xmlNode)
+
+    # functions from module tree
+    copyNamespace()
+    copyNamespaceList()
+    freeNs()
+    freeNsList()
+    newNode()
diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am
new file mode 100644
index 0000000..366ad06
--- /dev/null
+++ b/python/tests/Makefile.am
@@ -0,0 +1,26 @@
+EXAMPLE_DIR = $(prefix)/share/doc/libxml2-python-$(LIBXML_VERSION)/examples
+
+TESTS=		\
+    tst.py	\
+    tstxpath.py	\
+    xpathext.py	\
+    xpath.py
+
+XMLS=		\
+    tst.xml
+
+EXTRA_DIST = $(TESTS) $(XMLS)
+
+if WITH_PYTHON
+tests: $(TESTS)
+	-@(CLASSPATH=".." ; export CLASSPATH; \
+	   for test in $(TESTS) ; do echo "-- $$test" ; $(PYTHON) $$test ; done)
+else
+tests:
+endif
+
+install-data-local:
+	$(mkinstalldirs) $(DESTDIR)$(EXAMPLE_DIR)
+	-(for test in $(TESTS) $(XMLS); \
+	  do @INSTALL@ -m 0644 $$test $(DESTDIR)$(EXAMPLE_DIR) ; done)
+
diff --git a/python/tests/tst.py b/python/tests/tst.py
new file mode 100755
index 0000000..86ac64b
--- /dev/null
+++ b/python/tests/tst.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python -u
+import libxml2
+
+doc = libxml2.parseFile("tst.xml")
+print doc.name
+root = doc.children
+print root.name
+child = root.children
+print child.name
+doc.freeDoc()
diff --git a/python/tests/tst.xml b/python/tests/tst.xml
new file mode 100644
index 0000000..751d46d
--- /dev/null
+++ b/python/tests/tst.xml
@@ -0,0 +1 @@
+<doc><foo>bar</foo></doc>
diff --git a/python/tests/tstxpath.py b/python/tests/tstxpath.py
new file mode 100755
index 0000000..f6c675a
--- /dev/null
+++ b/python/tests/tstxpath.py
@@ -0,0 +1,29 @@
+#!/usr/bin/python -u
+import libxml2
+
+def foo(x):
+    # print "foo called %s" % (x)
+    return x + 1
+
+def bar(x):
+    # print "foo called %s" % (x)
+    return "%s" % (x + 1)
+
+doc = libxml2.parseFile("tst.xml")
+ctxt = doc.xpathNewContext()
+res = ctxt.xpathEval("//*")
+print res
+
+libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
+libxml2.registerXPathFunction(ctxt._o, "bar", None, bar)
+i = 10000
+while i > 0:
+    res = ctxt.xpathEval("foo(1)")
+    i = i - 1
+print res
+i = 10000
+while i > 0:
+    res = ctxt.xpathEval("bar(1)")
+    i = i - 1
+print res
+doc.freeDoc()
diff --git a/python/tests/xpath.py b/python/tests/xpath.py
new file mode 100755
index 0000000..fdbd839
--- /dev/null
+++ b/python/tests/xpath.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python -u
+#
+# this test exercise the XPath basic engine, parser, etc, and
+# allows to detect memory leaks
+#
+import libxml2
+
+doc = libxml2.parseFile("tst.xml")
+print doc
+i = 1000
+while i > 0:
+    doc = libxml2.parseFile("tst.xml")
+    ctxt = doc.xpathNewContext()
+    res = ctxt.xpathEval("//*")
+    doc.freeDoc()
+    i = i -1
+doc = libxml2.parseFile("tst.xml")
+ctxt = doc.xpathNewContext()
+res = ctxt.xpathEval("//*")
+print res
+doc.freeDoc()
diff --git a/python/tests/xpathext.py b/python/tests/xpathext.py
new file mode 100755
index 0000000..d6f0455
--- /dev/null
+++ b/python/tests/xpathext.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python -u
+#
+# This test exercise the extension of the XPath engine with
+# functions defined in Python.
+#
+import libxml2
+
+def foo(x):
+    # print "foo called %s" % (x)
+    return x + 1
+
+def bar(x):
+    # print "foo called %s" % (x)
+    return "%s" % (x + 1)
+
+doc = libxml2.parseFile("tst.xml")
+ctxt = doc.xpathNewContext()
+res = ctxt.xpathEval("//*")
+print res
+
+libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
+libxml2.registerXPathFunction(ctxt._o, "bar", None, bar)
+i = 10000
+while i > 0:
+    res = ctxt.xpathEval("foo(1)")
+    i = i - 1
+print res
+i = 10000
+while i > 0:
+    res = ctxt.xpathEval("bar(1)")
+    i = i - 1
+print res
+doc.freeDoc()