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 os |
| 10 import sys |
| 11 import string |
| 12 |
| 13 if __name__ == "__main__": |
| 14 # launched as a script |
| 15 srcPref = os.path.dirname(sys.argv[0]) |
| 16 else: |
| 17 # imported |
| 18 srcPref = os.path.dirname(__file__) |
| 19 |
| 20 ####################################################################### |
| 21 # |
| 22 # That part if purely the API acquisition phase from the |
| 23 # XML API description |
| 24 # |
| 25 ####################################################################### |
| 26 import os |
| 27 import xml.sax |
| 28 |
| 29 debug = 0 |
| 30 |
| 31 def getparser(): |
| 32 # Attach parser to an unmarshalling object. return both objects. |
| 33 target = docParser() |
| 34 parser = xml.sax.make_parser() |
| 35 parser.setContentHandler(target) |
| 36 return parser, target |
| 37 |
| 38 class docParser(xml.sax.handler.ContentHandler): |
| 39 def __init__(self): |
| 40 self._methodname = None |
| 41 self._data = [] |
| 42 self.in_function = 0 |
| 43 |
| 44 self.startElement = self.start |
| 45 self.endElement = self.end |
| 46 self.characters = self.data |
| 47 |
| 48 def close(self): |
| 49 if debug: |
| 50 print("close") |
| 51 |
| 52 def getmethodname(self): |
| 53 return self._methodname |
| 54 |
| 55 def data(self, text): |
| 56 if debug: |
| 57 print("data %s" % text) |
| 58 self._data.append(text) |
| 59 |
| 60 def start(self, tag, attrs): |
| 61 if debug: |
| 62 print("start %s, %s" % (tag, attrs)) |
| 63 if tag == 'function': |
| 64 self._data = [] |
| 65 self.in_function = 1 |
| 66 self.function = None |
| 67 self.function_cond = None |
| 68 self.function_args = [] |
| 69 self.function_descr = None |
| 70 self.function_return = None |
| 71 self.function_file = None |
| 72 if 'name' in attrs.keys(): |
| 73 self.function = attrs['name'] |
| 74 if 'file' in attrs.keys(): |
| 75 self.function_file = attrs['file'] |
| 76 elif tag == 'cond': |
| 77 self._data = [] |
| 78 elif tag == 'info': |
| 79 self._data = [] |
| 80 elif tag == 'arg': |
| 81 if self.in_function == 1: |
| 82 self.function_arg_name = None |
| 83 self.function_arg_type = None |
| 84 self.function_arg_info = None |
| 85 if 'name' in attrs.keys(): |
| 86 self.function_arg_name = attrs['name'] |
| 87 if 'type' in attrs.keys(): |
| 88 self.function_arg_type = attrs['type'] |
| 89 if 'info' in attrs.keys(): |
| 90 self.function_arg_info = attrs['info'] |
| 91 elif tag == 'return': |
| 92 if self.in_function == 1: |
| 93 self.function_return_type = None |
| 94 self.function_return_info = None |
| 95 self.function_return_field = None |
| 96 if 'type' in attrs.keys(): |
| 97 self.function_return_type = attrs['type'] |
| 98 if 'info' in attrs.keys(): |
| 99 self.function_return_info = attrs['info'] |
| 100 if 'field' in attrs.keys(): |
| 101 self.function_return_field = attrs['field'] |
| 102 elif tag == 'enum': |
| 103 enum(attrs['type'],attrs['name'],attrs['value']) |
| 104 |
| 105 def end(self, tag): |
| 106 if debug: |
| 107 print("end %s" % tag) |
| 108 if tag == 'function': |
| 109 if self.function != None: |
| 110 function(self.function, self.function_descr, |
| 111 self.function_return, self.function_args, |
| 112 self.function_file, self.function_cond) |
| 113 self.in_function = 0 |
| 114 elif tag == 'arg': |
| 115 if self.in_function == 1: |
| 116 self.function_args.append([self.function_arg_name, |
| 117 self.function_arg_type, |
| 118 self.function_arg_info]) |
| 119 elif tag == 'return': |
| 120 if self.in_function == 1: |
| 121 self.function_return = [self.function_return_type, |
| 122 self.function_return_info, |
| 123 self.function_return_field] |
| 124 elif tag == 'info': |
| 125 str = '' |
| 126 for c in self._data: |
| 127 str = str + c |
| 128 if self.in_function == 1: |
| 129 self.function_descr = str |
| 130 elif tag == 'cond': |
| 131 str = '' |
| 132 for c in self._data: |
| 133 str = str + c |
| 134 if self.in_function == 1: |
| 135 self.function_cond = str |
| 136 |
| 137 |
| 138 def function(name, desc, ret, args, file, cond): |
| 139 functions[name] = (desc, ret, args, file, cond) |
| 140 |
| 141 def enum(type, name, value): |
| 142 if type not in enums: |
| 143 enums[type] = {} |
| 144 enums[type][name] = value |
| 145 |
| 146 ####################################################################### |
| 147 # |
| 148 # Some filtering rukes to drop functions/types which should not |
| 149 # be exposed as-is on the Python interface |
| 150 # |
| 151 ####################################################################### |
| 152 |
| 153 skipped_modules = { |
| 154 'xmlmemory': None, |
| 155 'DOCBparser': None, |
| 156 'SAX': None, |
| 157 'hash': None, |
| 158 'list': None, |
| 159 'threads': None, |
| 160 # 'xpointer': None, |
| 161 } |
| 162 skipped_types = { |
| 163 'int *': "usually a return type", |
| 164 'xmlSAXHandlerPtr': "not the proper interface for SAX", |
| 165 'htmlSAXHandlerPtr': "not the proper interface for SAX", |
| 166 'xmlRMutexPtr': "thread specific, skipped", |
| 167 'xmlMutexPtr': "thread specific, skipped", |
| 168 'xmlGlobalStatePtr': "thread specific, skipped", |
| 169 'xmlListPtr': "internal representation not suitable for python", |
| 170 'xmlBufferPtr': "internal representation not suitable for python", |
| 171 'FILE *': None, |
| 172 } |
| 173 |
| 174 ####################################################################### |
| 175 # |
| 176 # Table of remapping to/from the python type or class to the C |
| 177 # counterpart. |
| 178 # |
| 179 ####################################################################### |
| 180 |
| 181 py_types = { |
| 182 'void': (None, None, None, None), |
| 183 'int': ('i', None, "int", "int"), |
| 184 'long': ('l', None, "long", "long"), |
| 185 'double': ('d', None, "double", "double"), |
| 186 'unsigned int': ('i', None, "int", "int"), |
| 187 'xmlChar': ('c', None, "int", "int"), |
| 188 'unsigned char *': ('z', None, "charPtr", "char *"), |
| 189 'char *': ('z', None, "charPtr", "char *"), |
| 190 'const char *': ('z', None, "charPtrConst", "const char *"), |
| 191 'xmlChar *': ('z', None, "xmlCharPtr", "xmlChar *"), |
| 192 'const xmlChar *': ('z', None, "xmlCharPtrConst", "const xmlChar *"), |
| 193 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 194 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 195 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 196 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 197 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 198 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 199 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 200 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 201 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 202 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 203 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 204 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 205 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 206 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 207 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 208 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 209 'xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"), |
| 210 'const xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"
), |
| 211 'xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"), |
| 212 'const xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr")
, |
| 213 'xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePt
r"), |
| 214 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttri
butePtr"), |
| 215 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr
"), |
| 216 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttrib
utePtr"), |
| 217 'xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), |
| 218 'const xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), |
| 219 'xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), |
| 220 'const xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), |
| 221 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 222 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 223 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 224 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 225 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 226 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 227 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 228 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), |
| 229 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 230 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 231 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 232 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), |
| 233 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXP
athContextPtr"), |
| 234 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathC
ontextPtr"), |
| 235 'xmlXPathParserContextPtr': ('O', "xmlXPathParserContext", "xmlXPathParserC
ontextPtr", "xmlXPathParserContextPtr"), |
| 236 'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPt
r"), |
| 237 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr
"), |
| 238 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtP
tr"), |
| 239 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPt
r"), |
| 240 'xmlValidCtxtPtr': ('O', "ValidCtxt", "xmlValidCtxtPtr", "xmlValidCtxtPtr"), |
| 241 'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"), |
| 242 'FILE *': ('O', "File", "FILEPtr", "FILE *"), |
| 243 'xmlURIPtr': ('O', "URI", "xmlURIPtr", "xmlURIPtr"), |
| 244 'xmlErrorPtr': ('O', "Error", "xmlErrorPtr", "xmlErrorPtr"), |
| 245 'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutput
BufferPtr"), |
| 246 'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "
xmlParserInputBufferPtr"), |
| 247 'xmlRegexpPtr': ('O', "xmlReg", "xmlRegexpPtr", "xmlRegexpPtr"), |
| 248 'xmlTextReaderLocatorPtr': ('O', "xmlTextReaderLocator", "xmlTextReaderLocat
orPtr", "xmlTextReaderLocatorPtr"), |
| 249 'xmlTextReaderPtr': ('O', "xmlTextReader", "xmlTextReaderPtr", "xmlTextReade
rPtr"), |
| 250 'xmlRelaxNGPtr': ('O', "relaxNgSchema", "xmlRelaxNGPtr", "xmlRelaxNGPtr"), |
| 251 'xmlRelaxNGParserCtxtPtr': ('O', "relaxNgParserCtxt", "xmlRelaxNGParserCtxtP
tr", "xmlRelaxNGParserCtxtPtr"), |
| 252 'xmlRelaxNGValidCtxtPtr': ('O', "relaxNgValidCtxt", "xmlRelaxNGValidCtxtPtr"
, "xmlRelaxNGValidCtxtPtr"), |
| 253 'xmlSchemaPtr': ('O', "Schema", "xmlSchemaPtr", "xmlSchemaPtr"), |
| 254 'xmlSchemaParserCtxtPtr': ('O', "SchemaParserCtxt", "xmlSchemaParserCtxtPtr"
, "xmlSchemaParserCtxtPtr"), |
| 255 'xmlSchemaValidCtxtPtr': ('O', "SchemaValidCtxt", "xmlSchemaValidCtxtPtr", "
xmlSchemaValidCtxtPtr"), |
| 256 } |
| 257 |
| 258 py_return_types = { |
| 259 'xmlXPathObjectPtr': ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr")
, |
| 260 } |
| 261 |
| 262 unknown_types = {} |
| 263 |
| 264 foreign_encoding_args = ( |
| 265 'htmlCreateMemoryParserCtxt', |
| 266 'htmlCtxtReadMemory', |
| 267 'htmlParseChunk', |
| 268 'htmlReadMemory', |
| 269 'xmlCreateMemoryParserCtxt', |
| 270 'xmlCtxtReadMemory', |
| 271 'xmlCtxtResetPush', |
| 272 'xmlParseChunk', |
| 273 'xmlParseMemory', |
| 274 'xmlReadMemory', |
| 275 'xmlRecoverMemory', |
| 276 ) |
| 277 |
| 278 ####################################################################### |
| 279 # |
| 280 # This part writes the C <-> Python stubs libxml2-py.[ch] and |
| 281 # the table libxml2-export.c to add when registrering the Python module |
| 282 # |
| 283 ####################################################################### |
| 284 |
| 285 # Class methods which are written by hand in libxml.c but the Python-level |
| 286 # code is still automatically generated (so they are not in skip_function()). |
| 287 skip_impl = ( |
| 288 'xmlSaveFileTo', |
| 289 'xmlSaveFormatFileTo', |
| 290 ) |
| 291 |
| 292 def skip_function(name): |
| 293 if name[0:12] == "xmlXPathWrap": |
| 294 return 1 |
| 295 if name == "xmlFreeParserCtxt": |
| 296 return 1 |
| 297 if name == "xmlCleanupParser": |
| 298 return 1 |
| 299 if name == "xmlFreeTextReader": |
| 300 return 1 |
| 301 # if name[0:11] == "xmlXPathNew": |
| 302 # return 1 |
| 303 # the next function is defined in libxml.c |
| 304 if name == "xmlRelaxNGFreeValidCtxt": |
| 305 return 1 |
| 306 if name == "xmlFreeValidCtxt": |
| 307 return 1 |
| 308 if name == "xmlSchemaFreeValidCtxt": |
| 309 return 1 |
| 310 |
| 311 # |
| 312 # Those are skipped because the Const version is used of the bindings |
| 313 # instead. |
| 314 # |
| 315 if name == "xmlTextReaderBaseUri": |
| 316 return 1 |
| 317 if name == "xmlTextReaderLocalName": |
| 318 return 1 |
| 319 if name == "xmlTextReaderName": |
| 320 return 1 |
| 321 if name == "xmlTextReaderNamespaceUri": |
| 322 return 1 |
| 323 if name == "xmlTextReaderPrefix": |
| 324 return 1 |
| 325 if name == "xmlTextReaderXmlLang": |
| 326 return 1 |
| 327 if name == "xmlTextReaderValue": |
| 328 return 1 |
| 329 if name == "xmlOutputBufferClose": # handled by by the superclass |
| 330 return 1 |
| 331 if name == "xmlOutputBufferFlush": # handled by by the superclass |
| 332 return 1 |
| 333 if name == "xmlErrMemory": |
| 334 return 1 |
| 335 |
| 336 if name == "xmlValidBuildContentModel": |
| 337 return 1 |
| 338 if name == "xmlValidateElementDecl": |
| 339 return 1 |
| 340 if name == "xmlValidateAttributeDecl": |
| 341 return 1 |
| 342 if name == "xmlPopInputCallbacks": |
| 343 return 1 |
| 344 |
| 345 return 0 |
| 346 |
| 347 def print_function_wrapper(name, output, export, include): |
| 348 global py_types |
| 349 global unknown_types |
| 350 global functions |
| 351 global skipped_modules |
| 352 |
| 353 try: |
| 354 (desc, ret, args, file, cond) = functions[name] |
| 355 except: |
| 356 print("failed to get function %s infos") |
| 357 return |
| 358 |
| 359 if file in skipped_modules: |
| 360 return 0 |
| 361 if skip_function(name) == 1: |
| 362 return 0 |
| 363 if name in skip_impl: |
| 364 # Don't delete the function entry in the caller. |
| 365 return 1 |
| 366 |
| 367 c_call = "" |
| 368 format="" |
| 369 format_args="" |
| 370 c_args="" |
| 371 c_return="" |
| 372 c_convert="" |
| 373 c_release="" |
| 374 num_bufs=0 |
| 375 for arg in args: |
| 376 # This should be correct |
| 377 if arg[1][0:6] == "const ": |
| 378 arg[1] = arg[1][6:] |
| 379 c_args = c_args + " %s %s;\n" % (arg[1], arg[0]) |
| 380 if arg[1] in py_types: |
| 381 (f, t, n, c) = py_types[arg[1]] |
| 382 if (f == 'z') and (name in foreign_encoding_args) and (num_bufs == 0
): |
| 383 f = 's#' |
| 384 if f != None: |
| 385 format = format + f |
| 386 if t != None: |
| 387 format_args = format_args + ", &pyobj_%s" % (arg[0]) |
| 388 c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0]) |
| 389 c_convert = c_convert + \ |
| 390 " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0], |
| 391 arg[1], t, arg[0]) |
| 392 else: |
| 393 format_args = format_args + ", &%s" % (arg[0]) |
| 394 if f == 's#': |
| 395 format_args = format_args + ", &py_buffsize%d" % num_bufs |
| 396 c_args = c_args + " int py_buffsize%d;\n" % num_bufs |
| 397 num_bufs = num_bufs + 1 |
| 398 if c_call != "": |
| 399 c_call = c_call + ", " |
| 400 c_call = c_call + "%s" % (arg[0]) |
| 401 if t == "File": |
| 402 c_release = c_release + \ |
| 403 " PyFile_Release(%s);\n" % (arg[0]) |
| 404 else: |
| 405 if arg[1] in skipped_types: |
| 406 return 0 |
| 407 if arg[1] in unknown_types: |
| 408 lst = unknown_types[arg[1]] |
| 409 lst.append(name) |
| 410 else: |
| 411 unknown_types[arg[1]] = [name] |
| 412 return -1 |
| 413 if format != "": |
| 414 format = format + ":%s" % (name) |
| 415 |
| 416 if ret[0] == 'void': |
| 417 if file == "python_accessor": |
| 418 if args[1][1] == "char *" or args[1][1] == "xmlChar *": |
| 419 c_call = "\n if (%s->%s != NULL) xmlFree(%s->%s);\n" % ( |
| 420 args[0][0], args[1][0], args[0][0], args[1][0]) |
| 421 c_call = c_call + " %s->%s = (%s)xmlStrdup((const xmlChar *)%
s);\n" % (args[0][0], |
| 422 args[1][0], args[1][1], args[1][0]) |
| 423 else: |
| 424 c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0], |
| 425 args[1][0]) |
| 426 else: |
| 427 c_call = "\n %s(%s);\n" % (name, c_call) |
| 428 ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n" |
| 429 elif ret[0] in py_types: |
| 430 (f, t, n, c) = py_types[ret[0]] |
| 431 c_return = c_return + " %s c_retval;\n" % (ret[0]) |
| 432 if file == "python_accessor" and ret[2] != None: |
| 433 c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2]) |
| 434 else: |
| 435 c_call = "\n c_retval = %s(%s);\n" % (name, c_call) |
| 436 ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c) |
| 437 ret_convert = ret_convert + " return(py_retval);\n" |
| 438 elif ret[0] in py_return_types: |
| 439 (f, t, n, c) = py_return_types[ret[0]] |
| 440 c_return = c_return + " %s c_retval;\n" % (ret[0]) |
| 441 c_call = "\n c_retval = %s(%s);\n" % (name, c_call) |
| 442 ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c) |
| 443 ret_convert = ret_convert + " return(py_retval);\n" |
| 444 else: |
| 445 if ret[0] in skipped_types: |
| 446 return 0 |
| 447 if ret[0] in unknown_types: |
| 448 lst = unknown_types[ret[0]] |
| 449 lst.append(name) |
| 450 else: |
| 451 unknown_types[ret[0]] = [name] |
| 452 return -1 |
| 453 |
| 454 if cond != None and cond != "": |
| 455 include.write("#if %s\n" % cond) |
| 456 export.write("#if %s\n" % cond) |
| 457 output.write("#if %s\n" % cond) |
| 458 |
| 459 include.write("PyObject * ") |
| 460 include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name)) |
| 461 |
| 462 export.write(" { (char *)\"%s\", libxml_%s, METH_VARARGS, NULL },\n" % |
| 463 (name, name)) |
| 464 |
| 465 if file == "python": |
| 466 # Those have been manually generated |
| 467 if cond != None and cond != "": |
| 468 include.write("#endif\n") |
| 469 export.write("#endif\n") |
| 470 output.write("#endif\n") |
| 471 return 1 |
| 472 if file == "python_accessor" and ret[0] != "void" and ret[2] is None: |
| 473 # Those have been manually generated |
| 474 if cond != None and cond != "": |
| 475 include.write("#endif\n") |
| 476 export.write("#endif\n") |
| 477 output.write("#endif\n") |
| 478 return 1 |
| 479 |
| 480 output.write("PyObject *\n") |
| 481 output.write("libxml_%s(PyObject *self ATTRIBUTE_UNUSED," % (name)) |
| 482 output.write(" PyObject *args") |
| 483 if format == "": |
| 484 output.write(" ATTRIBUTE_UNUSED") |
| 485 output.write(") {\n") |
| 486 if ret[0] != 'void': |
| 487 output.write(" PyObject *py_retval;\n") |
| 488 if c_return != "": |
| 489 output.write(c_return) |
| 490 if c_args != "": |
| 491 output.write(c_args) |
| 492 if format != "": |
| 493 output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" % |
| 494 (format, format_args)) |
| 495 output.write(" return(NULL);\n") |
| 496 if c_convert != "": |
| 497 output.write(c_convert) |
| 498 |
| 499 output.write(c_call) |
| 500 if c_release != "": |
| 501 output.write(c_release) |
| 502 output.write(ret_convert) |
| 503 output.write("}\n\n") |
| 504 if cond != None and cond != "": |
| 505 include.write("#endif /* %s */\n" % cond) |
| 506 export.write("#endif /* %s */\n" % cond) |
| 507 output.write("#endif /* %s */\n" % cond) |
| 508 return 1 |
| 509 |
| 510 def buildStubs(): |
| 511 global py_types |
| 512 global py_return_types |
| 513 global unknown_types |
| 514 |
| 515 try: |
| 516 f = open(os.path.join(srcPref,"libxml2-api.xml")) |
| 517 data = f.read() |
| 518 (parser, target) = getparser() |
| 519 parser.feed(data) |
| 520 parser.close() |
| 521 except IOError as msg: |
| 522 try: |
| 523 f = open(os.path.join(srcPref,"..","doc","libxml2-api.xml")) |
| 524 data = f.read() |
| 525 (parser, target) = getparser() |
| 526 parser.feed(data) |
| 527 parser.close() |
| 528 except IOError as msg: |
| 529 print(file, ":", msg) |
| 530 sys.exit(1) |
| 531 |
| 532 n = len(list(functions.keys())) |
| 533 print("Found %d functions in libxml2-api.xml" % (n)) |
| 534 |
| 535 py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObje
ct") |
| 536 try: |
| 537 f = open(os.path.join(srcPref,"libxml2-python-api.xml")) |
| 538 data = f.read() |
| 539 (parser, target) = getparser() |
| 540 parser.feed(data) |
| 541 parser.close() |
| 542 except IOError as msg: |
| 543 print(file, ":", msg) |
| 544 |
| 545 |
| 546 print("Found %d functions in libxml2-python-api.xml" % ( |
| 547 len(list(functions.keys())) - n)) |
| 548 nb_wrap = 0 |
| 549 failed = 0 |
| 550 skipped = 0 |
| 551 |
| 552 include = open("libxml2-py.h", "w") |
| 553 include.write("/* Generated */\n\n") |
| 554 export = open("libxml2-export.c", "w") |
| 555 export.write("/* Generated */\n\n") |
| 556 wrapper = open("libxml2-py.c", "w") |
| 557 wrapper.write("/* Generated */\n\n") |
| 558 wrapper.write("#include <Python.h>\n") |
| 559 wrapper.write("#include <libxml/xmlversion.h>\n") |
| 560 wrapper.write("#include <libxml/tree.h>\n") |
| 561 wrapper.write("#include <libxml/xmlschemastypes.h>\n") |
| 562 wrapper.write("#include \"libxml_wrap.h\"\n") |
| 563 wrapper.write("#include \"libxml2-py.h\"\n\n") |
| 564 for function in sorted(functions.keys()): |
| 565 ret = print_function_wrapper(function, wrapper, export, include) |
| 566 if ret < 0: |
| 567 failed = failed + 1 |
| 568 del functions[function] |
| 569 if ret == 0: |
| 570 skipped = skipped + 1 |
| 571 del functions[function] |
| 572 if ret == 1: |
| 573 nb_wrap = nb_wrap + 1 |
| 574 include.close() |
| 575 export.close() |
| 576 wrapper.close() |
| 577 |
| 578 print("Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap, |
| 579 failed, skipped)) |
| 580 print("Missing type converters: ") |
| 581 for type in list(unknown_types.keys()): |
| 582 print("%s:%d " % (type, len(unknown_types[type]))) |
| 583 print() |
| 584 |
| 585 ####################################################################### |
| 586 # |
| 587 # This part writes part of the Python front-end classes based on |
| 588 # mapping rules between types and classes and also based on function |
| 589 # renaming to get consistent function names at the Python level |
| 590 # |
| 591 ####################################################################### |
| 592 |
| 593 # |
| 594 # The type automatically remapped to generated classes |
| 595 # |
| 596 classes_type = { |
| 597 "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"), |
| 598 "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"), |
| 599 "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), |
| 600 "xmlDoc *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), |
| 601 "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), |
| 602 "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), |
| 603 "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"), |
| 604 "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"), |
| 605 "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"), |
| 606 "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"), |
| 607 "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"), |
| 608 "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"), |
| 609 "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"), |
| 610 "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"), |
| 611 "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"), |
| 612 "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"), |
| 613 "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), |
| 614 "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), |
| 615 "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"), |
| 616 "xmlXPathContext *": ("._o", "xpathContext(_obj=%s)", "xpathContext"), |
| 617 "xmlXPathParserContext *": ("._o", "xpathParserContext(_obj=%s)", "xpathPars
erContext"), |
| 618 "xmlXPathParserContextPtr": ("._o", "xpathParserContext(_obj=%s)", "xpathPar
serContext"), |
| 619 "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), |
| 620 "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), |
| 621 "htmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), |
| 622 "htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), |
| 623 "xmlValidCtxtPtr": ("._o", "ValidCtxt(_obj=%s)", "ValidCtxt"), |
| 624 "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"), |
| 625 "xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"), |
| 626 "xmlErrorPtr": ("._o", "Error(_obj=%s)", "Error"), |
| 627 "xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"), |
| 628 "xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"), |
| 629 "xmlRegexpPtr": ("._o", "xmlReg(_obj=%s)", "xmlReg"), |
| 630 "xmlTextReaderLocatorPtr": ("._o", "xmlTextReaderLocator(_obj=%s)", "xmlText
ReaderLocator"), |
| 631 "xmlTextReaderPtr": ("._o", "xmlTextReader(_obj=%s)", "xmlTextReader"), |
| 632 'xmlRelaxNGPtr': ('._o', "relaxNgSchema(_obj=%s)", "relaxNgSchema"), |
| 633 'xmlRelaxNGParserCtxtPtr': ('._o', "relaxNgParserCtxt(_obj=%s)", "relaxNgPar
serCtxt"), |
| 634 'xmlRelaxNGValidCtxtPtr': ('._o', "relaxNgValidCtxt(_obj=%s)", "relaxNgValid
Ctxt"), |
| 635 'xmlSchemaPtr': ("._o", "Schema(_obj=%s)", "Schema"), |
| 636 'xmlSchemaParserCtxtPtr': ("._o", "SchemaParserCtxt(_obj=%s)", "SchemaParser
Ctxt"), |
| 637 'xmlSchemaValidCtxtPtr': ("._o", "SchemaValidCtxt(_obj=%s)", "SchemaValidCtx
t"), |
| 638 } |
| 639 |
| 640 converter_type = { |
| 641 "xmlXPathObjectPtr": "xpathObjectRet(%s)", |
| 642 } |
| 643 |
| 644 primary_classes = ["xmlNode", "xmlDoc"] |
| 645 |
| 646 classes_ancestor = { |
| 647 "xmlNode" : "xmlCore", |
| 648 "xmlDtd" : "xmlNode", |
| 649 "xmlDoc" : "xmlNode", |
| 650 "xmlAttr" : "xmlNode", |
| 651 "xmlNs" : "xmlNode", |
| 652 "xmlEntity" : "xmlNode", |
| 653 "xmlElement" : "xmlNode", |
| 654 "xmlAttribute" : "xmlNode", |
| 655 "outputBuffer": "ioWriteWrapper", |
| 656 "inputBuffer": "ioReadWrapper", |
| 657 "parserCtxt": "parserCtxtCore", |
| 658 "xmlTextReader": "xmlTextReaderCore", |
| 659 "ValidCtxt": "ValidCtxtCore", |
| 660 "SchemaValidCtxt": "SchemaValidCtxtCore", |
| 661 "relaxNgValidCtxt": "relaxNgValidCtxtCore", |
| 662 } |
| 663 classes_destructors = { |
| 664 "parserCtxt": "xmlFreeParserCtxt", |
| 665 "catalog": "xmlFreeCatalog", |
| 666 "URI": "xmlFreeURI", |
| 667 # "outputBuffer": "xmlOutputBufferClose", |
| 668 "inputBuffer": "xmlFreeParserInputBuffer", |
| 669 "xmlReg": "xmlRegFreeRegexp", |
| 670 "xmlTextReader": "xmlFreeTextReader", |
| 671 "relaxNgSchema": "xmlRelaxNGFree", |
| 672 "relaxNgParserCtxt": "xmlRelaxNGFreeParserCtxt", |
| 673 "relaxNgValidCtxt": "xmlRelaxNGFreeValidCtxt", |
| 674 "Schema": "xmlSchemaFree", |
| 675 "SchemaParserCtxt": "xmlSchemaFreeParserCtxt", |
| 676 "SchemaValidCtxt": "xmlSchemaFreeValidCtxt", |
| 677 "ValidCtxt": "xmlFreeValidCtxt", |
| 678 } |
| 679 |
| 680 functions_noexcept = { |
| 681 "xmlHasProp": 1, |
| 682 "xmlHasNsProp": 1, |
| 683 "xmlDocSetRootElement": 1, |
| 684 "xmlNodeGetNs": 1, |
| 685 "xmlNodeGetNsDefs": 1, |
| 686 "xmlNextElementSibling": 1, |
| 687 "xmlPreviousElementSibling": 1, |
| 688 "xmlFirstElementChild": 1, |
| 689 "xmlLastElementChild": 1, |
| 690 } |
| 691 |
| 692 reference_keepers = { |
| 693 "xmlTextReader": [('inputBuffer', 'input')], |
| 694 "relaxNgValidCtxt": [('relaxNgSchema', 'schema')], |
| 695 "SchemaValidCtxt": [('Schema', 'schema')], |
| 696 } |
| 697 |
| 698 function_classes = {} |
| 699 |
| 700 function_classes["None"] = [] |
| 701 |
| 702 def nameFixup(name, classe, type, file): |
| 703 listname = classe + "List" |
| 704 ll = len(listname) |
| 705 l = len(classe) |
| 706 if name[0:l] == listname: |
| 707 func = name[l:] |
| 708 func = func[0:1].lower() + func[1:] |
| 709 elif name[0:12] == "xmlParserGet" and file == "python_accessor": |
| 710 func = name[12:] |
| 711 func = func[0:1].lower() + func[1:] |
| 712 elif name[0:12] == "xmlParserSet" and file == "python_accessor": |
| 713 func = name[12:] |
| 714 func = func[0:1].lower() + func[1:] |
| 715 elif name[0:10] == "xmlNodeGet" and file == "python_accessor": |
| 716 func = name[10:] |
| 717 func = func[0:1].lower() + func[1:] |
| 718 elif name[0:9] == "xmlURIGet" and file == "python_accessor": |
| 719 func = name[9:] |
| 720 func = func[0:1].lower() + func[1:] |
| 721 elif name[0:9] == "xmlURISet" and file == "python_accessor": |
| 722 func = name[6:] |
| 723 func = func[0:1].lower() + func[1:] |
| 724 elif name[0:11] == "xmlErrorGet" and file == "python_accessor": |
| 725 func = name[11:] |
| 726 func = func[0:1].lower() + func[1:] |
| 727 elif name[0:17] == "xmlXPathParserGet" and file == "python_accessor": |
| 728 func = name[17:] |
| 729 func = func[0:1].lower() + func[1:] |
| 730 elif name[0:11] == "xmlXPathGet" and file == "python_accessor": |
| 731 func = name[11:] |
| 732 func = func[0:1].lower() + func[1:] |
| 733 elif name[0:11] == "xmlXPathSet" and file == "python_accessor": |
| 734 func = name[8:] |
| 735 func = func[0:1].lower() + func[1:] |
| 736 elif name[0:15] == "xmlOutputBuffer" and file != "python": |
| 737 func = name[15:] |
| 738 func = func[0:1].lower() + func[1:] |
| 739 elif name[0:20] == "xmlParserInputBuffer" and file != "python": |
| 740 func = name[20:] |
| 741 func = func[0:1].lower() + func[1:] |
| 742 elif name[0:9] == "xmlRegexp" and file == "xmlregexp": |
| 743 func = "regexp" + name[9:] |
| 744 elif name[0:6] == "xmlReg" and file == "xmlregexp": |
| 745 func = "regexp" + name[6:] |
| 746 elif name[0:20] == "xmlTextReaderLocator" and file == "xmlreader": |
| 747 func = name[20:] |
| 748 elif name[0:18] == "xmlTextReaderConst" and file == "xmlreader": |
| 749 func = name[18:] |
| 750 elif name[0:13] == "xmlTextReader" and file == "xmlreader": |
| 751 func = name[13:] |
| 752 elif name[0:12] == "xmlReaderNew" and file == "xmlreader": |
| 753 func = name[9:] |
| 754 elif name[0:11] == "xmlACatalog": |
| 755 func = name[11:] |
| 756 func = func[0:1].lower() + func[1:] |
| 757 elif name[0:l] == classe: |
| 758 func = name[l:] |
| 759 func = func[0:1].lower() + func[1:] |
| 760 elif name[0:7] == "libxml_": |
| 761 func = name[7:] |
| 762 func = func[0:1].lower() + func[1:] |
| 763 elif name[0:6] == "xmlGet": |
| 764 func = name[6:] |
| 765 func = func[0:1].lower() + func[1:] |
| 766 elif name[0:3] == "xml": |
| 767 func = name[3:] |
| 768 func = func[0:1].lower() + func[1:] |
| 769 else: |
| 770 func = name |
| 771 if func[0:5] == "xPath": |
| 772 func = "xpath" + func[5:] |
| 773 elif func[0:4] == "xPtr": |
| 774 func = "xpointer" + func[4:] |
| 775 elif func[0:8] == "xInclude": |
| 776 func = "xinclude" + func[8:] |
| 777 elif func[0:2] == "iD": |
| 778 func = "ID" + func[2:] |
| 779 elif func[0:3] == "uRI": |
| 780 func = "URI" + func[3:] |
| 781 elif func[0:4] == "uTF8": |
| 782 func = "UTF8" + func[4:] |
| 783 elif func[0:3] == 'sAX': |
| 784 func = "SAX" + func[3:] |
| 785 return func |
| 786 |
| 787 |
| 788 def functionCompare(info1, info2): |
| 789 (index1, func1, name1, ret1, args1, file1) = info1 |
| 790 (index2, func2, name2, ret2, args2, file2) = info2 |
| 791 if file1 == file2: |
| 792 if func1 < func2: |
| 793 return -1 |
| 794 if func1 > func2: |
| 795 return 1 |
| 796 if file1 == "python_accessor": |
| 797 return -1 |
| 798 if file2 == "python_accessor": |
| 799 return 1 |
| 800 if file1 < file2: |
| 801 return -1 |
| 802 if file1 > file2: |
| 803 return 1 |
| 804 return 0 |
| 805 |
| 806 def cmp_to_key(mycmp): |
| 807 'Convert a cmp= function into a key= function' |
| 808 class K(object): |
| 809 def __init__(self, obj, *args): |
| 810 self.obj = obj |
| 811 def __lt__(self, other): |
| 812 return mycmp(self.obj, other.obj) < 0 |
| 813 def __gt__(self, other): |
| 814 return mycmp(self.obj, other.obj) > 0 |
| 815 def __eq__(self, other): |
| 816 return mycmp(self.obj, other.obj) == 0 |
| 817 def __le__(self, other): |
| 818 return mycmp(self.obj, other.obj) <= 0 |
| 819 def __ge__(self, other): |
| 820 return mycmp(self.obj, other.obj) >= 0 |
| 821 def __ne__(self, other): |
| 822 return mycmp(self.obj, other.obj) != 0 |
| 823 return K |
| 824 def writeDoc(name, args, indent, output): |
| 825 if functions[name][0] is None or functions[name][0] == "": |
| 826 return |
| 827 val = functions[name][0] |
| 828 val = val.replace("NULL", "None") |
| 829 output.write(indent) |
| 830 output.write('"""') |
| 831 while len(val) > 60: |
| 832 if val[0] == " ": |
| 833 val = val[1:] |
| 834 continue |
| 835 str = val[0:60] |
| 836 i = str.rfind(" ") |
| 837 if i < 0: |
| 838 i = 60 |
| 839 str = val[0:i] |
| 840 val = val[i:] |
| 841 output.write(str) |
| 842 output.write('\n ') |
| 843 output.write(indent) |
| 844 output.write(val) |
| 845 output.write(' """\n') |
| 846 |
| 847 def buildWrappers(): |
| 848 global ctypes |
| 849 global py_types |
| 850 global py_return_types |
| 851 global unknown_types |
| 852 global functions |
| 853 global function_classes |
| 854 global classes_type |
| 855 global classes_list |
| 856 global converter_type |
| 857 global primary_classes |
| 858 global converter_type |
| 859 global classes_ancestor |
| 860 global converter_type |
| 861 global primary_classes |
| 862 global classes_ancestor |
| 863 global classes_destructors |
| 864 global functions_noexcept |
| 865 |
| 866 for type in classes_type.keys(): |
| 867 function_classes[classes_type[type][2]] = [] |
| 868 |
| 869 # |
| 870 # Build the list of C types to look for ordered to start |
| 871 # with primary classes |
| 872 # |
| 873 ctypes = [] |
| 874 classes_list = [] |
| 875 ctypes_processed = {} |
| 876 classes_processed = {} |
| 877 for classe in primary_classes: |
| 878 classes_list.append(classe) |
| 879 classes_processed[classe] = () |
| 880 for type in classes_type.keys(): |
| 881 tinfo = classes_type[type] |
| 882 if tinfo[2] == classe: |
| 883 ctypes.append(type) |
| 884 ctypes_processed[type] = () |
| 885 for type in sorted(classes_type.keys()): |
| 886 if type in ctypes_processed: |
| 887 continue |
| 888 tinfo = classes_type[type] |
| 889 if tinfo[2] not in classes_processed: |
| 890 classes_list.append(tinfo[2]) |
| 891 classes_processed[tinfo[2]] = () |
| 892 |
| 893 ctypes.append(type) |
| 894 ctypes_processed[type] = () |
| 895 |
| 896 for name in functions.keys(): |
| 897 found = 0 |
| 898 (desc, ret, args, file, cond) = functions[name] |
| 899 for type in ctypes: |
| 900 classe = classes_type[type][2] |
| 901 |
| 902 if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type: |
| 903 found = 1 |
| 904 func = nameFixup(name, classe, type, file) |
| 905 info = (0, func, name, ret, args, file) |
| 906 function_classes[classe].append(info) |
| 907 elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type \ |
| 908 and file != "python_accessor": |
| 909 found = 1 |
| 910 func = nameFixup(name, classe, type, file) |
| 911 info = (1, func, name, ret, args, file) |
| 912 function_classes[classe].append(info) |
| 913 elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type: |
| 914 found = 1 |
| 915 func = nameFixup(name, classe, type, file) |
| 916 info = (0, func, name, ret, args, file) |
| 917 function_classes[classe].append(info) |
| 918 elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type \ |
| 919 and file != "python_accessor": |
| 920 found = 1 |
| 921 func = nameFixup(name, classe, type, file) |
| 922 info = (1, func, name, ret, args, file) |
| 923 function_classes[classe].append(info) |
| 924 if found == 1: |
| 925 continue |
| 926 if name[0:8] == "xmlXPath": |
| 927 continue |
| 928 if name[0:6] == "xmlStr": |
| 929 continue |
| 930 if name[0:10] == "xmlCharStr": |
| 931 continue |
| 932 func = nameFixup(name, "None", file, file) |
| 933 info = (0, func, name, ret, args, file) |
| 934 function_classes['None'].append(info) |
| 935 |
| 936 classes = open("libxml2class.py", "w") |
| 937 txt = open("libxml2class.txt", "w") |
| 938 txt.write(" Generated Classes for libxml2-python\n\n") |
| 939 |
| 940 txt.write("#\n# Global functions of the module\n#\n\n") |
| 941 if "None" in function_classes: |
| 942 flist = function_classes["None"] |
| 943 flist = sorted(flist, key=cmp_to_key(functionCompare)) |
| 944 oldfile = "" |
| 945 for info in flist: |
| 946 (index, func, name, ret, args, file) = info |
| 947 if file != oldfile: |
| 948 classes.write("#\n# Functions from module %s\n#\n\n" % file) |
| 949 txt.write("\n# functions from module %s\n" % file) |
| 950 oldfile = file |
| 951 classes.write("def %s(" % func) |
| 952 txt.write("%s()\n" % func) |
| 953 n = 0 |
| 954 for arg in args: |
| 955 if n != 0: |
| 956 classes.write(", ") |
| 957 classes.write("%s" % arg[0]) |
| 958 n = n + 1 |
| 959 classes.write("):\n") |
| 960 writeDoc(name, args, ' ', classes) |
| 961 |
| 962 for arg in args: |
| 963 if arg[1] in classes_type: |
| 964 classes.write(" if %s is None: %s__o = None\n" % |
| 965 (arg[0], arg[0])) |
| 966 classes.write(" else: %s__o = %s%s\n" % |
| 967 (arg[0], arg[0], classes_type[arg[1]][0])) |
| 968 if arg[1] in py_types: |
| 969 (f, t, n, c) = py_types[arg[1]] |
| 970 if t == "File": |
| 971 classes.write(" if %s is not None: %s.flush()\n" % ( |
| 972 arg[0], arg[0])) |
| 973 |
| 974 if ret[0] != "void": |
| 975 classes.write(" ret = ") |
| 976 else: |
| 977 classes.write(" ") |
| 978 classes.write("libxml2mod.%s(" % name) |
| 979 n = 0 |
| 980 for arg in args: |
| 981 if n != 0: |
| 982 classes.write(", ") |
| 983 classes.write("%s" % arg[0]) |
| 984 if arg[1] in classes_type: |
| 985 classes.write("__o") |
| 986 n = n + 1 |
| 987 classes.write(")\n") |
| 988 |
| 989 # This may be needed to reposition the I/O, but likely to cause more harm |
| 990 # than good. Those changes in Python3 really break the model. |
| 991 # for arg in args: |
| 992 # if arg[1] in py_types: |
| 993 # (f, t, n, c) = py_types[arg[1]] |
| 994 # if t == "File": |
| 995 # classes.write(" if %s is not None: %s.seek(0,0)\n"%( |
| 996 # arg[0], arg[0])) |
| 997 |
| 998 if ret[0] != "void": |
| 999 if ret[0] in classes_type: |
| 1000 # |
| 1001 # Raise an exception |
| 1002 # |
| 1003 if name in functions_noexcept: |
| 1004 classes.write(" if ret is None:return None\n") |
| 1005 elif name.find("URI") >= 0: |
| 1006 classes.write( |
| 1007 " if ret is None:raise uriError('%s() failed')\n" |
| 1008 % (name)) |
| 1009 elif name.find("XPath") >= 0: |
| 1010 classes.write( |
| 1011 " if ret is None:raise xpathError('%s() failed')\n" |
| 1012 % (name)) |
| 1013 elif name.find("Parse") >= 0: |
| 1014 classes.write( |
| 1015 " if ret is None:raise parserError('%s() failed')\n" |
| 1016 % (name)) |
| 1017 else: |
| 1018 classes.write( |
| 1019 " if ret is None:raise treeError('%s() failed')\n" |
| 1020 % (name)) |
| 1021 classes.write(" return ") |
| 1022 classes.write(classes_type[ret[0]][1] % ("ret")) |
| 1023 classes.write("\n") |
| 1024 else: |
| 1025 classes.write(" return ret\n") |
| 1026 classes.write("\n") |
| 1027 |
| 1028 txt.write("\n\n#\n# Set of classes of the module\n#\n\n") |
| 1029 for classname in classes_list: |
| 1030 if classname == "None": |
| 1031 pass |
| 1032 else: |
| 1033 if classname in classes_ancestor: |
| 1034 txt.write("\n\nClass %s(%s)\n" % (classname, |
| 1035 classes_ancestor[classname])) |
| 1036 classes.write("class %s(%s):\n" % (classname, |
| 1037 classes_ancestor[classname])) |
| 1038 classes.write(" def __init__(self, _obj=None):\n") |
| 1039 if classes_ancestor[classname] == "xmlCore" or \ |
| 1040 classes_ancestor[classname] == "xmlNode": |
| 1041 classes.write(" if checkWrapper(_obj) != 0:") |
| 1042 classes.write(" raise TypeError") |
| 1043 classes.write("('%s got a wrong wrapper object type')\n" % \ |
| 1044 classname) |
| 1045 if classname in reference_keepers: |
| 1046 rlist = reference_keepers[classname] |
| 1047 for ref in rlist: |
| 1048 classes.write(" self.%s = None\n" % ref[1]) |
| 1049 classes.write(" self._o = _obj\n") |
| 1050 classes.write(" %s.__init__(self, _obj=_obj)\n\n" % ( |
| 1051 classes_ancestor[classname])) |
| 1052 if classes_ancestor[classname] == "xmlCore" or \ |
| 1053 classes_ancestor[classname] == "xmlNode": |
| 1054 classes.write(" def __repr__(self):\n") |
| 1055 format = "<%s (%%s) object at 0x%%x>" % (classname) |
| 1056 classes.write(" return \"%s\" %% (self.name, int(pos_
id (self)))\n\n" % ( |
| 1057 format)) |
| 1058 else: |
| 1059 txt.write("Class %s()\n" % (classname)) |
| 1060 classes.write("class %s:\n" % (classname)) |
| 1061 classes.write(" def __init__(self, _obj=None):\n") |
| 1062 if classname in reference_keepers: |
| 1063 list = reference_keepers[classname] |
| 1064 for ref in list: |
| 1065 classes.write(" self.%s = None\n" % ref[1]) |
| 1066 classes.write(" if _obj != None:self._o = _obj;return\n") |
| 1067 classes.write(" self._o = None\n\n") |
| 1068 destruct=None |
| 1069 if classname in classes_destructors: |
| 1070 classes.write(" def __del__(self):\n") |
| 1071 classes.write(" if self._o != None:\n") |
| 1072 classes.write(" libxml2mod.%s(self._o)\n" % |
| 1073 classes_destructors[classname]) |
| 1074 classes.write(" self._o = None\n\n") |
| 1075 destruct=classes_destructors[classname] |
| 1076 flist = function_classes[classname] |
| 1077 flist = sorted(flist, key=cmp_to_key(functionCompare)) |
| 1078 oldfile = "" |
| 1079 for info in flist: |
| 1080 (index, func, name, ret, args, file) = info |
| 1081 # |
| 1082 # Do not provide as method the destructors for the class |
| 1083 # to avoid double free |
| 1084 # |
| 1085 if name == destruct: |
| 1086 continue |
| 1087 if file != oldfile: |
| 1088 if file == "python_accessor": |
| 1089 classes.write(" # accessors for %s\n" % (classname)) |
| 1090 txt.write(" # accessors\n") |
| 1091 else: |
| 1092 classes.write(" #\n") |
| 1093 classes.write(" # %s functions from module %s\n" % ( |
| 1094 classname, file)) |
| 1095 txt.write("\n # functions from module %s\n" % file) |
| 1096 classes.write(" #\n\n") |
| 1097 oldfile = file |
| 1098 classes.write(" def %s(self" % func) |
| 1099 txt.write(" %s()\n" % func) |
| 1100 n = 0 |
| 1101 for arg in args: |
| 1102 if n != index: |
| 1103 classes.write(", %s" % arg[0]) |
| 1104 n = n + 1 |
| 1105 classes.write("):\n") |
| 1106 writeDoc(name, args, ' ', classes) |
| 1107 n = 0 |
| 1108 for arg in args: |
| 1109 if arg[1] in classes_type: |
| 1110 if n != index: |
| 1111 classes.write(" if %s is None: %s__o = None\n
" % |
| 1112 (arg[0], arg[0])) |
| 1113 classes.write(" else: %s__o = %s%s\n" % |
| 1114 (arg[0], arg[0], classes_type[arg[1]][
0])) |
| 1115 n = n + 1 |
| 1116 if ret[0] != "void": |
| 1117 classes.write(" ret = ") |
| 1118 else: |
| 1119 classes.write(" ") |
| 1120 classes.write("libxml2mod.%s(" % name) |
| 1121 n = 0 |
| 1122 for arg in args: |
| 1123 if n != 0: |
| 1124 classes.write(", ") |
| 1125 if n != index: |
| 1126 classes.write("%s" % arg[0]) |
| 1127 if arg[1] in classes_type: |
| 1128 classes.write("__o") |
| 1129 else: |
| 1130 classes.write("self") |
| 1131 if arg[1] in classes_type: |
| 1132 classes.write(classes_type[arg[1]][0]) |
| 1133 n = n + 1 |
| 1134 classes.write(")\n") |
| 1135 if ret[0] != "void": |
| 1136 if ret[0] in classes_type: |
| 1137 # |
| 1138 # Raise an exception |
| 1139 # |
| 1140 if name in functions_noexcept: |
| 1141 classes.write( |
| 1142 " if ret is None:return None\n") |
| 1143 elif name.find("URI") >= 0: |
| 1144 classes.write( |
| 1145 " if ret is None:raise uriError('%s() failed')\n" |
| 1146 % (name)) |
| 1147 elif name.find("XPath") >= 0: |
| 1148 classes.write( |
| 1149 " if ret is None:raise xpathError('%s() failed')\n" |
| 1150 % (name)) |
| 1151 elif name.find("Parse") >= 0: |
| 1152 classes.write( |
| 1153 " if ret is None:raise parserError('%s() failed')\n" |
| 1154 % (name)) |
| 1155 else: |
| 1156 classes.write( |
| 1157 " if ret is None:raise treeError('%s() failed')\n" |
| 1158 % (name)) |
| 1159 |
| 1160 # |
| 1161 # generate the returned class wrapper for the object |
| 1162 # |
| 1163 classes.write(" __tmp = ") |
| 1164 classes.write(classes_type[ret[0]][1] % ("ret")) |
| 1165 classes.write("\n") |
| 1166 |
| 1167 # |
| 1168 # Sometime one need to keep references of the source |
| 1169 # class in the returned class object. |
| 1170 # See reference_keepers for the list |
| 1171 # |
| 1172 tclass = classes_type[ret[0]][2] |
| 1173 if tclass in reference_keepers: |
| 1174 list = reference_keepers[tclass] |
| 1175 for pref in list: |
| 1176 if pref[0] == classname: |
| 1177 classes.write(" __tmp.%s = self\n" % |
| 1178 pref[1]) |
| 1179 # |
| 1180 # return the class |
| 1181 # |
| 1182 classes.write(" return __tmp\n") |
| 1183 elif ret[0] in converter_type: |
| 1184 # |
| 1185 # Raise an exception |
| 1186 # |
| 1187 if name in functions_noexcept: |
| 1188 classes.write( |
| 1189 " if ret is None:return None") |
| 1190 elif name.find("URI") >= 0: |
| 1191 classes.write( |
| 1192 " if ret is None:raise uriError('%s() failed')\n" |
| 1193 % (name)) |
| 1194 elif name.find("XPath") >= 0: |
| 1195 classes.write( |
| 1196 " if ret is None:raise xpathError('%s() failed')\n" |
| 1197 % (name)) |
| 1198 elif name.find("Parse") >= 0: |
| 1199 classes.write( |
| 1200 " if ret is None:raise parserError('%s() failed')\n" |
| 1201 % (name)) |
| 1202 else: |
| 1203 classes.write( |
| 1204 " if ret is None:raise treeError('%s() failed')\n" |
| 1205 % (name)) |
| 1206 classes.write(" return ") |
| 1207 classes.write(converter_type[ret[0]] % ("ret")) |
| 1208 classes.write("\n") |
| 1209 else: |
| 1210 classes.write(" return ret\n") |
| 1211 classes.write("\n") |
| 1212 |
| 1213 # |
| 1214 # Generate enum constants |
| 1215 # |
| 1216 for type,enum in enums.items(): |
| 1217 classes.write("# %s\n" % type) |
| 1218 items = enum.items() |
| 1219 items = sorted(items, key=(lambda i: int(i[1]))) |
| 1220 for name,value in items: |
| 1221 classes.write("%s = %s\n" % (name,value)) |
| 1222 classes.write("\n") |
| 1223 |
| 1224 txt.close() |
| 1225 classes.close() |
| 1226 |
| 1227 buildStubs() |
| 1228 buildWrappers() |
OLD | NEW |