diff --git a/ChangeLog b/ChangeLog index 1280f73e..fabaffb5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Tue Jan 6 23:51:46 CET 2004 Daniel Veillard + + * python/libxml2-python-api.xml python/libxml_wrap.h python/types.c + python/tests/Makefile.am python/tests/tstLastError.py: applied + patch from Stephane Bidoul for structured error handling from + python, and the associated test + Tue Jan 6 23:18:11 HKT 2004 William Brack * configure.in: fixed Bug130593 diff --git a/python/generator.py b/python/generator.py index ce0b8f35..db7be28f 100755 --- a/python/generator.py +++ b/python/generator.py @@ -268,6 +268,7 @@ py_types = { 'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"), 'FILE *': ('O', "File", "FILEPtr", "FILE *"), 'xmlURIPtr': ('O', "URI", "xmlURIPtr", "xmlURIPtr"), + 'xmlErrorPtr': ('O', "Error", "xmlErrorPtr", "xmlErrorPtr"), 'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutputBufferPtr"), 'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"), 'xmlRegexpPtr': ('O', "xmlReg", "xmlRegexpPtr", "xmlRegexpPtr"), @@ -641,6 +642,7 @@ classes_type = { "htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"), "xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"), + "xmlErrorPtr": ("._o", "Error(_obj=%s)", "Error"), "xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"), "xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"), "xmlRegexpPtr": ("._o", "xmlReg(_obj=%s)", "xmlReg"), @@ -721,6 +723,9 @@ def nameFixup(name, classe, type, file): elif name[0:9] == "xmlURISet" and file == "python_accessor": func = name[6:] func = string.lower(func[0:1]) + func[1:] + elif name[0:11] == "xmlErrorGet" and file == "python_accessor": + func = name[11:] + func = string.lower(func[0:1]) + func[1:] elif name[0:17] == "xmlXPathParserGet" and file == "python_accessor": func = name[17:] func = string.lower(func[0:1]) + func[1:] diff --git a/python/libxml2-python-api.xml b/python/libxml2-python-api.xml index 7e8e922c..d5a4cbe6 100644 --- a/python/libxml2-python-api.xml +++ b/python/libxml2-python-api.xml @@ -275,5 +275,36 @@ + + + What part of the library raised this error + + + + + The error code, e.g. an xmlParserError + + + + + human-readable informative error message + + + + + how consequent is the error + + + + + the filename + + + + + the line number if available + + + diff --git a/python/libxml2class.txt b/python/libxml2class.txt index eebdf6f9..8325abce 100644 --- a/python/libxml2class.txt +++ b/python/libxml2class.txt @@ -203,6 +203,7 @@ registerDefaultOutputCallbacks() registerHTTPPostCallbacks() # functions from module xmlerror +lastError() resetLastError() # functions from module xmlreader @@ -779,6 +780,18 @@ Class relaxNgSchema() # functions from module xmlreader RelaxNGSetSchema() +Class Error() + # accessors + code() + domain() + file() + level() + line() + message() + + # functions from module xmlerror + copyError() + resetError() Class relaxNgValidCtxt() # functions from module relaxng diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h index 064f8a8f..09fc77fe 100644 --- a/python/libxml_wrap.h +++ b/python/libxml_wrap.h @@ -107,6 +107,14 @@ typedef struct { #define PyURI_Get(v) (((v) == Py_None) ? NULL : \ (((PyURI_Object *)(v))->obj)) +typedef struct { + PyObject_HEAD + xmlErrorPtr obj; +} PyError_Object; + +#define PyError_Get(v) (((v) == Py_None) ? NULL : \ + (((PyError_Object *)(v))->obj)) + typedef struct { PyObject_HEAD xmlOutputBufferPtr obj; @@ -194,3 +202,4 @@ PyObject * libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt); PyObject * libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt); PyObject * libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid); #endif /* LIBXML_SCHEMAS_ENABLED */ +PyObject * libxml_xmlErrorPtrWrap(xmlErrorPtr error); diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am index fd704fdf..c496dc88 100644 --- a/python/tests/Makefile.am +++ b/python/tests/Makefile.am @@ -31,7 +31,8 @@ PYTESTS= \ ctxterror.py\ readererr.py\ relaxng.py \ - thread2.py + thread2.py \ + tstLastError.py XMLS= \ tst.xml \ diff --git a/python/tests/tstLastError.py b/python/tests/tstLastError.py new file mode 100755 index 00000000..12229e8c --- /dev/null +++ b/python/tests/tstLastError.py @@ -0,0 +1,72 @@ +#!/usr/bin/python -u +import sys, unittest + +import libxml2 + +class TestCase(unittest.TestCase): + + def setUp(self): + libxml2.debugMemory(1) + + def tearDown(self): + libxml2.cleanupParser() + if libxml2.debugMemory(1) != 0: + libxml2.dumpMemory() + self.fail("Memory leak %d bytes" % (libxml2.debugMemory(1),)) + + def failUnlessXmlError(self,f,args,exc,domain,code,message,level,file,line): + """Run function f, with arguments args and expect an exception exc; + when the exception is raised, check the libxml2.lastError for + expected values.""" + # disable the default error handler + libxml2.registerErrorHandler(None,None) + try: + f(*args) + except exc: + e = libxml2.lastError() + if e is None: + self.fail("lastError not set") + if 0: + print "domain = ",e.domain() + print "code = ",e.code() + print "message =",repr(e.message()) + print "level =",e.level() + print "file =",e.file() + print "line =",e.line() + print + self.failUnlessEqual(domain,e.domain()) + self.failUnlessEqual(code,e.code()) + self.failUnlessEqual(message,e.message()) + self.failUnlessEqual(level,e.level()) + self.failUnlessEqual(file,e.file()) + self.failUnlessEqual(line,e.line()) + else: + self.fail("exception %s should have been raised" % exc) + + def test1(self): + """Test readFile with a file that does not exist""" + self.failUnlessXmlError(libxml2.readFile, + ("dummy.xml",None,0), + libxml2.treeError, + domain=8, # XML_FROM_IO + code=1549, # XML_IO_LOAD_ERROR + message='failed to load external entity "dummy.xml"\n', + level=1, # XML_ERR_WARNING + file=None, + line=0) + + def test2(self): + """Test a well-formedness error: we get the last error only""" + s = "\n\n" + self.failUnlessXmlError(libxml2.readMemory, + (s,len(s),"dummy.xml",None,0), + libxml2.treeError, + domain=1, # XML_FROM_PARSER + code=77, # XML_ERR_TAG_NOT_FINISHED + message='Premature end of data in tag x line 1\n', + level=3, # XML_ERR_FATAL + file='dummy.xml', + line=3) + +if __name__ == "__main__": + unittest.main() diff --git a/python/types.c b/python/types.c index a9717912..42279d00 100644 --- a/python/types.c +++ b/python/types.c @@ -641,3 +641,21 @@ libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid) return (ret); } #endif /* LIBXML_SCHEMAS_ENABLED */ + +PyObject * +libxml_xmlErrorPtrWrap(xmlErrorPtr error) +{ + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlErrorPtrWrap: error = %p\n", error); +#endif + if (error == NULL) { + Py_INCREF(Py_None); + return (Py_None); + } + ret = + PyCObject_FromVoidPtrAndDesc((void *) error, + (char *) "xmlErrorPtr", NULL); + return (ret); +}