diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | python/Makefile.am | 12 | ||||
-rwxr-xr-x | python/generator.py | 63 | ||||
-rw-r--r-- | python/libxml.c | 432 | ||||
-rw-r--r-- | python/libxml.py | 8 | ||||
-rw-r--r-- | python/libxml2-python-api.xml | 13 | ||||
-rw-r--r-- | python/libxml2class.txt | 75 | ||||
-rw-r--r-- | python/libxml_wrap.h | 9 | ||||
-rw-r--r-- | python/tests/Makefile.am | 4 | ||||
-rwxr-xr-x | python/tests/push.py | 25 | ||||
-rw-r--r-- | python/types.c | 297 |
11 files changed, 527 insertions, 422 deletions
@@ -1,3 +1,14 @@ +Sun Feb 3 16:03:55 CET 2002 Daniel Veillard <daniel@veillard.com> + + * python/Makefile.am python/types.c: cleanup + * python/libxml.c python/libxml.py python/libxml_wrap.h + python/generator.py python/libxml2-python-api.xml + python/libxml2class.txt: added class for parser context, added + first cut for push mode support. Added a framework to generate + accessors functions. + * python/tests/Makefile.am python/tests/push.py: added a push + test + Sun Feb 3 00:17:26 CET 2002 Daniel Veillard <daniel@veillard.com> * python/Makefile.am python/TODO python/libxml.py: fixed a small diff --git a/python/Makefile.am b/python/Makefile.am index a76492af..7d02f53f 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -10,6 +10,7 @@ DOCS = TODO libxml2class.txt EXTRA_DIST = \ libxml.c \ + types.c \ generator.py \ libxml_wrap.h \ libxml.py \ @@ -22,8 +23,8 @@ all: _libxml.so 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 +_libxml.so: libxml.o libxml2-py.o types.o + $(CC) $(LINK_FLAGS) libxml.o libxml2-py.o types.o $(LIBS) -o _libxml.so else all: endif @@ -31,6 +32,9 @@ endif libxml.o: libxml.c libxml2-export.c libxml_wrap.h $(CC) $(SHCFLAGS) -c -o libxml.o $(srcdir)/libxml.c +types.o: types.c libxml_wrap.h + $(CC) $(SHCFLAGS) -c -o types.o $(srcdir)/types.c + libxml2-py.o: libxml2-py.c libxml2-py.h libxml_wrap.h $(CC) $(SHCFLAGS) -c -o libxml2-py.o $(srcdir)/libxml2-py.c @@ -44,9 +48,7 @@ GENERATED= $(srcdir)/libxml2class.py \ $(GENERATED): $(srcdir)/$(GENERATE) $(API_DESC) cd $(srcdir) && $(PYTHON) $(GENERATE) -dummy: - -tests: dummy +tests: all cd tests && $(MAKE) tests clean: diff --git a/python/generator.py b/python/generator.py index 80dca7bb..587528ae 100755 --- a/python/generator.py +++ b/python/generator.py @@ -129,10 +129,13 @@ class docParser: if self.in_function == 1: self.function_return_type = None self.function_return_info = None + self.function_return_field = None if attrs.has_key('type'): self.function_return_type = attrs['type'] if attrs.has_key('info'): self.function_return_info = attrs['info'] + if attrs.has_key('field'): + self.function_return_field = attrs['field'] def end(self, tag): @@ -152,7 +155,8 @@ class docParser: elif tag == 'return': if self.in_function == 1: self.function_return = [self.function_return_type, - self.function_return_info] + self.function_return_info, + self.function_return_field] elif tag == 'info': str = '' for c in self._data: @@ -186,8 +190,6 @@ skipped_types = { 'int *': "usually a return type", 'xmlSAXHandlerPtr': "not the proper interface for SAX", 'htmlSAXHandlerPtr': "not the proper interface for SAX", - 'xmlParserCtxtPtr': "not the proper interface for the parser", - 'htmlParserCtxtPtr': "not the proper interface for the parser", 'xmlRMutexPtr': "thread specific, skipped", 'xmlMutexPtr': "thread specific, skipped", 'xmlGlobalStatePtr': "thread specific, skipped", @@ -257,6 +259,10 @@ py_types = { 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"), 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"), + 'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), + 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), + 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), + 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), } py_return_types = { @@ -340,7 +346,10 @@ def print_function_wrapper(name, output, export, include): elif py_types.has_key(ret[0]): (f, t, n, c) = py_types[ret[0]] c_return = " %s c_retval;\n" % (ret[0]) - c_call = "\n c_retval = %s(%s);\n" % (name, c_call); + if file == "python_accessor": + c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2]) + else: + c_call = "\n c_retval = %s(%s);\n" % (name, c_call); ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c) ret_convert = ret_convert + " return(py_retval);\n" elif py_return_types.has_key(ret[0]): @@ -476,6 +485,8 @@ classes_type = { "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"), + "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), + "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), } converter_type = { @@ -496,6 +507,7 @@ classes_ancestor = { } classes_destructors = { "xpathContext": "xmlXPathFreeContext", + "parserCtxt": "xmlFreeParserCtxt", } function_classes = {} @@ -530,13 +542,16 @@ for type in classes_type.keys(): ctypes.append(type) ctypes_processed[type] = () -def nameFixup(function, classe, type): +def nameFixup(function, classe, type, file): listname = classe + "List" ll = len(listname) l = len(classe) if name[0:l] == listname: func = name[l:] func = string.lower(func[0:1]) + func[1:] + elif name[0:12] == "xmlParserGet" and file == "python_accessor": + func = name[12:] + func = string.lower(func[0:1]) + func[1:] elif name[0:l] == classe: func = name[l:] func = string.lower(func[0:1]) + func[1:] @@ -573,22 +588,22 @@ for name in functions.keys(): if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type: found = 1 - func = nameFixup(name, classe, type) + func = nameFixup(name, classe, type, file) info = (0, func, name, ret, args, file) function_classes[classe].append(info) elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type: found = 1 - func = nameFixup(name, classe, type) + func = nameFixup(name, classe, type, file) info = (1, func, name, ret, args, file) function_classes[classe].append(info) elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type: found = 1 - func = nameFixup(name, classe, type) + func = nameFixup(name, classe, type, file) info = (0, func, name, ret, args, file) function_classes[classe].append(info) elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type: found = 1 - func = nameFixup(name, classe, type) + func = nameFixup(name, classe, type, file) info = (1, func, name, ret, args, file) function_classes[classe].append(info) if found == 1: @@ -601,7 +616,7 @@ for name in functions.keys(): continue if name[0:10] == "xmlCharStr": continue - func = nameFixup(name, "None", file) + func = nameFixup(name, "None", file, file) info = (0, func, name, ret, args, file) function_classes['None'].append(info) @@ -612,6 +627,10 @@ txt.write(" Generated Classes for libxml2-python\n\n") def functionCompare(info1, info2): (index1, func1, name1, ret1, args1, file1) = info1 (index2, func2, name2, ret2, args2, file2) = info2 + if file1 == "python_accessor": + return -1 + if file2 == "python_accessor": + return 1 if file1 < file2: return -1 if file1 > file2: @@ -701,6 +720,12 @@ for classname in classes_list: classes.write(" self._o = None\n") classes.write(" %s.__init__(self, _obj=_obj)\n\n" % ( classes_ancestor[classname])) + if classes_ancestor[classname] == "xmlCore" or \ + classes_ancestor[classname] == "xmlNode": + classes.write(" def __repr__(self):\n") + format = "%s:%%s" % (classname) + classes.write(" return \"%s\" %% (self.name)\n\n" % ( + format)) else: txt.write("Class %s()\n" % (classname)) classes.write("class %s:\n" % (classname)) @@ -713,21 +738,21 @@ for classname in classes_list: classes.write(" _libxml.%s(self._o)\n" % classes_destructors[classname]); classes.write(" self._o = None\n\n"); - classes.write(" def __repr__(self):\n") - format = "%s:%%s" % (classname) - classes.write(" return \"%s\" %% (self.name)\n\n" % ( - format)) flist = function_classes[classname] flist.sort(functionCompare) oldfile = "" for info in flist: (index, func, name, ret, args, file) = info if file != oldfile: - 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") + if file == "python_accessor": + classes.write(" # accessors for %s\n" % (classname)) + txt.write(" # accessors\n") + else: + 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); diff --git a/python/libxml.c b/python/libxml.c index cca2b049..57e370f0 100644 --- a/python/libxml.c +++ b/python/libxml.c @@ -1,5 +1,14 @@ +/* + * libxml.c: this modules implements the main part of the glue of the + * libxml2 library and the Python interpreter. It provides the + * entry points where an automatically generated stub is either + * unpractical or would not match cleanly the Python model. + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ #include <Python.h> - #include <libxml/xmlmemory.h> #include <libxml/parser.h> #include <libxml/tree.h> @@ -15,277 +24,48 @@ /************************************************************************ * * - * Per type specific glue * + * Handling SAX/xmllib/sgmlop callback interfaces * * * ************************************************************************/ -PyObject * -libxml_intWrap(int val) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_intWrap: val = %d\n", val); -#endif - ret = PyInt_FromLong((long) val); - return(ret); -} - -PyObject * -libxml_doubleWrap(double val) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_doubleWrap: val = %f\n", val); -#endif - ret = PyFloat_FromDouble((double) val); - return(ret); -} - -PyObject * -libxml_charPtrWrap(char *str) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlcharPtrWrap: str = %s\n", str); -#endif - if (str == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - /* TODO: look at deallocation */ - ret = PyString_FromString(str); - xmlFree(str); - return(ret); -} - -PyObject * -libxml_xmlCharPtrWrap(xmlChar *str) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlCharPtrWrap: str = %s\n", str); -#endif - if (str == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - /* TODO: look at deallocation */ - ret = PyString_FromString(str); - xmlFree(str); - return(ret); -} - -PyObject * -libxml_constcharPtrWrap(const char *str) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlcharPtrWrap: str = %s\n", str); -#endif - if (str == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - /* TODO: look at deallocation */ - ret = PyString_FromString(str); - return(ret); -} -PyObject * -libxml_constxmlCharPtrWrap(const xmlChar *str) { - PyObject *ret; +typedef struct pySAXhandler { + PyObject *startDocument; + /* TODO !!! */ +} pySAXhandler, *pySAXhandlerPtr; -#ifdef DEBUG - printf("libxml_xmlCharPtrWrap: str = %s\n", str); -#endif - if (str == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - /* TODO: look at deallocation */ - ret = PyString_FromString(str); - return(ret); -} - -PyObject * -libxml_xmlDocPtrWrap(xmlDocPtr doc) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlDocPtrWrap: doc = %p\n", doc); -#endif - if (doc == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - /* TODO: look at deallocation */ - ret = PyCObject_FromVoidPtrAndDesc((void *) doc, "xmlDocPtr", NULL); - return(ret); -} - -PyObject * -libxml_xmlNodePtrWrap(xmlNodePtr node) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlNodePtrWrap: node = %p\n", node); -#endif - if (node == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - ret = PyCObject_FromVoidPtrAndDesc((void *) node, "xmlNodePtr", NULL); - return(ret); -} - -PyObject * -libxml_xmlNsPtrWrap(xmlNsPtr ns) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlNsPtrWrap: node = %p\n", ns); -#endif - if (ns == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - ret = PyCObject_FromVoidPtrAndDesc((void *) ns, "xmlNsPtr", NULL); - return(ret); -} - -PyObject * -libxml_xmlAttrPtrWrap(xmlAttrPtr attr) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlAttrNodePtrWrap: attr = %p\n", attr); -#endif - if (attr == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttrPtr", NULL); - return(ret); -} - -PyObject * -libxml_xmlAttributePtrWrap(xmlAttributePtr attr) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlAttributePtrWrap: attr = %p\n", attr); -#endif - if (attr == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttributePtr", NULL); - return(ret); -} - -PyObject * -libxml_xmlElementPtrWrap(xmlElementPtr elem) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlElementNodePtrWrap: elem = %p\n", elem); -#endif - if (elem == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - ret = PyCObject_FromVoidPtrAndDesc((void *) elem, "xmlElementPtr", NULL); - return(ret); -} - -PyObject * -libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt) { - PyObject *ret; - -#ifdef DEBUG - printf("libxml_xmlXPathContextPtrWrap: ctxt = %p\n", ctxt); -#endif - if (ctxt == NULL) { - Py_INCREF(Py_None); - return(Py_None); - } - ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, "xmlXPathContextPtr", - NULL); - return(ret); -} +/************************************************************************ + * * + * Handling of specific parser context * + * * + ************************************************************************/ PyObject * -libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj) { - PyObject *ret; +libxml_xmlCreatePushParser(PyObject *self, PyObject *args) { + xmlChar *chunk; + int size; + xmlChar *URI; + PyObject *pyobj_SAX; + xmlSAXHandlerPtr SAX = NULL; + pySAXhandlerPtr SAXdata = NULL; + xmlParserCtxtPtr ret; + PyObject *pyret; + + if (!PyArg_ParseTuple(args, "Oziz:xmlCreatePushParser", &pyobj_SAX, + &chunk, &size, &URI)) + return(NULL); -#ifdef DEBUG - printf("libxml_xmlXPathObjectPtrWrap: ctxt = %p\n", obj); +#ifdef DEBUG_ERROR + printf("libxml_xmlCreatePushParser(%p, %s, %d, %s) called\n", + pyobj_SAX, chunk, size, URI); #endif - if (obj == NULL) { + if (pyobj_SAX != Py_None) { + printf("xmlCreatePushParser: event interface not supported yet !\n"); Py_INCREF(Py_None); return(Py_None); } - switch(obj->type) { - case XPATH_XSLT_TREE: - /* TODO !!!! Allocation problems */ - case XPATH_NODESET: - if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) - ret = PyList_New(0); - else { - int i; - xmlNodePtr node; - - ret = PyList_New(obj->nodesetval->nodeNr); - for (i = 0;i < obj->nodesetval->nodeNr;i++) { - node = obj->nodesetval->nodeTab[i]; - /* TODO: try to cast directly to the proper node type */ - PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node)); - } - } - break; - case XPATH_BOOLEAN: - ret = PyInt_FromLong((long) obj->boolval); - break; - case XPATH_NUMBER: - ret = PyFloat_FromDouble(obj->floatval); - break; - case XPATH_STRING: - ret = PyString_FromString(obj->stringval); - break; - case XPATH_POINT: - case XPATH_RANGE: - case XPATH_LOCATIONSET: - default: - printf("Unable to convert XPath object type %d\n", obj->type); - Py_INCREF(Py_None); - ret = Py_None; - } - xmlXPathFreeObject(obj); - return(ret); -} - -xmlXPathObjectPtr -libxml_xmlXPathObjectPtrConvert(PyObject * obj) { - xmlXPathObjectPtr ret; - -#ifdef DEBUG - printf("libxml_xmlXPathObjectPtrConvert: obj = %p\n", obj); -#endif - if (obj == NULL) { - return(NULL); - } - if PyFloat_Check(obj) { - ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj)); - } else if PyString_Check(obj) { - xmlChar *str; - - str = xmlStrndup((const xmlChar *)PyString_AS_STRING(obj), - PyString_GET_SIZE(obj)); - ret = xmlXPathWrapString(str); - } else { - printf("Unable to convert Python Object to XPath"); - } - Py_DECREF(obj); - return(ret); + ret = xmlCreatePushParserCtxt(SAX, SAXdata, chunk, size, URI); + pyret = libxml_xmlParserCtxtPtrWrap(ret); + return(pyret); } /************************************************************************ @@ -534,131 +314,6 @@ done: /************************************************************************ * * - * The PyxmlNode type * - * * - ************************************************************************/ -static void -PyxmlNode_dealloc(PyxmlNode_Object * self) -{ - printf("TODO PyxmlNode_dealloc\n"); - PyMem_DEL(self); -} - -static int -PyxmlNode_compare(PyxmlNode_Object * self, PyxmlNode_Object * v) -{ - if (self->obj == v->obj) - return 0; - if (self->obj > v->obj) - return -1; - return 1; -} - -static long -PyxmlNode_hash(PyxmlNode_Object * self) -{ - return (long) self->obj; -} - -static PyObject * -PyxmlNode_repr(PyxmlNode_Object * self) -{ - char buf[100]; - - sprintf(buf, "<xmlNode of type %d at %lx>", - PyxmlNode_Get(self)->type, - (long) PyxmlNode_Get(self)); - return PyString_FromString(buf); -} - -static char PyxmlNode_Type__doc__[] = "This is the type of libxml Nodes"; - -static PyTypeObject PyxmlNode_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size */ - "xmlNode", /*tp_name */ - sizeof(PyxmlNode_Object), /*tp_basicsize */ - 0, /*tp_itemsize */ - (destructor) PyxmlNode_dealloc,/*tp_dealloc */ - (printfunc) 0, /*tp_print */ - (getattrfunc) 0, /*tp_getattr */ - (setattrfunc) 0, /*tp_setattr */ - (cmpfunc) PyxmlNode_compare,/*tp_compare */ - (reprfunc) PyxmlNode_repr, /*tp_repr */ - 0, /*tp_as_number */ - 0, /*tp_as_sequence */ - 0, /*tp_as_mapping */ - (hashfunc) PyxmlNode_hash, /*tp_hash */ - (ternaryfunc) 0, /*tp_call */ - (reprfunc) 0, /*tp_str */ - 0L, 0L, 0L, 0L, - PyxmlNode_Type__doc__ -}; - -/************************************************************************ - * * - * The PyxmlXPathContext type * - * * - ************************************************************************/ -static void -PyxmlXPathContext_dealloc(PyxmlXPathContext_Object * self) -{ - printf("TODO PyxmlXPathContext_dealloc\n"); - PyMem_DEL(self); -} - -static int -PyxmlXPathContext_compare(PyxmlXPathContext_Object * self, PyxmlXPathContext_Object * v) -{ - if (self->obj == v->obj) - return 0; - if (self->obj > v->obj) - return -1; - return 1; -} - -static long -PyxmlXPathContext_hash(PyxmlXPathContext_Object * self) -{ - return (long) self->obj; -} - -static PyObject * -PyxmlXPathContext_repr(PyxmlXPathContext_Object * self) -{ - char buf[100]; - - sprintf(buf, "<xmlXPathContext at %lx>", - (long) PyxmlXPathContext_Get(self)); - return PyString_FromString(buf); -} - -static char PyxmlXPathContext_Type__doc__[] = "This is the type of XPath evaluation contexts"; - -PyTypeObject PyxmlXPathContext_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size */ - "xmlXPathContext", /*tp_name */ - sizeof(PyxmlXPathContext_Object), /*tp_basicsize */ - 0, /*tp_itemsize */ - (destructor) PyxmlXPathContext_dealloc,/*tp_dealloc */ - (printfunc) 0, /*tp_print */ - (getattrfunc) 0, /*tp_getattr */ - (setattrfunc) 0, /*tp_setattr */ - (cmpfunc) PyxmlXPathContext_compare,/*tp_compare */ - (reprfunc) PyxmlXPathContext_repr, /*tp_repr */ - 0, /*tp_as_number */ - 0, /*tp_as_sequence */ - 0, /*tp_as_mapping */ - (hashfunc) PyxmlXPathContext_hash, /*tp_hash */ - (ternaryfunc) 0, /*tp_call */ - (reprfunc) 0, /*tp_str */ - 0L, 0L, 0L, 0L, - PyxmlXPathContext_Type__doc__ -}; - -/************************************************************************ - * * * Global properties access * * * ************************************************************************/ @@ -1055,11 +710,8 @@ static PyMethodDef libxmlMethods[] = { }; void init_libxml(void) { - PyObject *m, *d; + PyObject *m; m = Py_InitModule("_libxml", libxmlMethods); - d = PyModule_GetDict(m); - PyDict_SetItemString(d, "xmlNodeType", (PyObject *)&PyxmlNode_Type); - PyDict_SetItemString(d, "xmlXPathContextType", (PyObject *)&PyxmlXPathContext_Type); libxml_xmlErrorInitialize(); } diff --git a/python/libxml.py b/python/libxml.py index 6f5197b2..22749f8b 100644 --- a/python/libxml.py +++ b/python/libxml.py @@ -148,14 +148,6 @@ def registerXPathFunction(ctxt, name, ns_uri, f): ret = _libxml.xmlRegisterXPathFunction(ctxt, name, ns_uri, f) # -# A parser context -# -class parserCtxt: - def __init__(self, _obj=None): - self._o = _obj - - -# # Everything below this point is automatically generated # diff --git a/python/libxml2-python-api.xml b/python/libxml2-python-api.xml index 5cdc9920..ec76f6ed 100644 --- a/python/libxml2-python-api.xml +++ b/python/libxml2-python-api.xml @@ -20,5 +20,18 @@ <arg name='f' type='pythonObject' info='the python function'/> <arg name='ctx' type='pythonObject' info='a context for the callback'/> </function> + <function name='xmlCreatePushParser' file='python'> + <info>Create a progressive parser context to build either an event flow if the SAX object is not None, or a DOM tree otherwise.</info> + <return type='xmlParserCtxtPtr' info="the parser context or None in case of error"/> + <arg name='SAX' type='pythonObject' info='the SAX callback object or None'/> + <arg name='chunk' type='xmlChar *' info='the initial data'/> + <arg name='size' type='int' info='the size of the initial data'/> + <arg name='URI' type='xmlChar *' info='The URI used for base computations'/> + </function> + <function name='xmlParserGetDoc' file='python_accessor'> + <info>Get the document tree from a parser context.</info> + <return type='xmlDocPtr' info="the document tree" field="myDoc"/> + <arg name='ctxt' type='xmlParserCtxtPtr' info='the SAX callback object or None'/> + </function> </symbols> </api> diff --git a/python/libxml2class.txt b/python/libxml2class.txt index 0411124d..d952c2c5 100644 --- a/python/libxml2class.txt +++ b/python/libxml2class.txt @@ -6,9 +6,13 @@ # functions from module HTMLparser +htmlFreeParserCtxt() htmlHandleOmittedElem() htmlIsScriptAttribute() +htmlParseCharRef() +htmlParseChunk() htmlParseDoc() +htmlParseElement() htmlParseFile() # functions from module HTMLtree @@ -68,6 +72,7 @@ nanoHTTPScanProxy() # functions from module parser cleanupParser() +createDocParserCtxt() defaultSAXHandlerInit() htmlDefaultSAXHandlerInit() initParser() @@ -88,6 +93,10 @@ substituteEntitiesDefault() checkLanguageID() copyChar() copyCharMultiByte() +createEntityParserCtxt() +createFileParserCtxt() +createMemoryParserCtxt() +htmlCreateFileParserCtxt() htmlInitAutoClose() isBaseChar() isBlank() @@ -98,8 +107,14 @@ isExtender() isIdeographic() isLetter() isPubidChar() +namePop() +namePush() +newParserCtxt() +nodePop() +nodePush() # functions from module python +createPushParser() registerErrorHandler() # functions from module tree @@ -315,6 +330,66 @@ Class xmlDtd(xmlNode) Class xmlElement(xmlNode) +Class parserCtxt() + # accessors + doc() + + # functions from module parser + clearParserCtxt() + initParserCtxt() + parseChunk() + parseDocument() + parseExtParsedEnt() + stopParser() + + # functions from module parserInternals + decodeEntities() + freeParserCtxt() + handleEntity() + namespaceParseNCName() + namespaceParseNSDef() + nextChar() + parseAttValue() + parseAttributeListDecl() + parseCDSect() + parseCharData() + parseCharRef() + parseComment() + parseContent() + parseDocTypeDecl() + parseElement() + parseElementDecl() + parseEncName() + parseEncodingDecl() + parseEndTag() + parseEntityDecl() + parseEntityRef() + parseExternalSubset() + parseMarkupDecl() + parseMisc() + parseName() + parseNamespace() + parseNmtoken() + parseNotationDecl() + parsePEReference() + parsePI() + parsePITarget() + parsePubidLiteral() + parseQuotedString() + parseReference() + parseSDDecl() + parseStartTag() + parseSystemLiteral() + parseTextDecl() + parseVersionInfo() + parseVersionNum() + parseXMLDecl() + parserHandlePEReference() + parserHandleReference() + popInput() + scanName() + skipBlankChars() + stringDecodeEntities() Class xpathContext() # functions from module python diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h index 972e871e..d6d89aa4 100644 --- a/python/libxml_wrap.h +++ b/python/libxml_wrap.h @@ -1,3 +1,4 @@ +#include <Python.h> #include <libxml/tree.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> @@ -27,6 +28,12 @@ typedef struct { xmlXPathContextPtr obj; } PyxmlXPathContext_Object; +#define PyparserCtxt_Get(v) (((PyparserCtxt_Object *)(v))->obj) +typedef struct { + PyObject_HEAD + xmlParserCtxtPtr obj; +} PyparserCtxt_Object; + PyObject * libxml_intWrap(int val); PyObject * libxml_xmlCharPtrWrap(xmlChar *str); PyObject * libxml_constxmlCharPtrWrap(const xmlChar *str); @@ -40,5 +47,7 @@ PyObject * libxml_xmlAttributePtrWrap(xmlAttributePtr ns); PyObject * libxml_xmlElementPtrWrap(xmlElementPtr ns); PyObject * libxml_doubleWrap(double val); PyObject * libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt); +PyObject * libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt); PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj); +xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj); diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am index 79d54561..b8e9cec8 100644 --- a/python/tests/Makefile.am +++ b/python/tests/Makefile.am @@ -4,6 +4,7 @@ TESTS= \ tst.py \ tstxpath.py \ xpathext.py \ + push.py \ error.py \ xpath.py @@ -20,6 +21,9 @@ else tests: endif +clean: + rm -f *.pyc core + install-data-local: $(mkinstalldirs) $(DESTDIR)$(EXAMPLE_DIR) -(for test in $(TESTS) $(XMLS); \ diff --git a/python/tests/push.py b/python/tests/push.py new file mode 100755 index 00000000..738d3e95 --- /dev/null +++ b/python/tests/push.py @@ -0,0 +1,25 @@ +#!/usr/bin/python -u +import sys +import libxml2 + +ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml") +ctxt.parseChunk("/>", 2, 1) +doc = ctxt.doc() +ctxt=None +if doc.name != "test.xml": + print "document name error" + sys.exit(1) +root = doc.children +if root.name != "foo": + print "root element name error" + sys.exit(1) +doc.freeDoc() +i = 10000 +while i > 0: + ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml") + ctxt.parseChunk("/>", 2, 1) + doc = ctxt.doc() + doc.freeDoc() + i = i -1 +ctxt=None +print "OK" diff --git a/python/types.c b/python/types.c new file mode 100644 index 00000000..07a178eb --- /dev/null +++ b/python/types.c @@ -0,0 +1,297 @@ +/* + * types.c: converter functions between the internal representation + * and the Python objects + * + * See Copyright for the status of this software. + * + * daniel@veillard.com + */ +#include "libxml_wrap.h" + +PyObject * +libxml_intWrap(int val) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_intWrap: val = %d\n", val); +#endif + ret = PyInt_FromLong((long) val); + return(ret); +} + +PyObject * +libxml_doubleWrap(double val) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_doubleWrap: val = %f\n", val); +#endif + ret = PyFloat_FromDouble((double) val); + return(ret); +} + +PyObject * +libxml_charPtrWrap(char *str) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlcharPtrWrap: str = %s\n", str); +#endif + if (str == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + /* TODO: look at deallocation */ + ret = PyString_FromString(str); + xmlFree(str); + return(ret); +} + +PyObject * +libxml_xmlCharPtrWrap(xmlChar *str) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlCharPtrWrap: str = %s\n", str); +#endif + if (str == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + /* TODO: look at deallocation */ + ret = PyString_FromString(str); + xmlFree(str); + return(ret); +} + +PyObject * +libxml_constcharPtrWrap(const char *str) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlcharPtrWrap: str = %s\n", str); +#endif + if (str == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + /* TODO: look at deallocation */ + ret = PyString_FromString(str); + return(ret); +} + +PyObject * +libxml_constxmlCharPtrWrap(const xmlChar *str) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlCharPtrWrap: str = %s\n", str); +#endif + if (str == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + /* TODO: look at deallocation */ + ret = PyString_FromString(str); + return(ret); +} + +PyObject * +libxml_xmlDocPtrWrap(xmlDocPtr doc) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlDocPtrWrap: doc = %p\n", doc); +#endif + if (doc == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + /* TODO: look at deallocation */ + ret = PyCObject_FromVoidPtrAndDesc((void *) doc, "xmlDocPtr", NULL); + return(ret); +} + +PyObject * +libxml_xmlNodePtrWrap(xmlNodePtr node) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlNodePtrWrap: node = %p\n", node); +#endif + if (node == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) node, "xmlNodePtr", NULL); + return(ret); +} + +PyObject * +libxml_xmlNsPtrWrap(xmlNsPtr ns) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlNsPtrWrap: node = %p\n", ns); +#endif + if (ns == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) ns, "xmlNsPtr", NULL); + return(ret); +} + +PyObject * +libxml_xmlAttrPtrWrap(xmlAttrPtr attr) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlAttrNodePtrWrap: attr = %p\n", attr); +#endif + if (attr == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttrPtr", NULL); + return(ret); +} + +PyObject * +libxml_xmlAttributePtrWrap(xmlAttributePtr attr) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlAttributePtrWrap: attr = %p\n", attr); +#endif + if (attr == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) attr, "xmlAttributePtr", NULL); + return(ret); +} + +PyObject * +libxml_xmlElementPtrWrap(xmlElementPtr elem) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlElementNodePtrWrap: elem = %p\n", elem); +#endif + if (elem == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) elem, "xmlElementPtr", NULL); + return(ret); +} + +PyObject * +libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlXPathContextPtrWrap: ctxt = %p\n", ctxt); +#endif + if (ctxt == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, "xmlXPathContextPtr", + NULL); + return(ret); +} + +PyObject * +libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlParserCtxtPtrWrap: ctxt = %p\n", ctxt); +#endif + if (ctxt == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + ret = PyCObject_FromVoidPtrAndDesc((void *) ctxt, "xmlParserCtxtPtr", + NULL); + return(ret); +} + +PyObject * +libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj) { + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlXPathObjectPtrWrap: ctxt = %p\n", obj); +#endif + if (obj == NULL) { + Py_INCREF(Py_None); + return(Py_None); + } + switch(obj->type) { + case XPATH_XSLT_TREE: + /* TODO !!!! Allocation problems */ + case XPATH_NODESET: + if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) + ret = PyList_New(0); + else { + int i; + xmlNodePtr node; + + ret = PyList_New(obj->nodesetval->nodeNr); + for (i = 0;i < obj->nodesetval->nodeNr;i++) { + node = obj->nodesetval->nodeTab[i]; + /* TODO: try to cast directly to the proper node type */ + PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node)); + } + } + break; + case XPATH_BOOLEAN: + ret = PyInt_FromLong((long) obj->boolval); + break; + case XPATH_NUMBER: + ret = PyFloat_FromDouble(obj->floatval); + break; + case XPATH_STRING: + ret = PyString_FromString(obj->stringval); + break; + case XPATH_POINT: + case XPATH_RANGE: + case XPATH_LOCATIONSET: + default: + printf("Unable to convert XPath object type %d\n", obj->type); + Py_INCREF(Py_None); + ret = Py_None; + } + xmlXPathFreeObject(obj); + return(ret); +} + +xmlXPathObjectPtr +libxml_xmlXPathObjectPtrConvert(PyObject * obj) { + xmlXPathObjectPtr ret; + +#ifdef DEBUG + printf("libxml_xmlXPathObjectPtrConvert: obj = %p\n", obj); +#endif + if (obj == NULL) { + return(NULL); + } + if PyFloat_Check(obj) { + ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj)); + } else if PyString_Check(obj) { + xmlChar *str; + + str = xmlStrndup((const xmlChar *)PyString_AS_STRING(obj), + PyString_GET_SIZE(obj)); + ret = xmlXPathWrapString(str); + } else { + printf("Unable to convert Python Object to XPath"); + } + Py_DECREF(obj); + return(ret); +} + + |