1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-28 00:21:53 +03:00

applied and fixed a patch from Stephane Bibould to provide per parser

* python/generator.py python/libxml.c python/libxml.py
  python/libxml_wrap.h python/types.c: applied and fixed a patch
  from Stephane Bibould to provide per parser error handlers at the
  Python level.
* python/tests/Makefile.am python/tests/ctxterror.py: added a
  regression test for it.
Daniel
This commit is contained in:
Daniel Veillard
2003-01-14 11:42:39 +00:00
parent 4dbe77a84f
commit e6227e0549
9 changed files with 312 additions and 29 deletions

View File

@ -290,6 +290,8 @@ unknown_types = {}
def skip_function(name):
if name[0:12] == "xmlXPathWrap":
return 1
if name == "xmlFreeParserCtxt":
return 1
# if name[0:11] == "xmlXPathNew":
# return 1
return 0
@ -618,6 +620,7 @@ classes_ancestor = {
"xmlAttribute" : "xmlNode",
"outputBuffer": "ioWriteWrapper",
"inputBuffer": "ioReadWrapper",
"parserCtxt": "parserCtxtCore",
}
classes_destructors = {
"parserCtxt": "xmlFreeParserCtxt",

View File

@ -1176,6 +1176,32 @@ libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
return (Py_None);
}
PyObject *
libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
xmlParserCtxtPtr ctxt;
PyObject *pyobj_ctxt;
xmlParserCtxtPyCtxtPtr pyCtxt;
if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeParserCtxt", &pyobj_ctxt))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
if (ctxt != NULL) {
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
if (pyCtxt) {
Py_XDECREF(pyCtxt->errorFunc);
Py_XDECREF(pyCtxt->errorFuncArg);
Py_XDECREF(pyCtxt->warningFunc);
Py_XDECREF(pyCtxt->warningFuncArg);
xmlFree(pyCtxt);
}
xmlFreeParserCtxt(ctxt);
}
Py_INCREF(Py_None);
return(Py_None);
}
/************************************************************************
* *
* Error message callback *
@ -1185,13 +1211,43 @@ libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
static PyObject *libxml_xmlPythonErrorFuncHandler = NULL;
static PyObject *libxml_xmlPythonErrorFuncCtxt = NULL;
static void
libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg,
...)
/* helper to build a xmlMalloc'ed string from a format and va_list */
static char *
libxml_buildMessage(const char *msg, va_list ap)
{
int size;
int chars;
char *larger;
char *str;
str = (char *) xmlMalloc(150);
if (str == NULL)
return NULL;
size = 150;
while (1) {
chars = vsnprintf(str, size, msg, ap);
if ((chars > -1) && (chars < size))
break;
if (chars > -1)
size += chars + 1;
else
size += 100;
if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
xmlFree(str);
return NULL;
}
str = larger;
}
return str;
}
static void
libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg,
...)
{
va_list ap;
char *str;
PyObject *list;
@ -1208,28 +1264,9 @@ libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg,
vfprintf(stdout, msg, ap);
va_end(ap);
} else {
str = (char *) xmlMalloc(150);
if (str == NULL)
return;
size = 150;
while (1) {
va_start(ap, msg);
chars = vsnprintf(str, size, msg, ap);
va_end(ap);
if ((chars > -1) && (chars < size))
break;
if (chars > -1)
size += chars + 1;
else
size += 100;
if ((larger = (char *) xmlRealloc(str, size)) == NULL) {
xmlFree(str);
return;
}
str = larger;
}
va_start(ap, msg);
str = libxml_buildMessage(msg,ap);
va_end(ap);
list = PyTuple_New(2);
PyTuple_SetItem(list, 0, libxml_xmlPythonErrorFuncCtxt);
@ -1287,6 +1324,147 @@ libxml_xmlRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,
return (py_retval);
}
/************************************************************************
* *
* Per parserCtxt error handler *
* *
************************************************************************/
static void
libxml_xmlParserCtxtErrorFuncHandler(void *ctxt, const char *msg, ...)
{
char *str;
va_list ap;
PyObject *list;
PyObject *message;
PyObject *result;
xmlParserCtxtPyCtxtPtr pyCtxt;
#ifdef DEBUG_ERROR
printf("libxml_xmlParserCtxtErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
#endif
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
if (pyCtxt->errorFunc == NULL) {
va_start(ap, msg);
vfprintf(stdout, msg, ap);
va_end(ap);
} else {
va_start(ap, msg);
str = libxml_buildMessage(msg,ap);
va_end(ap);
list = PyTuple_New(2);
PyTuple_SetItem(list, 0, pyCtxt->errorFuncArg);
Py_XINCREF(pyCtxt->errorFuncArg);
message = libxml_charPtrWrap(str);
PyTuple_SetItem(list, 1, message);
result = PyEval_CallObject(pyCtxt->errorFunc, list);
Py_XDECREF(list);
Py_XDECREF(result);
}
}
PyObject *
libxml_xmlSetParserCtxtErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
{
PyObject *py_retval;
xmlParserCtxtPtr ctxt;
PyObject *pyobj_ctxt;
PyObject *pyobj_f;
PyObject *pyobj_arg;
if (!PyArg_ParseTuple(args, (char *)"OOO:xmlSetParserCtxtErrorHandler",
&pyobj_ctxt, &pyobj_f, &pyobj_arg))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
if (ctxt->_private == NULL) {
xmlParserCtxtPyCtxt *pyCtxt;
pyCtxt = xmlMalloc(sizeof(xmlParserCtxtPyCtxt));
if (pyCtxt == NULL) {
py_retval = libxml_intWrap(-1);
return(py_retval);
}
memset(pyCtxt,0,sizeof(xmlParserCtxtPyCtxt));
ctxt->_private = pyCtxt;
}
/* TODO: check f is a function ! */
Py_XINCREF(pyobj_f);
((xmlParserCtxtPyCtxt *)ctxt->_private)->errorFunc = pyobj_f;
Py_XINCREF(pyobj_arg);
((xmlParserCtxtPyCtxt *)ctxt->_private)->errorFuncArg = pyobj_arg;
ctxt->sax->error = libxml_xmlParserCtxtErrorFuncHandler;
ctxt->vctxt.error = libxml_xmlParserCtxtErrorFuncHandler;
py_retval = libxml_intWrap(1);
return(py_retval);
}
static void
libxml_xmlParserCtxtWarningFuncHandler(void *ctxt, const char *msg, ...)
{
char *str;
va_list ap;
PyObject *list;
PyObject *message;
PyObject *result;
xmlParserCtxtPyCtxtPtr pyCtxt;
#ifdef DEBUG_ERROR
printf("libxml_xmlParserCtxtWarningFuncHandler(%p, %s, ...) called\n", ctx, msg);
#endif
pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
if (pyCtxt->warningFunc == NULL) {
va_start(ap, msg);
vfprintf(stdout, msg, ap);
va_end(ap);
} else {
va_start(ap, msg);
str = libxml_buildMessage(msg,ap);
va_end(ap);
list = PyTuple_New(2);
PyTuple_SetItem(list, 0, pyCtxt->warningFuncArg);
Py_XINCREF(pyCtxt->warningFuncArg);
message = libxml_charPtrWrap(str);
PyTuple_SetItem(list, 1, message);
result = PyEval_CallObject(pyCtxt->warningFunc, list);
Py_XDECREF(list);
Py_XDECREF(result);
}
}
PyObject *
libxml_xmlSetParserCtxtWarningHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
{
PyObject *py_retval;
xmlParserCtxtPtr ctxt;
PyObject *pyobj_ctxt;
PyObject *pyobj_f;
PyObject *pyobj_arg;
if (!PyArg_ParseTuple(args, (char *)"OOO:xmlSetParserCtxtWarningHandler", &pyobj_ctxt, &pyobj_f, &pyobj_arg))
return(NULL);
ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
/* TODO: check f is a function ! */
Py_XINCREF(pyobj_f);
((xmlParserCtxtPyCtxt *)ctxt->_private)->warningFunc = pyobj_f;
Py_XINCREF(pyobj_arg);
((xmlParserCtxtPyCtxt *)ctxt->_private)->warningFuncArg = pyobj_arg;
ctxt->sax->warning = libxml_xmlParserCtxtWarningFuncHandler;
ctxt->vctxt.warning = libxml_xmlParserCtxtWarningFuncHandler;
py_retval = libxml_intWrap(1);
return(py_retval);
}
/************************************************************************
* *
* XPath extensions *
@ -2196,6 +2374,9 @@ static PyMethodDef libxmlMethods[] = {
{(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
{(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
{(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlSetParserCtxtErrorHandler", libxml_xmlSetParserCtxtErrorHandler, METH_VARARGS, NULL },
{(char *)"xmlSetParserCtxtWarningHandler", libxml_xmlSetParserCtxtWarningHandler, METH_VARARGS, NULL },
{(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
{NULL, NULL, 0, NULL}
};

View File

@ -478,6 +478,25 @@ def registerErrorHandler(f, ctx):
ret = libxslt.registerErrorHandler(f,ctx)
return ret
class parserCtxtCore:
def __init__(self, _obj=None):
if _obj != None:
self._o = _obj;
return
self._o = None
def __del__(self):
if self._o != None:
libxml2mod.xmlFreeParserCtxt(self._o)
self._o = None
def registerErrorHandler(self,f,arg):
libxml2mod.xmlSetParserCtxtErrorHandler(self._o,f,arg)
def registerWarningHandler(self,f,arg):
libxml2mod.xmlSetParserCtxtWarningHandler(self._o,f,arg)
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
#
# Everything before this line comes from libxml.py

View File

@ -662,7 +662,9 @@ Class xpathParserContext()
xpathTrueFunction()
xpathValueFlipSign()
xpatherror()
Class parserCtxt()
Class parserCtxt(parserCtxtCore)
# accessors
doc()
isValid()
@ -682,7 +684,6 @@ Class parserCtxt()
# functions from module parser
clearParserCtxt()
freeParserCtxt()
initParserCtxt()
parseChunk()
parseDocument()

View File

@ -149,3 +149,17 @@ PyObject * libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp);
PyObject * libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader);
xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
/*
* Data structure that makes the link from the parser context
* to the python wrapper.
*/
typedef struct
{
PyObject *errorFunc;
PyObject *errorFuncArg;
PyObject *warningFunc;
PyObject *warningFuncArg;
} xmlParserCtxtPyCtxt;
typedef xmlParserCtxtPyCtxt *xmlParserCtxtPyCtxtPtr;

View File

@ -22,8 +22,8 @@ PYTESTS= \
regexp.py \
reader.py \
reader2.py \
reader3.py
reader3.py \
ctxterror.py
XMLS= \
tst.xml \

55
python/tests/ctxterror.py Executable file
View File

@ -0,0 +1,55 @@
#!/usr/bin/python -u
#
# This test exercise the redirection of error messages with a
# functions defined in Python.
#
import sys
import libxml2
# Memory debug specific
libxml2.debugMemory(1)
expect="""--> Opening and ending tag mismatch: x and y
"""
err=""
def callback(ctx, str):
global err
err = err + "%s %s" % (ctx, str)
s = """<x></y>"""
parserCtxt = libxml2.createPushParser(None,"",0,"test.xml")
parserCtxt.registerErrorHandler(callback, "-->")
parserCtxt.registerWarningHandler(callback, "-->")
parserCtxt.parseChunk(s,len(s),1)
doc = parserCtxt.doc()
doc.freeDoc()
parserCtxt = None
if err != expect:
print "error"
print "received %s" %(err)
print "expected %s" %(expect)
sys.exit(1)
i = 10000
while i > 0:
parserCtxt = libxml2.createPushParser(None,"",0,"test.xml")
parserCtxt.registerErrorHandler(callback, "-->")
parserCtxt.registerWarningHandler(callback, "-->")
parserCtxt.parseChunk(s,len(s),1)
doc = parserCtxt.doc()
doc.freeDoc()
parserCtxt = None
err = ""
i = i - 1
# Memory debug specific
libxml2.cleanupParser()
if libxml2.debugMemory(1) == 0:
print "OK"
else:
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
libxml2.dumpMemory()

View File

@ -323,6 +323,7 @@ libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt)
Py_INCREF(Py_None);
return (Py_None);
}
ret =
PyCObject_FromVoidPtrAndDesc((void *) ctxt,
(char *) "xmlParserCtxtPtr", NULL);