From 263ec86a75f7b5ec2d37dbb89356bf7fca11cff3 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Mon, 4 Oct 2004 10:26:54 +0000 Subject: [PATCH] applied patch from Malcolm Tredinnick fixing bug #154294 related to saving * python/generator.py python/libxml.c python/tests/outbuf.py: applied patch from Malcolm Tredinnick fixing bug #154294 related to saving to python file objects. Daniel --- ChangeLog | 6 +++ python/generator.py | 10 ++++ python/libxml.c | 54 +++++++++++++++++++ python/tests/outbuf.py | 116 +++++++++++++++++++++++++++++++++-------- 4 files changed, 164 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4265e5cf..c77c1c68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Mon Oct 4 12:26:28 CEST 2004 Daniel Veillard + + * python/generator.py python/libxml.c python/tests/outbuf.py: + applied patch from Malcolm Tredinnick fixing bug #154294 + related to saving to python file objects. + Sat Oct 2 21:08:51 PDT 2004 William Brack * tree.c: changed xmlHasNsProp to properly handle a request for diff --git a/python/generator.py b/python/generator.py index df89c4e7..04b3832f 100755 --- a/python/generator.py +++ b/python/generator.py @@ -300,6 +300,13 @@ unknown_types = {} # ####################################################################### +# Class methods which are written by hand in libxml.c but the Python-level +# code is still automatically generated (so they are not in skip_function()). +skip_impl = ( + 'xmlSaveFileTo', + 'xmlSaveFormatFileTo', +) + def skip_function(name): if name[0:12] == "xmlXPathWrap": return 1 @@ -356,6 +363,9 @@ def print_function_wrapper(name, output, export, include): return 0 if skip_function(name) == 1: return 0 + if name in skip_impl: + # Don't delete the function entry in the caller. + return 1 c_call = ""; format="" diff --git a/python/libxml.c b/python/libxml.c index 9e243146..99d9ac3e 100644 --- a/python/libxml.c +++ b/python/libxml.c @@ -512,6 +512,11 @@ libxml_xmlOutputBufferClose(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { if (!PyArg_ParseTuple(args, (char *)"O:xmlOutputBufferClose", &pyobj_out)) return(NULL); out = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_out); + /* Buffer may already have been destroyed elsewhere. This is harmless. */ + if (out == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } c_retval = xmlOutputBufferClose(out); py_retval = libxml_intWrap((int) c_retval); @@ -533,6 +538,53 @@ libxml_xmlOutputBufferFlush(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { py_retval = libxml_intWrap((int) c_retval); return(py_retval); } + +static PyObject * +libxml_xmlSaveFileTo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + int c_retval; + xmlOutputBufferPtr buf; + PyObject *pyobj_buf; + xmlDocPtr cur; + PyObject *pyobj_cur; + char * encoding; + + if (!PyArg_ParseTuple(args, (char *)"OOz:xmlSaveFileTo", &pyobj_buf, &pyobj_cur, &encoding)) + return(NULL); + buf = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_buf); + cur = (xmlDocPtr) PyxmlNode_Get(pyobj_cur); + + c_retval = xmlSaveFileTo(buf, cur, encoding); + /* xmlSaveTo() freed the memory pointed to by buf, so record that in the + * Python object. */ + ((PyoutputBuffer_Object *)(pyobj_buf))->obj = NULL; + py_retval = libxml_intWrap((int) c_retval); + return(py_retval); +} + +static PyObject * +libxml_xmlSaveFormatFileTo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { + PyObject *py_retval; + int c_retval; + xmlOutputBufferPtr buf; + PyObject *pyobj_buf; + xmlDocPtr cur; + PyObject *pyobj_cur; + char * encoding; + int format; + + if (!PyArg_ParseTuple(args, (char *)"OOzi:xmlSaveFormatFileTo", &pyobj_buf, &pyobj_cur, &encoding, &format)) + return(NULL); + buf = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_buf); + cur = (xmlDocPtr) PyxmlNode_Get(pyobj_cur); + + c_retval = xmlSaveFormatFileTo(buf, cur, encoding, format); + /* xmlSaveFormatFileTo() freed the memory pointed to by buf, so record that + * in the Python object */ + ((PyoutputBuffer_Object *)(pyobj_buf))->obj = NULL; + py_retval = libxml_intWrap((int) c_retval); + return(py_retval); +} #endif /* LIBXML_OUTPUT_ENABLED */ @@ -3446,6 +3498,8 @@ static PyMethodDef libxmlMethods[] = { {(char *) "outputBufferGetPythonFile", libxml_outputBufferGetPythonFile, METH_VARARGS, NULL}, {(char *) "xmlOutputBufferClose", libxml_xmlOutputBufferClose, METH_VARARGS, NULL}, { (char *)"xmlOutputBufferFlush", libxml_xmlOutputBufferFlush, METH_VARARGS, NULL }, + { (char *)"xmlSaveFileTo", libxml_xmlSaveFileTo, METH_VARARGS, NULL }, + { (char *)"xmlSaveFormatFileTo", libxml_xmlSaveFormatFileTo, METH_VARARGS, NULL }, #endif /* LIBXML_OUTPUT_ENABLED */ {(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL}, {(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL}, diff --git a/python/tests/outbuf.py b/python/tests/outbuf.py index 4213159f..09cd9b5e 100755 --- a/python/tests/outbuf.py +++ b/python/tests/outbuf.py @@ -3,31 +3,103 @@ import sys import libxml2 import StringIO -#print "Skipped" -#sys.exit(1) +def testSimpleBufferWrites(): + f = StringIO.StringIO() + buf = libxml2.createOutputBuffer(f, "ISO-8859-1") + buf.write(3, "foo") + buf.writeString("bar") + buf.close() + + if f.getvalue() != "foobar": + print "Failed to save to StringIO" + sys.exit(1) -# Memory debug specific -libxml2.debugMemory(1) +def testSaveDocToBuffer(): + """ + Regression test for bug #154294. + """ + input = 'Hello' + expected = '''\ + +Hello +''' + f = StringIO.StringIO() + buf = libxml2.createOutputBuffer(f, 'UTF-8') + doc = libxml2.parseDoc(input) + doc.saveFileTo(buf, 'UTF-8') + doc.freeDoc() + if f.getvalue() != expected: + print 'xmlDoc.saveFileTo() call failed.' + print ' got: %s' % repr(f.getvalue()) + print 'expected: %s' % repr(expected) + sys.exit(1) -#f = open('res', 'w') -f = StringIO.StringIO() -buf = libxml2.createOutputBuffer(f, "ISO-8859-1") -buf.write(3, "foo") -buf.writeString("bar") -buf.close() +def testSaveFormattedDocToBuffer(): + input = 'Some text' + # The formatted and non-formatted versions of the output. + expected = ('''\ + +Some text +''', '''\ + + + Some text + + +''') + doc = libxml2.parseDoc(input) + for i in (0, 1): + f = StringIO.StringIO() + buf = libxml2.createOutputBuffer(f, 'UTF-8') + doc.saveFormatFileTo(buf, 'UTF-8', i) + if f.getvalue() != expected[i]: + print 'xmlDoc.saveFormatFileTo() call failed.' + print ' got: %s' % repr(f.getvalue()) + print 'expected: %s' % repr(expected[i]) + sys.exit(1) + doc.freeDoc() -if f.getvalue() != "foobar": - print "Failed to save to StringIO" - sys.exit(1) +def testSaveIntoOutputBuffer(): + """ + Similar to the previous two tests, except this time we invoke the save + methods on the output buffer object and pass in an XML node object. + """ + input = 'Hello' + expected = '''\ + +Hello +''' + f = StringIO.StringIO() + doc = libxml2.parseDoc(input) + buf = libxml2.createOutputBuffer(f, 'UTF-8') + buf.saveFileTo(doc, 'UTF-8') + if f.getvalue() != expected: + print 'outputBuffer.saveFileTo() call failed.' + print ' got: %s' % repr(f.getvalue()) + print 'expected: %s' % repr(expected) + sys.exit(1) + f = StringIO.StringIO() + buf = libxml2.createOutputBuffer(f, 'UTF-8') + buf.saveFormatFileTo(doc, 'UTF-8', 1) + if f.getvalue() != expected: + print 'outputBuffer.saveFormatFileTo() call failed.' + print ' got: %s' % repr(f.getvalue()) + print 'expected: %s' % repr(expected) + sys.exit(1) + doc.freeDoc() -del buf -del f +if __name__ == '__main__': + # Memory debug specific + libxml2.debugMemory(1) -# Memory debug specific -libxml2.cleanupParser() -if libxml2.debugMemory(1) == 0: - print "OK" -else: - print "Memory leak %d bytes" % (libxml2.debugMemory(1)) - libxml2.dumpMemory() + testSimpleBufferWrites() + testSaveDocToBuffer() + testSaveFormattedDocToBuffer() + testSaveIntoOutputBuffer() + libxml2.cleanupParser() + if libxml2.debugMemory(1) == 0: + print "OK" + else: + print "Memory leak %d bytes" % (libxml2.debugMemory(1)) + libxml2.dumpMemory()