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