source: trunk/third/libxslt/python/generator.py @ 18543

Revision 18543, 33.8 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18542, which included commits to RCS files with non-trunk default branches.
  • Property svn:executable set to *
Line 
1#!/usr/bin/python -u
2#
3# generate python wrappers from the XML API description
4#
5
6functions = {}
7
8import string
9
10#######################################################################
11#
12#  That part if purely the API acquisition phase from the
13#  XML API description
14#
15#######################################################################
16import os
17import xmllib
18try:
19    import sgmlop
20except ImportError:
21    sgmlop = None # accelerator not available
22
23debug = 0
24
25if sgmlop:
26    class FastParser:
27        """sgmlop based XML parser.  this is typically 15x faster
28           than SlowParser..."""
29
30        def __init__(self, target):
31
32            # setup callbacks
33            self.finish_starttag = target.start
34            self.finish_endtag = target.end
35            self.handle_data = target.data
36
37            # activate parser
38            self.parser = sgmlop.XMLParser()
39            self.parser.register(self)
40            self.feed = self.parser.feed
41            self.entity = {
42                "amp": "&", "gt": ">", "lt": "<",
43                "apos": "'", "quot": '"'
44                }
45
46        def close(self):
47            try:
48                self.parser.close()
49            finally:
50                self.parser = self.feed = None # nuke circular reference
51
52        def handle_entityref(self, entity):
53            # <string> entity
54            try:
55                self.handle_data(self.entity[entity])
56            except KeyError:
57                self.handle_data("&%s;" % entity)
58
59else:
60    FastParser = None
61
62
63class SlowParser(xmllib.XMLParser):
64    """slow but safe standard parser, based on the XML parser in
65       Python's standard library."""
66
67    def __init__(self, target):
68        self.unknown_starttag = target.start
69        self.handle_data = target.data
70        self.unknown_endtag = target.end
71        xmllib.XMLParser.__init__(self)
72
73def getparser(target = None):
74    # get the fastest available parser, and attach it to an
75    # unmarshalling object.  return both objects.
76    if target == None:
77        target = docParser()
78    if FastParser:
79        return FastParser(target), target
80    return SlowParser(target), target
81
82class docParser:
83    def __init__(self):
84        self._methodname = None
85        self._data = []
86        self.in_function = 0
87
88    def close(self):
89        if debug:
90            print "close"
91
92    def getmethodname(self):
93        return self._methodname
94
95    def data(self, text):
96        if debug:
97            print "data %s" % text
98        self._data.append(text)
99
100    def start(self, tag, attrs):
101        if debug:
102            print "start %s, %s" % (tag, attrs)
103        if tag == 'function':
104            self._data = []
105            self.in_function = 1
106            self.function = None
107            self.function_args = []
108            self.function_descr = None
109            self.function_return = None
110            self.function_file = None
111            if attrs.has_key('name'):
112                self.function = attrs['name']
113            if attrs.has_key('file'):
114                self.function_file = attrs['file']
115        elif tag == 'info':
116            self._data = []
117        elif tag == 'arg':
118            if self.in_function == 1:
119                self.function_arg_name = None
120                self.function_arg_type = None
121                self.function_arg_info = None
122                if attrs.has_key('name'):
123                    self.function_arg_name = attrs['name']
124                if attrs.has_key('type'):
125                    self.function_arg_type = attrs['type']
126                if attrs.has_key('info'):
127                    self.function_arg_info = attrs['info']
128        elif tag == 'return':
129            if self.in_function == 1:
130                self.function_return_type = None
131                self.function_return_info = None
132                self.function_return_field = None
133                if attrs.has_key('type'):
134                    self.function_return_type = attrs['type']
135                if attrs.has_key('info'):
136                    self.function_return_info = attrs['info']
137                if attrs.has_key('field'):
138                    self.function_return_field = attrs['field']
139
140
141    def end(self, tag):
142        if debug:
143            print "end %s" % tag
144        if tag == 'function':
145            if self.function != None:
146                function(self.function, self.function_descr,
147                         self.function_return, self.function_args,
148                         self.function_file)
149                self.in_function = 0
150        elif tag == 'arg':
151            if self.in_function == 1:
152                self.function_args.append([self.function_arg_name,
153                                           self.function_arg_type,
154                                           self.function_arg_info])
155        elif tag == 'return':
156            if self.in_function == 1:
157                self.function_return = [self.function_return_type,
158                                        self.function_return_info,
159                                        self.function_return_field]
160        elif tag == 'info':
161            str = ''
162            for c in self._data:
163                str = str + c
164            if self.in_function == 1:
165                self.function_descr = str
166               
167               
168def function(name, desc, ret, args, file):
169    global functions
170
171    functions[name] = (desc, ret, args, file)
172
173#######################################################################
174#
175#  Some filtering rukes to drop functions/types which should not
176#  be exposed as-is on the Python interface
177#
178#######################################################################
179
180skipped_modules = {
181    'xmlmemory': None,
182    'DOCBparser': None,
183    'SAX': None,
184    'hash': None,
185    'list': None,
186    'threads': None,
187    'xpointer': None,
188}
189skipped_types = {
190    'int *': "usually a return type",
191    'xmlSAXHandlerPtr': "not the proper interface for SAX",
192    'htmlSAXHandlerPtr': "not the proper interface for SAX",
193    'xmlRMutexPtr': "thread specific, skipped",
194    'xmlMutexPtr': "thread specific, skipped",
195    'xmlGlobalStatePtr': "thread specific, skipped",
196    'xmlListPtr': "internal representation not suitable for python",
197    'xmlBufferPtr': "internal representation not suitable for python",
198    'FILE *': None,
199}
200
201#######################################################################
202#
203#  Table of remapping to/from the python type or class to the C
204#  counterpart.
205#
206#######################################################################
207
208py_types = {
209    'void': (None, None, None, None, None),
210    'int':  ('i', None, "int", "int", "libxml_"),
211    'long':  ('i', None, "int", "int", "libxml_"),
212    'double':  ('d', None, "double", "double", "libxml_"),
213    'unsigned int':  ('i', None, "int", "int", "libxml_"),
214    'xmlChar':  ('c', None, "int", "int", "libxml_"),
215    'unsigned char *':  ('z', None, "charPtr", "char *", "libxml_"),
216    'char *':  ('z', None, "charPtr", "char *", "libxml_"),
217    'const char *':  ('z', None, "charPtrConst", "const char *", "libxml_"),
218    'xmlChar *':  ('z', None, "xmlCharPtr", "xmlChar *", "libxml_"),
219    'const xmlChar *':  ('z', None, "xmlCharPtrConst", "const xmlChar *", "libxml_"),
220    'xmlNodePtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
221    'const xmlNodePtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
222    'xmlNode *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
223    'const xmlNode *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
224    'xmlDtdPtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
225    'const xmlDtdPtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
226    'xmlDtd *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
227    'const xmlDtd *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
228    'xmlAttrPtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
229    'const xmlAttrPtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
230    'xmlAttr *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
231    'const xmlAttr *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
232    'xmlEntityPtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
233    'const xmlEntityPtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
234    'xmlEntity *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
235    'const xmlEntity *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
236    'xmlElementPtr':  ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
237    'const xmlElementPtr':  ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
238    'xmlElement *':  ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
239    'const xmlElement *':  ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr", "libxml_"),
240    'xmlAttributePtr':  ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
241    'const xmlAttributePtr':  ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
242    'xmlAttribute *':  ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
243    'const xmlAttribute *':  ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr", "libxml_"),
244    'xmlNsPtr':  ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
245    'const xmlNsPtr':  ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
246    'xmlNs *':  ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
247    'const xmlNs *':  ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr", "libxml_"),
248    'xmlDocPtr':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
249    'const xmlDocPtr':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
250    'xmlDoc *':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
251    'const xmlDoc *':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
252    'htmlDocPtr':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
253    'const htmlDocPtr':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
254    'htmlDoc *':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
255    'const htmlDoc *':  ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr", "libxml_"),
256    'htmlNodePtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
257    'const htmlNodePtr':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
258    'htmlNode *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
259    'const htmlNode *':  ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr", "libxml_"),
260    'xmlXPathContextPtr':  ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxml_"),
261    'xmlXPathParserContextPtr':  ('O', "xmlXPathParserContext", "xmlXPathParserContextPtr", "xmlXPathParserContextPtr", "libxml_"),
262    'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
263    'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
264    'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
265    'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr", "libxml_"),
266    'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"),
267    'FILE *': ('O', "File", "FILEPtr", "FILE *", "libxml_"),
268    'xsltTransformContextPtr':  ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
269    'xsltTransformContext *':  ('O', "transformCtxt", "xsltTransformContextPtr", "xsltTransformContextPtr", "libxslt_"),
270    'xsltStylesheetPtr':  ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
271    'xsltStylesheet *':  ('O', "stylesheet", "xsltStylesheetPtr", "xsltStylesheetPtr", "libxslt_"),
272    'xmlXPathContext *':  ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr", "libxslt_"),
273}
274
275py_return_types = {
276    'xmlXPathObjectPtr':  ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr", "libxml_"),
277}
278
279unknown_types = {}
280
281#######################################################################
282#
283#  This part writes the C <-> Python stubs libxslt-py.[ch] and
284#  the table libxslt-export.c to add when registrering the Python module
285#
286#######################################################################
287
288def skip_function(name):
289    if name[0:12] == "xmlXPathWrap":
290        return 1
291    if name == "xsltMatchPattern":
292        return 1
293#    if name[0:11] == "xmlXPathNew":
294#        return 1
295    return 0
296
297def print_function_wrapper(name, output, export, include):
298    global py_types
299    global unknown_types
300    global functions
301    global skipped_modules
302
303    try:
304        (desc, ret, args, file) = functions[name]
305    except:
306        print "failed to get function %s infos"
307        return
308
309    if skipped_modules.has_key(file):
310        return 0
311    if skip_function(name) == 1:
312        return 0
313
314    c_call = "";
315    format=""
316    format_args=""
317    c_args=""
318    c_return=""
319    c_convert=""
320    for arg in args:
321        # This should be correct
322        if arg[1][0:6] == "const ":
323            arg[1] = arg[1][6:]
324        c_args = c_args + "    %s %s;\n" % (arg[1], arg[0])
325        if py_types.has_key(arg[1]):
326            (f, t, n, c, p) = py_types[arg[1]]
327            if f != None:
328                format = format + f
329            if t != None:
330                format_args = format_args + ", &pyobj_%s" % (arg[0])
331                c_args = c_args + "    PyObject *pyobj_%s;\n" % (arg[0])
332                c_convert = c_convert + \
333                   "    %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
334                   arg[1], t, arg[0]);
335            else:
336                format_args = format_args + ", &%s" % (arg[0])
337            if c_call != "":
338                c_call = c_call + ", ";
339            c_call = c_call + "%s" % (arg[0])
340        else:
341            if skipped_types.has_key(arg[1]):
342                return 0
343            if unknown_types.has_key(arg[1]):
344                lst = unknown_types[arg[1]]
345                lst.append(name)
346            else:
347                unknown_types[arg[1]] = [name]
348            return -1
349    if format != "":
350        format = format + ":%s" % (name)
351
352    if ret[0] == 'void':
353        if file == "python_accessor":
354            if args[1][1] == "char *" or args[1][1] == "xmlChar *":
355                c_call = "\n    if (%s->%s != NULL) xmlFree(%s->%s);\n" % (
356                                 args[0][0], args[1][0], args[0][0], args[1][0])
357                c_call = c_call + "    %s->%s = xmlStrdup((const xmlChar *)%s);\n" % (args[0][0],
358                                 args[1][0], args[1][0])
359            else:
360                c_call = "\n    %s->%s = %s;\n" % (args[0][0], args[1][0],
361                                                   args[1][0])
362        else:
363            c_call = "\n    %s(%s);\n" % (name, c_call);
364        ret_convert = "    Py_INCREF(Py_None);\n    return(Py_None);\n"
365    elif py_types.has_key(ret[0]):
366        (f, t, n, c, p) = py_types[ret[0]]
367        c_return = "    %s c_retval;\n" % (ret[0])
368        if file == "python_accessor" and ret[2] != None:
369            c_call = "\n    c_retval = %s->%s;\n" % (args[0][0], ret[2])
370        else:
371            c_call = "\n    c_retval = %s(%s);\n" % (name, c_call);
372        ret_convert = "    py_retval = %s%sWrap((%s) c_retval);\n" % (p,n,c)
373        ret_convert = ret_convert + "    return(py_retval);\n"
374    elif py_return_types.has_key(ret[0]):
375        (f, t, n, c, p) = py_return_types[ret[0]]
376        c_return = "    %s c_retval;\n" % (ret[0])
377        if file == "python_accessor" and ret[2] != None:
378            c_call = "\n    c_retval = %s->%s;\n" % (args[0][0], ret[2])
379        else:
380            c_call = "\n    c_retval = %s(%s);\n" % (name, c_call);
381        ret_convert = "    py_retval = %s%sWrap((%s) c_retval);\n" % (p,n,c)
382        ret_convert = ret_convert + "    return(py_retval);\n"
383    else:
384        if skipped_types.has_key(ret[0]):
385            return 0
386        if unknown_types.has_key(ret[0]):
387            lst = unknown_types[ret[0]]
388            lst.append(name)
389        else:
390            unknown_types[ret[0]] = [name]
391        return -1
392
393    include.write("PyObject * ")
394    include.write("libxslt_%s(PyObject *self, PyObject *args);\n" % (name))
395
396    export.write("    { (char *)\"%s\", libxslt_%s, METH_VARARGS, NULL },\n" % (name, name))
397
398    if file == "python":
399        # Those have been manually generated
400        return 1
401    if file == "python_accessor" and ret[0] != "void" and ret[2] == None:
402        # Those have been manually generated
403        return 1
404
405    output.write("PyObject *\n")
406    output.write("libxslt_%s(ATTRIBUTE_UNUSED PyObject *self," % (name))
407    if format == "":
408        output.write("ATTRIBUTE_UNUSED ")
409    output.write(" PyObject *args) {\n")
410    if ret[0] != 'void':
411        output.write("    PyObject *py_retval;\n")
412    if c_return != "":
413        output.write(c_return)
414    if c_args != "":
415        output.write(c_args)
416    if format != "":
417        output.write("\n    if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" %
418                     (format, format_args))
419        output.write("        return(NULL);\n")
420    if c_convert != "":
421        output.write(c_convert)
422                                                             
423    output.write(c_call)
424    output.write(ret_convert)
425    output.write("}\n\n")
426    return 1
427
428def buildStubs():
429    global py_types
430    global py_return_types
431    global unknown_types
432
433    try:
434        f = open("libxslt-api.xml")
435        data = f.read()
436        (parser, target)  = getparser()
437        parser.feed(data)
438        parser.close()
439    except IOError, msg:
440        try:
441            f = open("../doc/libxslt-api.xml")
442            data = f.read()
443            (parser, target)  = getparser()
444            parser.feed(data)
445            parser.close()
446        except IOError, msg:
447            print "../doc/libxslt-api.xml", ":", msg
448
449    n = len(functions.keys())
450    print "Found %d functions in libxslt-api.xml" % (n)
451
452    py_types['pythonObject'] = ('O', "pythonObject", "pythonObject",
453                                "pythonObject", "libxml_")
454    try:
455        f = open("libxslt-python-api.xml")
456        data = f.read()
457        (parser, target)  = getparser()
458        parser.feed(data)
459        parser.close()
460    except IOError, msg:
461        print "libxslt-python-api.xml", ":", msg
462
463
464    print "Found %d functions in libxslt-python-api.xml" % (
465          len(functions.keys()) - n)
466    nb_wrap = 0
467    failed = 0
468    skipped = 0
469
470    include = open("libxslt-py.h", "w")
471    include.write("/* Generated */\n\n")
472    export = open("libxslt-export.c", "w")
473    export.write("/* Generated */\n\n")
474    wrapper = open("libxslt-py.c", "w")
475    wrapper.write("/* Generated */\n\n")
476#    wrapper.write("#include \"config.h\"\n")
477    wrapper.write("#include <libxslt/xsltconfig.h>\n")
478    wrapper.write("#include \"libxslt_wrap.h\"\n")
479    wrapper.write("#include \"libxslt-py.h\"\n\n")
480    for function in functions.keys():
481        ret = print_function_wrapper(function, wrapper, export, include)
482        if ret < 0:
483            failed = failed + 1
484            del functions[function]
485        if ret == 0:
486            skipped = skipped + 1
487            del functions[function]
488        if ret == 1:
489            nb_wrap = nb_wrap + 1
490    include.close()
491    export.close()
492    wrapper.close()
493
494    print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
495                                                              failed, skipped);
496    print "Missing type converters:"
497    for type in unknown_types.keys():
498        print "%s:%d " % (type, len(unknown_types[type])),
499    print
500
501#######################################################################
502#
503#  This part writes part of the Python front-end classes based on
504#  mapping rules between types and classes and also based on function
505#  renaming to get consistent function names at the Python level
506#
507#######################################################################
508
509#
510# The type automatically remapped to generated classes
511#
512libxml2_classes_type = {
513    "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
514    "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
515    "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
516    "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
517    "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
518    "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
519    "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
520    "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
521    "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
522    "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
523    "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
524    "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
525    "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
526    "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
527    "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
528    "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
529    "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
530    "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
531    "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
532    "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
533    "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"),
534}
535
536classes_type = {
537    "xsltTransformContextPtr": ("._o", "transformCtxt(_obj=%s)", "transformCtxt"),
538    "xsltTransformContext *": ("._o", "transformCtxt(_obj=%s)", "transformCtxt"),
539    "xsltStylesheetPtr": ("._o", "stylesheet(_obj=%s)", "stylesheet"),
540    "xsltStylesheet *": ("._o", "stylesheet(_obj=%s)", "stylesheet"),
541    "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
542    "xmlXPathContext *": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
543    "xmlXPathParserContextPtr": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"),
544    "xmlXPathParserContext *": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"),
545}
546
547converter_type = {
548    "xmlXPathObjectPtr": "libxml2.xpathObjectRet(%s)",
549}
550
551primary_classes = ["xpathParserContext", "xpathContext", "transformCtxt", "stylesheet"]
552
553classes_ancestor = {
554    "xpathContext" : "libxml2.xpathContext",
555    "xpathParserContext" : "libxml2.xpathParserContext",
556}
557classes_destructors = {
558    "xpathContext" : "pass"
559}
560
561function_classes = {}
562ctypes = []
563classes_list = []
564
565
566def nameFixup(name, classe, type, file):
567    listname = classe + "List"
568    ll = len(listname)
569    l = len(classe)
570    if name[0:l] == listname:
571        func = name[l:]
572        func = string.lower(func[0:1]) + func[1:]
573    elif name[0:12] == "xmlParserGet" and file == "python_accessor":
574        func = name[12:]
575        func = string.lower(func[0:1]) + func[1:]
576    elif name[0:12] == "xmlParserSet" and file == "python_accessor":
577        func = name[12:]
578        func = string.lower(func[0:1]) + func[1:]
579    elif name[0:10] == "xmlNodeGet" and file == "python_accessor":
580        func = name[10:]
581        func = string.lower(func[0:1]) + func[1:]
582    elif name[0:18] == "xsltXPathParserGet" and file == "python_accessor":
583        func = name[18:]
584        func = string.lower(func[0:1]) + func[1:]
585    elif name[0:12] == "xsltXPathGet" and file == "python_accessor":
586        func = name[12:]
587        func = string.lower(func[0:1]) + func[1:]
588    elif name[0:16] == "xsltTransformGet" and file == "python_accessor":
589        func = name[16:]
590        func = string.lower(func[0:1]) + func[1:]
591    elif name[0:16] == "xsltTransformSet" and file == "python_accessor":
592        func = name[13:]
593        func = string.lower(func[0:1]) + func[1:]
594    elif name[0:17] == "xsltStylesheetGet" and file == "python_accessor":
595        func = name[17:]
596        func = string.lower(func[0:1]) + func[1:]
597    elif name[0:17] == "xsltStylesheetSet" and file == "python_accessor":
598        func = name[14:]
599        func = string.lower(func[0:1]) + func[1:]
600    elif name[0:l] == classe:
601        func = name[l:]
602        func = string.lower(func[0:1]) + func[1:]
603    elif name[0:7] == "libxml_":
604        func = name[7:]
605        func = string.lower(func[0:1]) + func[1:]
606    elif name[0:8] == "libxslt_":
607        func = name[8:]
608        func = string.lower(func[0:1]) + func[1:]
609    elif name[0:6] == "xmlGet":
610        func = name[6:]
611        func = string.lower(func[0:1]) + func[1:]
612    elif name[0:3] == "xml":
613        func = name[3:]
614        func = string.lower(func[0:1]) + func[1:]
615    elif name[0:7] == "xsltGet":
616        func = name[7:]
617        func = string.lower(func[0:1]) + func[1:]
618    elif name[0:4] == "xslt":
619        func = name[4:]
620        func = string.lower(func[0:1]) + func[1:]
621    else:
622        func = name
623    if func[0:5] == "xPath":
624        func = "xpath" + func[5:]
625    elif func[0:4] == "xPtr":
626        func = "xpointer" + func[4:]
627    elif func[0:8] == "xInclude":
628        func = "xinclude" + func[8:]
629    elif func[0:2] == "iD":
630        func = "ID" + func[2:]
631    elif func[0:3] == "uRI":
632        func = "URI" + func[3:]
633    elif func[0:4] == "uTF8":
634        func = "UTF8" + func[4:]
635    return func
636
637def functionCompare(info1, info2):
638    (index1, func1, name1, ret1, args1, file1) = info1
639    (index2, func2, name2, ret2, args2, file2) = info2
640    if file1 == file2:
641        if func1 < func2:
642            return -1
643        if func1 > func2:
644            return 1
645    if file1 == "python_accessor":
646        return -1
647    if file2 == "python_accessor":
648        return 1
649    if file1 < file2:
650        return -1
651    if file1 > file2:
652        return 1
653    return 0
654
655def writeDoc(name, args, indent, output):
656     if functions[name][0] == None or functions[name][0] == "":
657         return
658     val = functions[name][0]
659     val = string.replace(val, "NULL", "None");
660     output.write(indent)
661     output.write('"""')
662     while len(val) > 60:
663         str = val[0:60]
664         i = string.rfind(str, " ");
665         if i < 0:
666             i = 60
667         str = val[0:i]
668         val = val[i:]
669         output.write(str)
670         output.write('\n  ');
671         output.write(indent)
672     output.write(val);
673     output.write('"""\n')
674
675def buildWrappers():
676    global ctypes
677    global py_types
678    global py_return_types
679    global unknown_types
680    global functions
681    global function_classes
682    global libxml2_classes_type
683    global classes_type
684    global classes_list
685    global converter_type
686    global primary_classes
687    global converter_type
688    global classes_ancestor
689    global converter_type
690    global primary_classes
691    global classes_ancestor
692    global classes_destructors
693
694    function_classes["None"] = []
695    for type in classes_type.keys():
696        function_classes[classes_type[type][2]] = []
697       
698    #
699    # Build the list of C types to look for ordered to start with
700    # primary classes
701    #
702    ctypes_processed = {}
703    classes_processed = {}
704    for classe in primary_classes:
705        classes_list.append(classe)
706        classes_processed[classe] = ()
707        for type in classes_type.keys():
708            tinfo = classes_type[type]
709            if tinfo[2] == classe:
710                ctypes.append(type)
711                ctypes_processed[type] = ()
712    for type in classes_type.keys():
713        if ctypes_processed.has_key(type):
714            continue
715        tinfo = classes_type[type]
716        if not classes_processed.has_key(tinfo[2]):
717            classes_list.append(tinfo[2])
718            classes_processed[tinfo[2]] = ()
719           
720        ctypes.append(type)
721        ctypes_processed[type] = ()
722
723    for name in functions.keys():
724        found = 0;
725        (desc, ret, args, file) = functions[name]
726        for type in ctypes:
727            classe = classes_type[type][2]
728
729            if name[0:4] == "xslt" and len(args) >= 1 and args[0][1] == type:
730                found = 1
731                func = nameFixup(name, classe, type, file)
732                info = (0, func, name, ret, args, file)
733                function_classes[classe].append(info)
734            elif name[0:4] == "xslt" and len(args) >= 2 and args[1][1] == type:
735                found = 1
736                func = nameFixup(name, classe, type, file)
737                info = (1, func, name, ret, args, file)
738                function_classes[classe].append(info)
739            elif name[0:4] == "xslt" and len(args) >= 3 and args[2][1] == type:
740                found = 1
741                func = nameFixup(name, classe, type, file)
742                info = (2, func, name, ret, args, file)
743                function_classes[classe].append(info)
744            if found == 1:
745                break
746        if found == 1:
747            continue
748        if name[0:8] == "xmlXPath":
749            continue
750        if name[0:6] == "xmlStr":
751            continue
752        if name[0:10] == "xmlCharStr":
753            continue
754        func = nameFixup(name, "None", file, file)
755        info = (0, func, name, ret, args, file)
756        function_classes['None'].append(info)
757
758    classes = open("libxsltclass.py", "w")
759    txt = open("libxsltclass.txt", "w")
760    txt.write("          Generated Classes for libxslt-python\n\n")
761
762    txt.write("#\n# Global functions of the module\n#\n\n")
763    if function_classes.has_key("None"):
764        flist = function_classes["None"]
765        flist.sort(functionCompare)
766        oldfile = ""
767        for info in flist:
768            (index, func, name, ret, args, file) = info
769            if file != oldfile:
770                classes.write("#\n# Functions from module %s\n#\n\n" % file)
771                txt.write("\n# functions from module %s\n" % file)
772                oldfile = file
773            classes.write("def %s(" % func)
774            txt.write("%s()\n" % func);
775            n = 0
776            for arg in args:
777                if n != 0:
778                    classes.write(", ")
779                classes.write("%s" % arg[0])
780                n = n + 1
781            classes.write("):\n")
782            writeDoc(name, args, '    ', classes);
783
784            for arg in args:
785                if classes_type.has_key(arg[1]):
786                    classes.write("    if %s == None: %s__o = None\n" %
787                                  (arg[0], arg[0]))
788                    classes.write("    else: %s__o = %s%s\n" %
789                                  (arg[0], arg[0], classes_type[arg[1]][0]))
790                elif libxml2_classes_type.has_key(arg[1]):
791                    classes.write("    if %s == None: %s__o = None\n" %
792                                  (arg[0], arg[0]))
793                    classes.write("    else: %s__o = %s%s\n" %
794                                  (arg[0], arg[0], libxml2_classes_type[arg[1]][0]))
795            if ret[0] != "void":
796                classes.write("    ret = ");
797            else:
798                classes.write("    ");
799            classes.write("libxsltmod.%s(" % name)
800            n = 0
801            for arg in args:
802                if n != 0:
803                    classes.write(", ");
804                classes.write("%s" % arg[0])
805                if classes_type.has_key(arg[1]):
806                    classes.write("__o");
807                if libxml2_classes_type.has_key(arg[1]):
808                    classes.write("__o");
809                n = n + 1
810            classes.write(")\n");
811            if ret[0] != "void":
812                if classes_type.has_key(ret[0]):
813                    classes.write("    if ret == None: return None\n");
814                    classes.write("    return ");
815                    classes.write(classes_type[ret[0]][1] % ("ret"));
816                    classes.write("\n");
817                elif libxml2_classes_type.has_key(ret[0]):
818                    classes.write("    if ret == None: return None\n");
819                    classes.write("    return libxml2.");
820                    classes.write(libxml2_classes_type[ret[0]][1] % ("ret"));
821                    classes.write("\n");
822                else:
823                    classes.write("    return ret\n");
824            classes.write("\n");
825
826    txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
827    for classname in classes_list:
828        if classname == "None":
829            pass
830        else:
831            if classes_ancestor.has_key(classname):
832                txt.write("\n\nClass %s(%s)\n" % (classname,
833                          classes_ancestor[classname]))
834                classes.write("class %s(%s):\n" % (classname,
835                              classes_ancestor[classname]))
836                classes.write("    def __init__(self, _obj=None):\n")
837                classes.write("        self._o = None\n")
838                classes.write("        %s.__init__(self, _obj=_obj)\n\n" % (
839                              classes_ancestor[classname]))
840                if classes_ancestor[classname] == "xmlCore" or \
841                   classes_ancestor[classname] == "xmlNode":
842                    classes.write("    def __repr__(self):\n")
843                    format = "%s:%%s" % (classname)
844                    classes.write("        return \"%s\" %% (self.name)\n\n" % (
845                                  format))
846            else:
847                txt.write("Class %s()\n" % (classname))
848                classes.write("class %s:\n" % (classname))
849                classes.write("    def __init__(self, _obj=None):\n")
850                classes.write("        if _obj != None:self._o = _obj;return\n")
851                classes.write("        self._o = None\n\n");
852            if classes_destructors.has_key(classname):
853                classes.write("    def __del__(self):\n")
854                if classes_destructors[classname] == "pass":
855                    classes.write("        pass\n")
856                else:
857                    classes.write("        if self._o != None:\n")
858                    classes.write("            libxsltmod.%s(self._o)\n" %
859                                  classes_destructors[classname]);
860                    classes.write("        self._o = None\n\n");
861            flist = function_classes[classname]
862            flist.sort(functionCompare)
863            oldfile = ""
864            for info in flist:
865                (index, func, name, ret, args, file) = info
866                if file != oldfile:
867                    if file == "python_accessor":
868                        classes.write("    # accessors for %s\n" % (classname))
869                        txt.write("    # accessors\n")
870                    else:
871                        classes.write("    #\n")
872                        classes.write("    # %s functions from module %s\n" % (
873                                      classname, file))
874                        txt.write("\n    # functions from module %s\n" % file)
875                        classes.write("    #\n\n")
876                oldfile = file
877                classes.write("    def %s(self" % func)
878                txt.write("    %s()\n" % func);
879                n = 0
880                for arg in args:
881                    if n != index:
882                        classes.write(", %s" % arg[0])
883                    n = n + 1
884                classes.write("):\n")
885                writeDoc(name, args, '        ', classes);
886                n = 0
887                for arg in args:
888                    if classes_type.has_key(arg[1]):
889                        if n != index:
890                            classes.write("        if %s == None: %s__o = None\n" %
891                                          (arg[0], arg[0]))
892                            classes.write("        else: %s__o = %s%s\n" %
893                                          (arg[0], arg[0], classes_type[arg[1]][0]))
894                    elif libxml2_classes_type.has_key(arg[1]):
895                        classes.write("        if %s == None: %s__o = None\n" %
896                                      (arg[0], arg[0]))
897                        classes.write("        else: %s__o = %s%s\n" %
898                                      (arg[0], arg[0],
899                                       libxml2_classes_type[arg[1]][0]))
900                    n = n + 1
901                if ret[0] != "void":
902                    classes.write("        ret = ");
903                else:
904                    classes.write("        ");
905                classes.write("libxsltmod.%s(" % name)
906                n = 0
907                for arg in args:
908                    if n != 0:
909                        classes.write(", ");
910                    if n != index:
911                        classes.write("%s" % arg[0])
912                        if classes_type.has_key(arg[1]):
913                            classes.write("__o");
914                        elif libxml2_classes_type.has_key(arg[1]):
915                            classes.write("__o");
916                    else:
917                        classes.write("self");
918                        if classes_type.has_key(arg[1]):
919                            classes.write(classes_type[arg[1]][0])
920                        elif libxml2_classes_type.has_key(arg[1]):
921                            classes.write(libxml2_classes_type[arg[1]][0])
922                    n = n + 1
923                classes.write(")\n");
924                if ret[0] != "void":
925                    if classes_type.has_key(ret[0]):
926                        classes.write("        if ret == None: return None\n");
927                        classes.write("        return ");
928                        classes.write(classes_type[ret[0]][1] % ("ret"));
929                        classes.write("\n");
930                    elif libxml2_classes_type.has_key(ret[0]):
931                        classes.write("        if ret == None: return None\n");
932                        classes.write("        return libxml2.");
933                        classes.write(libxml2_classes_type[ret[0]][1] % ("ret"));
934                        classes.write("\n");
935                    elif converter_type.has_key(ret[0]):
936                        classes.write("        if ret == None: return None\n");
937                        classes.write("        return ");
938                        classes.write(converter_type[ret[0]] % ("ret"));
939                        classes.write("\n");
940                    else:
941                        classes.write("        return ret\n");
942                classes.write("\n");
943
944    txt.close()
945    classes.close()
946
947buildStubs()
948buildWrappers()
Note: See TracBrowser for help on using the repository browser.