1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-29 11:41:22 +03:00

updated the python bindings, added code for easier File I/O, and the

* python/generator.py python/libxml.c python/libxml.py
  python/libxml2-python-api.xml python/libxml2class.txt
  python/libxml_wrap.h python/types.c: updated the python
  bindings, added code for easier File I/O, and the ability to
  define a resolver from Python fixing bug #91635
* python/tests/Makefile.am python/tests/inbuf.py
  python/tests/outbuf.py python/tests/pushSAXhtml.py
  python/tests/resolver.py python/tests/serialize.py: updated
  and augmented the set of Python tests.
Daniel
This commit is contained in:
Daniel Veillard
2002-09-12 15:00:57 +00:00
parent 353bf5822a
commit c6d4a933f0
14 changed files with 677 additions and 12 deletions

View File

@ -268,6 +268,8 @@ py_types = {
'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"),
'FILE *': ('O', "File", "FILEPtr", "FILE *"),
'xmlURIPtr': ('O', "URI", "xmlURIPtr", "xmlURIPtr"),
'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutputBufferPtr"),
'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"),
}
py_return_types = {
@ -583,6 +585,8 @@ classes_type = {
"htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
"xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"),
"xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"),
"xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"),
"xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"),
}
converter_type = {
@ -600,11 +604,15 @@ classes_ancestor = {
"xmlEntity" : "xmlNode",
"xmlElement" : "xmlNode",
"xmlAttribute" : "xmlNode",
"outputBuffer": "ioWriteWrapper",
"inputBuffer": "ioReadWrapper",
}
classes_destructors = {
"parserCtxt": "xmlFreeParserCtxt",
"catalog": "xmlFreeCatalog",
"URI": "xmlFreeURI",
# "outputBuffer": "xmlOutputBufferClose",
"inputBuffer": "xmlFreeParserInputBuffer",
}
functions_noexcept = {
@ -647,6 +655,12 @@ def nameFixup(name, classe, type, file):
elif name[0:11] == "xmlXPathSet" and file == "python_accessor":
func = name[8:]
func = string.lower(func[0:1]) + func[1:]
elif name[0:15] == "xmlOutputBuffer" and file != "python":
func = name[15:]
func = string.lower(func[0:1]) + func[1:]
elif name[0:20] == "xmlParserInputBuffer" and file != "python":
func = name[20:]
func = string.lower(func[0:1]) + func[1:]
elif name[0:11] == "xmlACatalog":
func = name[11:]
func = string.lower(func[0:1]) + func[1:]

View File

@ -12,6 +12,7 @@
* daniel@veillard.com
*/
#include <Python.h>
#include <fileobject.h>
#include "config.h"
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
@ -20,21 +21,30 @@
#include <libxml/xmlerror.h>
#include <libxml/xpathInternals.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlIO.h>
#include "libxml_wrap.h"
#include "libxml2-py.h"
/* #define DEBUG */
/* #define DEBUG_SAX */
/* #define DEBUG_XPATH */
/* #define DEBUG_ERROR */
/* #define DEBUG_MEMORY */
/* #define DEBUG_FILES */
/* #define DEBUG_LOADER */
void initlibxml2mod(void);
/**
* TODO:
*
* macro to flag unimplemented blocks
*/
#define TODO \
xmlGenericError(xmlGenericErrorContext, \
"Unimplemented block at %s:%d\n", \
__FILE__, __LINE__);
/************************************************************************
* *
* Memory debug interface *
@ -123,6 +133,363 @@ libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
return (Py_None);
}
/************************************************************************
* *
* Handling Python FILE I/O at the C level *
* The raw I/O attack diectly the File objects, while the *
* other routines address the ioWrapper instance instead *
* *
************************************************************************/
/**
* xmlPythonFileCloseUnref:
* @context: the I/O context
*
* Close an I/O channel
*/
static int
xmlPythonFileCloseRaw (void * context) {
PyObject *file, *ret;
#ifdef DEBUG_FILES
printf("xmlPythonFileCloseUnref\n");
#endif
file = (PyObject *) context;
if (file == NULL) return(-1);
ret = PyEval_CallMethod(file, "close", "()");
if (ret != NULL) {
Py_DECREF(ret);
}
Py_DECREF(file);
return(0);
}
/**
* xmlPythonFileReadRaw:
* @context: the I/O context
* @buffer: where to drop data
* @len: number of bytes to write
*
* Read @len bytes to @buffer from the Python file in the I/O channel
*
* Returns the number of bytes read
*/
static int
xmlPythonFileReadRaw (void * context, char * buffer, int len) {
PyObject *file;
PyObject *ret;
int lenread = -1;
char *data;
#ifdef DEBUG_FILES
printf("xmlPythonFileReadRaw: %d\n", len);
#endif
file = (PyObject *) context;
if (file == NULL) return(-1);
ret = PyEval_CallMethod(file, "read", "(i)", len);
if (ret == NULL) {
printf("xmlPythonFileReadRaw: result is NULL\n");
return(-1);
} else if (PyString_Check(ret)) {
lenread = PyString_Size(ret);
data = PyString_AsString(ret);
if (lenread > len)
memcpy(buffer, data, len);
else
memcpy(buffer, data, lenread);
Py_DECREF(ret);
} else {
printf("xmlPythonFileReadRaw: result is not a String\n");
Py_DECREF(ret);
}
return(lenread);
}
/**
* xmlPythonFileRead:
* @context: the I/O context
* @buffer: where to drop data
* @len: number of bytes to write
*
* Read @len bytes to @buffer from the I/O channel.
*
* Returns the number of bytes read
*/
static int
xmlPythonFileRead (void * context, char * buffer, int len) {
PyObject *file;
PyObject *ret;
int lenread = -1;
char *data;
#ifdef DEBUG_FILES
printf("xmlPythonFileRead: %d\n", len);
#endif
file = (PyObject *) context;
if (file == NULL) return(-1);
ret = PyEval_CallMethod(file, "io_read", "(i)", len);
if (ret == NULL) {
printf("xmlPythonFileRead: result is NULL\n");
return(-1);
} else if (PyString_Check(ret)) {
lenread = PyString_Size(ret);
data = PyString_AsString(ret);
if (lenread > len)
memcpy(buffer, data, len);
else
memcpy(buffer, data, lenread);
Py_DECREF(ret);
} else {
printf("xmlPythonFileRead: result is not a String\n");
Py_DECREF(ret);
}
return(lenread);
}
/**
* xmlFileWrite:
* @context: the I/O context
* @buffer: where to drop data
* @len: number of bytes to write
*
* Write @len bytes from @buffer to the I/O channel.
*
* Returns the number of bytes written
*/
static int
xmlPythonFileWrite (void * context, const char * buffer, int len) {
PyObject *file;
PyObject *string;
PyObject *ret;
int written = -1;
#ifdef DEBUG_FILES
printf("xmlPythonFileWrite: %d\n", len);
#endif
file = (PyObject *) context;
if (file == NULL) return(-1);
string = PyString_FromStringAndSize(buffer, len);
if (string == NULL) return(-1);
ret = PyEval_CallMethod(file, "io_write", "(O)", string);
Py_DECREF(string);
if (ret == NULL) {
printf("xmlPythonFileWrite: result is NULL\n");
return(-1);
} else if (PyInt_Check(ret)) {
written = (int) PyInt_AsLong(ret);
Py_DECREF(ret);
} else if (ret == Py_None) {
written = len;
Py_DECREF(ret);
} else {
printf("xmlPythonFileWrite: result is not an Int nor None\n");
Py_DECREF(ret);
}
return(written);
}
/**
* xmlPythonFileClose:
* @context: the I/O context
*
* Close an I/O channel
*/
static int
xmlPythonFileClose (void * context) {
PyObject *file, *ret;
#ifdef DEBUG_FILES
printf("xmlPythonFileClose\n");
#endif
file = (PyObject *) context;
if (file == NULL) return(-1);
ret = PyEval_CallMethod(file, "io_close", "()");
if (ret != NULL) {
Py_DECREF(ret);
}
return(0);
}
/**
* xmlOutputBufferCreatePythonFile:
* @file: a PyFile_Type
* @encoder: the encoding converter or NULL
*
* Create a buffered output for the progressive saving to a PyFile_Type
* buffered C I/O
*
* Returns the new parser output or NULL
*/
xmlOutputBufferPtr
xmlOutputBufferCreatePythonFile(PyObject *file,
xmlCharEncodingHandlerPtr encoder) {
xmlOutputBufferPtr ret;
if (file == NULL) return(NULL);
ret = xmlAllocOutputBuffer(encoder);
if (ret != NULL) {
ret->context = file;
/* Py_INCREF(file); */
ret->writecallback = xmlPythonFileWrite;
ret->closecallback = xmlPythonFileClose;
}
return(ret);
}
PyObject *
libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
PyObject *py_retval;
PyObject *file;
xmlChar *encoding;
xmlCharEncodingHandlerPtr handler = NULL;
xmlOutputBufferPtr buffer;
if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate",
&file, &encoding))
return(NULL);
if ((encoding != NULL) && (encoding[0] != 0)) {
handler = xmlFindCharEncodingHandler(encoding);
}
buffer = xmlOutputBufferCreatePythonFile(file, handler);
if (buffer == NULL)
printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n");
py_retval = libxml_xmlOutputBufferPtrWrap(buffer);
return(py_retval);
}
/**
* xmlParserInputBufferCreatePythonFile:
* @file: a PyFile_Type
* @encoder: the encoding converter or NULL
*
* Create a buffered output for the progressive saving to a PyFile_Type
* buffered C I/O
*
* Returns the new parser output or NULL
*/
xmlParserInputBufferPtr
xmlParserInputBufferCreatePythonFile(PyObject *file,
xmlCharEncoding encoding) {
xmlParserInputBufferPtr ret;
if (file == NULL) return(NULL);
ret = xmlAllocParserInputBuffer(encoding);
if (ret != NULL) {
ret->context = file;
/* Py_INCREF(file); */
ret->readcallback = xmlPythonFileRead;
ret->closecallback = xmlPythonFileClose;
}
return(ret);
}
PyObject *
libxml_xmlCreateInputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
PyObject *py_retval;
PyObject *file;
xmlChar *encoding;
xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
xmlParserInputBufferPtr buffer;
if (!PyArg_ParseTuple(args, (char *)"Oz:xmlParserInputBufferCreate",
&file, &encoding))
return(NULL);
if ((encoding != NULL) && (encoding[0] != 0)) {
enc = xmlParseCharEncoding(encoding);
}
buffer = xmlParserInputBufferCreatePythonFile(file, enc);
if (buffer == NULL)
printf("libxml_xmlParserInputBufferCreate: buffer == NULL\n");
py_retval = libxml_xmlParserInputBufferPtrWrap(buffer);
return(py_retval);
}
/************************************************************************
* *
* Providing the resolver at the Python level *
* *
************************************************************************/
static xmlExternalEntityLoader defaultExternalEntityLoader = NULL;
static PyObject *pythonExternalEntityLoaderObjext;
static xmlParserInputPtr
pythonExternalEntityLoader(const char *URL, const char *ID,
xmlParserCtxtPtr ctxt) {
xmlParserInputPtr result = NULL;
if (pythonExternalEntityLoaderObjext != NULL) {
PyObject *ret;
PyObject *ctxtobj;
ctxtobj = libxml_xmlParserCtxtPtrWrap(ctxt);
#ifdef DEBUG_LOADER
printf("pythonExternalEntityLoader: ready to call\n");
#endif
ret = PyObject_CallFunction(pythonExternalEntityLoaderObjext,
"(ssO)", URL, ID, ctxtobj);
#ifdef DEBUG_LOADER
printf("pythonExternalEntityLoader: result ");
PyObject_Print(ret, stdout, 0);
printf("\n");
#endif
if (ret != NULL) {
if (PyObject_HasAttrString(ret, "read")) {
xmlParserInputBufferPtr buf;
buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
if (buf != NULL) {
buf->context = ret;
buf->readcallback = xmlPythonFileReadRaw;
buf->closecallback = xmlPythonFileCloseRaw;
result = xmlNewIOInputStream(ctxt, buf,
XML_CHAR_ENCODING_NONE);
}
} else {
printf("pythonExternalEntityLoader: can't read\n");
}
if (result == NULL) {
Py_DECREF(ret);
}
}
}
if ((result == NULL) && (defaultExternalEntityLoader != NULL)) {
result = defaultExternalEntityLoader(URL, ID, ctxt);
}
return(result);
}
PyObject *
libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
PyObject *py_retval;
PyObject *loader;
if (!PyArg_ParseTuple(args, (char *)"O:libxml_xmlSetEntityLoader",
&loader))
return(NULL);
#ifdef DEBUG_LOADER
printf("libxml_xmlSetEntityLoader\n");
#endif
if (defaultExternalEntityLoader == NULL)
defaultExternalEntityLoader = xmlGetExternalEntityLoader();
pythonExternalEntityLoaderObjext = loader;
xmlSetExternalEntityLoader(pythonExternalEntityLoader);
py_retval = PyInt_FromLong(0);
return(py_retval);
}
/************************************************************************
* *
* Handling SAX/xmllib/sgmlop callback interfaces *
@ -1821,6 +2188,9 @@ static PyMethodDef libxmlMethods[] = {
{(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
{(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
{(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
{(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
{(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
{(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
@ -1836,6 +2206,8 @@ initlibxml2mod(void)
if (initialized != 0)
return;
xmlRegisterDefaultOutputCallbacks();
xmlRegisterDefaultInputCallbacks();
m = Py_InitModule((char *) "libxml2mod", libxmlMethods);
initialized = 1;
libxml_xmlErrorInitialize();

View File

@ -27,6 +27,74 @@ class xpathError:
def __str__(self):
return self.msg
class ioWrapper:
def __init__(self, _obj):
self.__io = _obj
self._o = None
def io_close(self):
if self.__io == None:
return(-1)
self.__io.close()
self.__io = None
return(0)
def io_flush(self):
if self.__io == None:
return(-1)
self.__io.flush()
return(0)
def io_read(self, len = -1):
if self.__io == None:
return(-1)
if len < 0:
return(self.__io.read())
return(self.__io.read(len))
def io_write(self, str, len = -1):
if self.__io == None:
return(-1)
if len < 0:
return(self.__io.write(str))
return(self.__io.write(str, len))
class ioReadWrapper(ioWrapper):
def __init__(self, _obj, enc = ""):
ioWrapper.__init__(self, _obj)
self._o = libxml2mod.xmlCreateInputBuffer(self, enc)
def __del__(self):
print "__del__"
self.io_close()
if self._o != None:
libxml2mod.xmlFreeParserInputBuffer(self._o)
self._o = None
def close(self):
self.io_close()
if self._o != None:
libxml2mod.xmlFreeParserInputBuffer(self._o)
self._o = None
class ioWriteWrapper(ioWrapper):
def __init__(self, _obj, enc = ""):
ioWrapper.__init__(self, _obj)
self._o = libxml2mod.xmlCreateOutputBuffer(self, enc)
def __del__(self):
print "__del__"
self.io_close()
if self._o != None:
libxml2mod.xmlOutputBufferClose(self._o)
self._o = None
def close(self):
self.io_close()
if self._o != None:
libxml2mod.xmlOutputBufferClose(self._o)
self._o = None
#
# Example of a class to handle SAX events
#

View File

@ -50,6 +50,23 @@
<arg name='URI' type='xmlChar *' info='The URI of the resource'/>
<arg name='encoding' type='const char *' info='encoding or None'/>
</function>
<function name='xmlCreateOutputBuffer' file='python'>
<info>Create a libxml2 output buffer from a Python file</info>
<return type='xmlOutputBufferPtr' info="the output buffer"/>
<arg name='file' type='pythonObject' info='the Python file'/>
<arg name='encoding' type='xmlChar *' info='an optionnal encoding'/>
</function>
<function name='xmlCreateInputBuffer' file='python'>
<info>Create a libxml2 input buffer from a Python file</info>
<return type='xmlParserInputBufferPtr' info="the input buffer"/>
<arg name='file' type='pythonObject' info='the Python file'/>
<arg name='encoding' type='xmlChar *' info='an optionnal encoding'/>
</function>
<function name='xmlSetEntityLoader' file='python'>
<info>Set the entity resolver as a python function</info>
<return type='int' info="0 in case of success, -1 for error"/>
<arg name='resolver' type='pythonObject' info='the Python function'/>
</function>
<!-- xmlParserCtxtPtr accessors -->
<function name='xmlParserGetDoc' file='python_accessor'>
<info>Get the document tree from a parser context.</info>

View File

@ -114,6 +114,8 @@ nodePush()
# functions from module python
SAXParseFile()
createInputBuffer()
createOutputBuffer()
createPushParser()
debugMemory()
dumpMemory()
@ -121,6 +123,7 @@ htmlCreatePushParser()
htmlSAXParseFile()
newNode()
registerErrorHandler()
setEntityLoader()
# functions from module tree
compressMode()
@ -276,10 +279,13 @@ Class xmlDoc(xmlNode)
htmlIsAutoClosed()
# functions from module HTMLtree
htmlDocContentDumpFormatOutput()
htmlDocContentDumpOutput()
htmlDocDump()
htmlGetMetaEncoding()
htmlNodeDumpFile()
htmlNodeDumpFileFormat()
htmlNodeDumpFormatOutput()
htmlSaveFile()
htmlSaveFileEnc()
htmlSaveFileFormat()
@ -323,10 +329,13 @@ Class xmlDoc(xmlNode)
newDtd()
newGlobalNs()
newReference()
nodeDumpOutput()
saveFile()
saveFileEnc()
saveFileTo()
saveFormatFile()
saveFormatFileEnc()
saveFormatFileTo()
setDocCompressMode()
stringGetNodeList()
stringLenGetNodeList()
@ -510,6 +519,15 @@ Class parserCtxt()
stringDecodeEntities()
Class outputBuffer(ioWriteWrapper)
# functions from module xmlIO
close()
flush()
write()
writeString()
Class xmlElement(xmlNode)
@ -584,3 +602,12 @@ Class xpathContext()
xpathRegisteredVariablesCleanup()
xpathVariableLookup()
xpathVariableLookupNS()
Class inputBuffer(ioReadWrapper)
# functions from module xmlIO
freeParserInputBuffer()
grow()
push()
read()

View File

@ -58,6 +58,22 @@ typedef struct {
#define PyURI_Get(v) (((v) == Py_None) ? NULL : \
(((PyURI_Object *)(v))->obj))
typedef struct {
PyObject_HEAD
xmlOutputBufferPtr obj;
} PyoutputBuffer_Object;
#define PyoutputBuffer_Get(v) (((v) == Py_None) ? NULL : \
(((PyURI_Object *)(v))->obj))
typedef struct {
PyObject_HEAD
xmlParserInputBufferPtr obj;
} PyinputBuffer_Object;
#define PyinputBuffer_Get(v) (((v) == Py_None) ? NULL : \
(((PyURI_Object *)(v))->obj))
typedef struct {
PyObject_HEAD
xmlURIPtr obj;
@ -89,5 +105,7 @@ PyObject * libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt);
PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj);
PyObject * libxml_xmlCatalogPtrWrap(xmlCatalogPtr obj);
PyObject * libxml_xmlURIPtrWrap(xmlURIPtr uri);
PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer);
PyObject * libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer);
xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);

View File

@ -15,7 +15,10 @@ PYTESTS= \
tstURI.py \
cutnpaste.py\
xpathret.py \
xpath.py
xpath.py \
outbuf.py \
inbuf.py \
resolver.py
XMLS= \
tst.xml \

25
python/tests/inbuf.py Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/python -u
import sys
import libxml2
import StringIO
# Memory debug specific
libxml2.debugMemory(1)
i = 0
while i < 5000:
f = StringIO.StringIO("foobar")
buf = libxml2.inputBuffer(f)
i = i + 1
del f
del buf
# Memory debug specific
libxml2.cleanupParser()
if libxml2.debugMemory(1) == 0:
print "OK"
else:
print "Memory leak %d bytes" % (libxml2.debugMemory(1))
libxml2.dumpMemory()

33
python/tests/outbuf.py Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/python -u
import sys
import libxml2
import StringIO
print "Skipped"
sys.exit(1)
# Memory debug specific
libxml2.debugMemory(1)
#f = open('res', 'w')
f = StringIO.StringIO()
buf = libxml2.createOutputBuffer(f, "ISO-8859-1")
buf.write(3, "foo")
buf.writeString("bar")
buf.close()
del buf
if f.getvalue() != "foobar":
print "Failed to save to StringIO"
sys.exit(1)
del f
# 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

@ -49,7 +49,8 @@ chunk = "ar</foo>"
ctxt.htmlParseChunk(chunk, len(chunk), 1)
ctxt=None
reference = "startDocument:startElement foo {'url': 'tst'}:characters: bar:endElement foo:endDocument:"
reference = """startDocument:startElement html None:startElement body None:startElement foo {'url': 'tst'}:error: Tag foo invalid
:characters: bar:endElement foo:endElement body:endElement html:endDocument:"""
if log != reference:
print "Error got: %s" % log
print "Exprected: %s" % reference

39
python/tests/resolver.py Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/python -u
import sys
import libxml2
import StringIO
# Memory debug specific
libxml2.debugMemory(1)
def myResolver(URL, ID, ctxt):
return(StringIO.StringIO("<foo/>"))
libxml2.setEntityLoader(myResolver)
doc = libxml2.parseFile("doesnotexist.xml")
root = doc.children
if root.name != "foo":
print "root element name error"
sys.exit(1)
doc.freeDoc()
i = 0
while i < 5000:
doc = libxml2.parseFile("doesnotexist.xml")
root = doc.children
if root.name != "foo":
print "root element name error"
sys.exit(1)
doc.freeDoc()
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

@ -76,7 +76,7 @@ if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http
sys.exit(1)
str = doc.serialize("ISO-8859-1")
if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>Hello</title></head><body><p>hello</p></body></html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Hello</title></head><body><p>hello</p></body></html>
""":
print "error serializing HTML document 2"
sys.exit(1)
@ -84,7 +84,7 @@ str = doc.serialize(format=1)
if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello</title>
</head>
<body><p>hello</p></body>
@ -96,7 +96,7 @@ str = doc.serialize("iso-8859-1", 1)
if str != """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Hello</title>
</head>
<body><p>hello</p></body>
@ -115,13 +115,13 @@ if str != """<html><head><title>Hello</title></head><body><p>hello</p></body></h
print "error serializing HTML root 1"
sys.exit(1)
str = root.serialize("ISO-8859-1")
if str != """<html><head><meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type"><title>Hello</title></head><body><p>hello</p></body></html>""":
if str != """<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Hello</title></head><body><p>hello</p></body></html>""":
print "error serializing HTML root 2"
sys.exit(1)
str = root.serialize(format=1)
if str != """<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello</title>
</head>
<body><p>hello</p></body>
@ -131,7 +131,7 @@ if str != """<html>
str = root.serialize("iso-8859-1", 1)
if str != """<html>
<head>
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Hello</title>
</head>
<body><p>hello</p></body>

View File

@ -469,3 +469,39 @@ libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal)
(char *) "xmlCatalogPtr", NULL);
return (ret);
}
PyObject *
libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer)
{
PyObject *ret;
#ifdef DEBUG
printf("libxml_xmlOutputBufferPtrWrap: buffer = %p\n", buffer);
#endif
if (buffer == NULL) {
Py_INCREF(Py_None);
return (Py_None);
}
ret =
PyCObject_FromVoidPtrAndDesc((void *) buffer,
(char *) "xmlOutputBufferPtr", NULL);
return (ret);
}
PyObject *
libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer)
{
PyObject *ret;
#ifdef DEBUG
printf("libxml_xmlParserInputBufferPtrWrap: buffer = %p\n", buffer);
#endif
if (buffer == NULL) {
Py_INCREF(Py_None);
return (Py_None);
}
ret =
PyCObject_FromVoidPtrAndDesc((void *) buffer,
(char *) "xmlParserInputBufferPtr", NULL);
return (ret);
}