Commit 3ce5257b authored by Daniel Veillard's avatar Daniel Veillard
Browse files

cleanup added class for parser context, added first cut for push mode

* 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
Daniel
parent cfb05462
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
......
......@@ -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:
......
......@@ -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);
......
/*
* 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);
}
/************************************************************************
......@@ -532,131 +312,6 @@ done:
return(py_retval);
}
/************************************************************************
* *
* 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