Annotation of embedaddon/libxml2/python/generator.py, revision 1.1
1.1 ! misho 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 attrs.has_key('name'):
! 73: self.function = attrs['name']
! 74: if attrs.has_key('file'):
! 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 attrs.has_key('name'):
! 86: self.function_arg_name = attrs['name']
! 87: if attrs.has_key('type'):
! 88: self.function_arg_type = attrs['type']
! 89: if attrs.has_key('info'):
! 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 attrs.has_key('type'):
! 97: self.function_return_type = attrs['type']
! 98: if attrs.has_key('info'):
! 99: self.function_return_info = attrs['info']
! 100: if attrs.has_key('field'):
! 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 not enums.has_key(type):
! 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", "xmlAttributePtr"),
! 214: 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
! 215: 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
! 216: 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"),
! 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", "xmlXPathContextPtr"),
! 234: 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"),
! 235: 'xmlXPathParserContextPtr': ('O', "xmlXPathParserContext", "xmlXPathParserContextPtr", "xmlXPathParserContextPtr"),
! 236: 'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
! 237: 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
! 238: 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
! 239: 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"),
! 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", "xmlOutputBufferPtr"),
! 246: 'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"),
! 247: 'xmlRegexpPtr': ('O', "xmlReg", "xmlRegexpPtr", "xmlRegexpPtr"),
! 248: 'xmlTextReaderLocatorPtr': ('O', "xmlTextReaderLocator", "xmlTextReaderLocatorPtr", "xmlTextReaderLocatorPtr"),
! 249: 'xmlTextReaderPtr': ('O', "xmlTextReader", "xmlTextReaderPtr", "xmlTextReaderPtr"),
! 250: 'xmlRelaxNGPtr': ('O', "relaxNgSchema", "xmlRelaxNGPtr", "xmlRelaxNGPtr"),
! 251: 'xmlRelaxNGParserCtxtPtr': ('O', "relaxNgParserCtxt", "xmlRelaxNGParserCtxtPtr", "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:
! 343: return 0
! 344:
! 345: def print_function_wrapper(name, output, export, include):
! 346: global py_types
! 347: global unknown_types
! 348: global functions
! 349: global skipped_modules
! 350:
! 351: try:
! 352: (desc, ret, args, file, cond) = functions[name]
! 353: except:
! 354: print "failed to get function %s infos"
! 355: return
! 356:
! 357: if skipped_modules.has_key(file):
! 358: return 0
! 359: if skip_function(name) == 1:
! 360: return 0
! 361: if name in skip_impl:
! 362: # Don't delete the function entry in the caller.
! 363: return 1
! 364:
! 365: c_call = ""
! 366: format=""
! 367: format_args=""
! 368: c_args=""
! 369: c_return=""
! 370: c_convert=""
! 371: num_bufs=0
! 372: for arg in args:
! 373: # This should be correct
! 374: if arg[1][0:6] == "const ":
! 375: arg[1] = arg[1][6:]
! 376: c_args = c_args + " %s %s;\n" % (arg[1], arg[0])
! 377: if py_types.has_key(arg[1]):
! 378: (f, t, n, c) = py_types[arg[1]]
! 379: if (f == 'z') and (name in foreign_encoding_args) and (num_bufs == 0):
! 380: f = 't#'
! 381: if f != None:
! 382: format = format + f
! 383: if t != None:
! 384: format_args = format_args + ", &pyobj_%s" % (arg[0])
! 385: c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0])
! 386: c_convert = c_convert + \
! 387: " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0],
! 388: arg[1], t, arg[0])
! 389: else:
! 390: format_args = format_args + ", &%s" % (arg[0])
! 391: if f == 't#':
! 392: format_args = format_args + ", &py_buffsize%d" % num_bufs
! 393: c_args = c_args + " int py_buffsize%d;\n" % num_bufs
! 394: num_bufs = num_bufs + 1
! 395: if c_call != "":
! 396: c_call = c_call + ", "
! 397: c_call = c_call + "%s" % (arg[0])
! 398: else:
! 399: if skipped_types.has_key(arg[1]):
! 400: return 0
! 401: if unknown_types.has_key(arg[1]):
! 402: lst = unknown_types[arg[1]]
! 403: lst.append(name)
! 404: else:
! 405: unknown_types[arg[1]] = [name]
! 406: return -1
! 407: if format != "":
! 408: format = format + ":%s" % (name)
! 409:
! 410: if ret[0] == 'void':
! 411: if file == "python_accessor":
! 412: if args[1][1] == "char *" or args[1][1] == "xmlChar *":
! 413: c_call = "\n if (%s->%s != NULL) xmlFree(%s->%s);\n" % (
! 414: args[0][0], args[1][0], args[0][0], args[1][0])
! 415: c_call = c_call + " %s->%s = (%s)xmlStrdup((const xmlChar *)%s);\n" % (args[0][0],
! 416: args[1][0], args[1][1], args[1][0])
! 417: else:
! 418: c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0],
! 419: args[1][0])
! 420: else:
! 421: c_call = "\n %s(%s);\n" % (name, c_call)
! 422: ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n"
! 423: elif py_types.has_key(ret[0]):
! 424: (f, t, n, c) = py_types[ret[0]]
! 425: c_return = " %s c_retval;\n" % (ret[0])
! 426: if file == "python_accessor" and ret[2] != None:
! 427: c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2])
! 428: else:
! 429: c_call = "\n c_retval = %s(%s);\n" % (name, c_call)
! 430: ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c)
! 431: ret_convert = ret_convert + " return(py_retval);\n"
! 432: elif py_return_types.has_key(ret[0]):
! 433: (f, t, n, c) = py_return_types[ret[0]]
! 434: c_return = " %s c_retval;\n" % (ret[0])
! 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: else:
! 439: if skipped_types.has_key(ret[0]):
! 440: return 0
! 441: if unknown_types.has_key(ret[0]):
! 442: lst = unknown_types[ret[0]]
! 443: lst.append(name)
! 444: else:
! 445: unknown_types[ret[0]] = [name]
! 446: return -1
! 447:
! 448: if cond != None and cond != "":
! 449: include.write("#if %s\n" % cond)
! 450: export.write("#if %s\n" % cond)
! 451: output.write("#if %s\n" % cond)
! 452:
! 453: include.write("PyObject * ")
! 454: include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name))
! 455:
! 456: export.write(" { (char *)\"%s\", libxml_%s, METH_VARARGS, NULL },\n" %
! 457: (name, name))
! 458:
! 459: if file == "python":
! 460: # Those have been manually generated
! 461: if cond != None and cond != "":
! 462: include.write("#endif\n")
! 463: export.write("#endif\n")
! 464: output.write("#endif\n")
! 465: return 1
! 466: if file == "python_accessor" and ret[0] != "void" and ret[2] is None:
! 467: # Those have been manually generated
! 468: if cond != None and cond != "":
! 469: include.write("#endif\n")
! 470: export.write("#endif\n")
! 471: output.write("#endif\n")
! 472: return 1
! 473:
! 474: output.write("PyObject *\n")
! 475: output.write("libxml_%s(PyObject *self ATTRIBUTE_UNUSED," % (name))
! 476: output.write(" PyObject *args")
! 477: if format == "":
! 478: output.write(" ATTRIBUTE_UNUSED")
! 479: output.write(") {\n")
! 480: if ret[0] != 'void':
! 481: output.write(" PyObject *py_retval;\n")
! 482: if c_return != "":
! 483: output.write(c_return)
! 484: if c_args != "":
! 485: output.write(c_args)
! 486: if format != "":
! 487: output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" %
! 488: (format, format_args))
! 489: output.write(" return(NULL);\n")
! 490: if c_convert != "":
! 491: output.write(c_convert)
! 492:
! 493: output.write(c_call)
! 494: output.write(ret_convert)
! 495: output.write("}\n\n")
! 496: if cond != None and cond != "":
! 497: include.write("#endif /* %s */\n" % cond)
! 498: export.write("#endif /* %s */\n" % cond)
! 499: output.write("#endif /* %s */\n" % cond)
! 500: return 1
! 501:
! 502: def buildStubs():
! 503: global py_types
! 504: global py_return_types
! 505: global unknown_types
! 506:
! 507: try:
! 508: f = open(os.path.join(srcPref,"libxml2-api.xml"))
! 509: data = f.read()
! 510: (parser, target) = getparser()
! 511: parser.feed(data)
! 512: parser.close()
! 513: except IOError, msg:
! 514: try:
! 515: f = open(os.path.join(srcPref,"..","doc","libxml2-api.xml"))
! 516: data = f.read()
! 517: (parser, target) = getparser()
! 518: parser.feed(data)
! 519: parser.close()
! 520: except IOError, msg:
! 521: print file, ":", msg
! 522: sys.exit(1)
! 523:
! 524: n = len(functions.keys())
! 525: print "Found %d functions in libxml2-api.xml" % (n)
! 526:
! 527: py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject")
! 528: try:
! 529: f = open(os.path.join(srcPref,"libxml2-python-api.xml"))
! 530: data = f.read()
! 531: (parser, target) = getparser()
! 532: parser.feed(data)
! 533: parser.close()
! 534: except IOError, msg:
! 535: print file, ":", msg
! 536:
! 537:
! 538: print "Found %d functions in libxml2-python-api.xml" % (
! 539: len(functions.keys()) - n)
! 540: nb_wrap = 0
! 541: failed = 0
! 542: skipped = 0
! 543:
! 544: include = open("libxml2-py.h", "w")
! 545: include.write("/* Generated */\n\n")
! 546: export = open("libxml2-export.c", "w")
! 547: export.write("/* Generated */\n\n")
! 548: wrapper = open("libxml2-py.c", "w")
! 549: wrapper.write("/* Generated */\n\n")
! 550: wrapper.write("#include <Python.h>\n")
! 551: wrapper.write("#include <libxml/xmlversion.h>\n")
! 552: wrapper.write("#include <libxml/tree.h>\n")
! 553: wrapper.write("#include <libxml/xmlschemastypes.h>\n")
! 554: wrapper.write("#include \"libxml_wrap.h\"\n")
! 555: wrapper.write("#include \"libxml2-py.h\"\n\n")
! 556: for function in sorted(functions.keys()):
! 557: ret = print_function_wrapper(function, wrapper, export, include)
! 558: if ret < 0:
! 559: failed = failed + 1
! 560: del functions[function]
! 561: if ret == 0:
! 562: skipped = skipped + 1
! 563: del functions[function]
! 564: if ret == 1:
! 565: nb_wrap = nb_wrap + 1
! 566: include.close()
! 567: export.close()
! 568: wrapper.close()
! 569:
! 570: print "Generated %d wrapper functions, %d failed, %d skipped\n" % (nb_wrap,
! 571: failed, skipped)
! 572: print "Missing type converters: "
! 573: for type in unknown_types.keys():
! 574: print "%s:%d " % (type, len(unknown_types[type])),
! 575: print
! 576:
! 577: #######################################################################
! 578: #
! 579: # This part writes part of the Python front-end classes based on
! 580: # mapping rules between types and classes and also based on function
! 581: # renaming to get consistent function names at the Python level
! 582: #
! 583: #######################################################################
! 584:
! 585: #
! 586: # The type automatically remapped to generated classes
! 587: #
! 588: classes_type = {
! 589: "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
! 590: "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"),
! 591: "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
! 592: "xmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
! 593: "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
! 594: "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"),
! 595: "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
! 596: "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"),
! 597: "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
! 598: "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"),
! 599: "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
! 600: "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"),
! 601: "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
! 602: "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"),
! 603: "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
! 604: "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"),
! 605: "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
! 606: "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"),
! 607: "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
! 608: "xmlXPathContext *": ("._o", "xpathContext(_obj=%s)", "xpathContext"),
! 609: "xmlXPathParserContext *": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"),
! 610: "xmlXPathParserContextPtr": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"),
! 611: "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
! 612: "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
! 613: "htmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
! 614: "htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"),
! 615: "xmlValidCtxtPtr": ("._o", "ValidCtxt(_obj=%s)", "ValidCtxt"),
! 616: "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"),
! 617: "xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"),
! 618: "xmlErrorPtr": ("._o", "Error(_obj=%s)", "Error"),
! 619: "xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"),
! 620: "xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"),
! 621: "xmlRegexpPtr": ("._o", "xmlReg(_obj=%s)", "xmlReg"),
! 622: "xmlTextReaderLocatorPtr": ("._o", "xmlTextReaderLocator(_obj=%s)", "xmlTextReaderLocator"),
! 623: "xmlTextReaderPtr": ("._o", "xmlTextReader(_obj=%s)", "xmlTextReader"),
! 624: 'xmlRelaxNGPtr': ('._o', "relaxNgSchema(_obj=%s)", "relaxNgSchema"),
! 625: 'xmlRelaxNGParserCtxtPtr': ('._o', "relaxNgParserCtxt(_obj=%s)", "relaxNgParserCtxt"),
! 626: 'xmlRelaxNGValidCtxtPtr': ('._o', "relaxNgValidCtxt(_obj=%s)", "relaxNgValidCtxt"),
! 627: 'xmlSchemaPtr': ("._o", "Schema(_obj=%s)", "Schema"),
! 628: 'xmlSchemaParserCtxtPtr': ("._o", "SchemaParserCtxt(_obj=%s)", "SchemaParserCtxt"),
! 629: 'xmlSchemaValidCtxtPtr': ("._o", "SchemaValidCtxt(_obj=%s)", "SchemaValidCtxt"),
! 630: }
! 631:
! 632: converter_type = {
! 633: "xmlXPathObjectPtr": "xpathObjectRet(%s)",
! 634: }
! 635:
! 636: primary_classes = ["xmlNode", "xmlDoc"]
! 637:
! 638: classes_ancestor = {
! 639: "xmlNode" : "xmlCore",
! 640: "xmlDtd" : "xmlNode",
! 641: "xmlDoc" : "xmlNode",
! 642: "xmlAttr" : "xmlNode",
! 643: "xmlNs" : "xmlNode",
! 644: "xmlEntity" : "xmlNode",
! 645: "xmlElement" : "xmlNode",
! 646: "xmlAttribute" : "xmlNode",
! 647: "outputBuffer": "ioWriteWrapper",
! 648: "inputBuffer": "ioReadWrapper",
! 649: "parserCtxt": "parserCtxtCore",
! 650: "xmlTextReader": "xmlTextReaderCore",
! 651: "ValidCtxt": "ValidCtxtCore",
! 652: "SchemaValidCtxt": "SchemaValidCtxtCore",
! 653: "relaxNgValidCtxt": "relaxNgValidCtxtCore",
! 654: }
! 655: classes_destructors = {
! 656: "parserCtxt": "xmlFreeParserCtxt",
! 657: "catalog": "xmlFreeCatalog",
! 658: "URI": "xmlFreeURI",
! 659: # "outputBuffer": "xmlOutputBufferClose",
! 660: "inputBuffer": "xmlFreeParserInputBuffer",
! 661: "xmlReg": "xmlRegFreeRegexp",
! 662: "xmlTextReader": "xmlFreeTextReader",
! 663: "relaxNgSchema": "xmlRelaxNGFree",
! 664: "relaxNgParserCtxt": "xmlRelaxNGFreeParserCtxt",
! 665: "relaxNgValidCtxt": "xmlRelaxNGFreeValidCtxt",
! 666: "Schema": "xmlSchemaFree",
! 667: "SchemaParserCtxt": "xmlSchemaFreeParserCtxt",
! 668: "SchemaValidCtxt": "xmlSchemaFreeValidCtxt",
! 669: "ValidCtxt": "xmlFreeValidCtxt",
! 670: }
! 671:
! 672: functions_noexcept = {
! 673: "xmlHasProp": 1,
! 674: "xmlHasNsProp": 1,
! 675: "xmlDocSetRootElement": 1,
! 676: "xmlNodeGetNs": 1,
! 677: "xmlNodeGetNsDefs": 1,
! 678: "xmlNextElementSibling": 1,
! 679: "xmlPreviousElementSibling": 1,
! 680: "xmlFirstElementChild": 1,
! 681: "xmlLastElementChild": 1,
! 682: }
! 683:
! 684: reference_keepers = {
! 685: "xmlTextReader": [('inputBuffer', 'input')],
! 686: "relaxNgValidCtxt": [('relaxNgSchema', 'schema')],
! 687: "SchemaValidCtxt": [('Schema', 'schema')],
! 688: }
! 689:
! 690: function_classes = {}
! 691:
! 692: function_classes["None"] = []
! 693:
! 694: def nameFixup(name, classe, type, file):
! 695: listname = classe + "List"
! 696: ll = len(listname)
! 697: l = len(classe)
! 698: if name[0:l] == listname:
! 699: func = name[l:]
! 700: func = string.lower(func[0:1]) + func[1:]
! 701: elif name[0:12] == "xmlParserGet" and file == "python_accessor":
! 702: func = name[12:]
! 703: func = string.lower(func[0:1]) + func[1:]
! 704: elif name[0:12] == "xmlParserSet" and file == "python_accessor":
! 705: func = name[12:]
! 706: func = string.lower(func[0:1]) + func[1:]
! 707: elif name[0:10] == "xmlNodeGet" and file == "python_accessor":
! 708: func = name[10:]
! 709: func = string.lower(func[0:1]) + func[1:]
! 710: elif name[0:9] == "xmlURIGet" and file == "python_accessor":
! 711: func = name[9:]
! 712: func = string.lower(func[0:1]) + func[1:]
! 713: elif name[0:9] == "xmlURISet" and file == "python_accessor":
! 714: func = name[6:]
! 715: func = string.lower(func[0:1]) + func[1:]
! 716: elif name[0:11] == "xmlErrorGet" and file == "python_accessor":
! 717: func = name[11:]
! 718: func = string.lower(func[0:1]) + func[1:]
! 719: elif name[0:17] == "xmlXPathParserGet" and file == "python_accessor":
! 720: func = name[17:]
! 721: func = string.lower(func[0:1]) + func[1:]
! 722: elif name[0:11] == "xmlXPathGet" and file == "python_accessor":
! 723: func = name[11:]
! 724: func = string.lower(func[0:1]) + func[1:]
! 725: elif name[0:11] == "xmlXPathSet" and file == "python_accessor":
! 726: func = name[8:]
! 727: func = string.lower(func[0:1]) + func[1:]
! 728: elif name[0:15] == "xmlOutputBuffer" and file != "python":
! 729: func = name[15:]
! 730: func = string.lower(func[0:1]) + func[1:]
! 731: elif name[0:20] == "xmlParserInputBuffer" and file != "python":
! 732: func = name[20:]
! 733: func = string.lower(func[0:1]) + func[1:]
! 734: elif name[0:9] == "xmlRegexp" and file == "xmlregexp":
! 735: func = "regexp" + name[9:]
! 736: elif name[0:6] == "xmlReg" and file == "xmlregexp":
! 737: func = "regexp" + name[6:]
! 738: elif name[0:20] == "xmlTextReaderLocator" and file == "xmlreader":
! 739: func = name[20:]
! 740: elif name[0:18] == "xmlTextReaderConst" and file == "xmlreader":
! 741: func = name[18:]
! 742: elif name[0:13] == "xmlTextReader" and file == "xmlreader":
! 743: func = name[13:]
! 744: elif name[0:12] == "xmlReaderNew" and file == "xmlreader":
! 745: func = name[9:]
! 746: elif name[0:11] == "xmlACatalog":
! 747: func = name[11:]
! 748: func = string.lower(func[0:1]) + func[1:]
! 749: elif name[0:l] == classe:
! 750: func = name[l:]
! 751: func = string.lower(func[0:1]) + func[1:]
! 752: elif name[0:7] == "libxml_":
! 753: func = name[7:]
! 754: func = string.lower(func[0:1]) + func[1:]
! 755: elif name[0:6] == "xmlGet":
! 756: func = name[6:]
! 757: func = string.lower(func[0:1]) + func[1:]
! 758: elif name[0:3] == "xml":
! 759: func = name[3:]
! 760: func = string.lower(func[0:1]) + func[1:]
! 761: else:
! 762: func = name
! 763: if func[0:5] == "xPath":
! 764: func = "xpath" + func[5:]
! 765: elif func[0:4] == "xPtr":
! 766: func = "xpointer" + func[4:]
! 767: elif func[0:8] == "xInclude":
! 768: func = "xinclude" + func[8:]
! 769: elif func[0:2] == "iD":
! 770: func = "ID" + func[2:]
! 771: elif func[0:3] == "uRI":
! 772: func = "URI" + func[3:]
! 773: elif func[0:4] == "uTF8":
! 774: func = "UTF8" + func[4:]
! 775: elif func[0:3] == 'sAX':
! 776: func = "SAX" + func[3:]
! 777: return func
! 778:
! 779:
! 780: def functionCompare(info1, info2):
! 781: (index1, func1, name1, ret1, args1, file1) = info1
! 782: (index2, func2, name2, ret2, args2, file2) = info2
! 783: if file1 == file2:
! 784: if func1 < func2:
! 785: return -1
! 786: if func1 > func2:
! 787: return 1
! 788: if file1 == "python_accessor":
! 789: return -1
! 790: if file2 == "python_accessor":
! 791: return 1
! 792: if file1 < file2:
! 793: return -1
! 794: if file1 > file2:
! 795: return 1
! 796: return 0
! 797:
! 798: def writeDoc(name, args, indent, output):
! 799: if functions[name][0] is None or functions[name][0] == "":
! 800: return
! 801: val = functions[name][0]
! 802: val = string.replace(val, "NULL", "None")
! 803: output.write(indent)
! 804: output.write('"""')
! 805: while len(val) > 60:
! 806: if val[0] == " ":
! 807: val = val[1:]
! 808: continue
! 809: str = val[0:60]
! 810: i = string.rfind(str, " ")
! 811: if i < 0:
! 812: i = 60
! 813: str = val[0:i]
! 814: val = val[i:]
! 815: output.write(str)
! 816: output.write('\n ')
! 817: output.write(indent)
! 818: output.write(val)
! 819: output.write(' """\n')
! 820:
! 821: def buildWrappers():
! 822: global ctypes
! 823: global py_types
! 824: global py_return_types
! 825: global unknown_types
! 826: global functions
! 827: global function_classes
! 828: global classes_type
! 829: global classes_list
! 830: global converter_type
! 831: global primary_classes
! 832: global converter_type
! 833: global classes_ancestor
! 834: global converter_type
! 835: global primary_classes
! 836: global classes_ancestor
! 837: global classes_destructors
! 838: global functions_noexcept
! 839:
! 840: for type in classes_type.keys():
! 841: function_classes[classes_type[type][2]] = []
! 842:
! 843: #
! 844: # Build the list of C types to look for ordered to start
! 845: # with primary classes
! 846: #
! 847: ctypes = []
! 848: classes_list = []
! 849: ctypes_processed = {}
! 850: classes_processed = {}
! 851: for classe in primary_classes:
! 852: classes_list.append(classe)
! 853: classes_processed[classe] = ()
! 854: for type in classes_type.keys():
! 855: tinfo = classes_type[type]
! 856: if tinfo[2] == classe:
! 857: ctypes.append(type)
! 858: ctypes_processed[type] = ()
! 859: for type in sorted(classes_type.keys()):
! 860: if ctypes_processed.has_key(type):
! 861: continue
! 862: tinfo = classes_type[type]
! 863: if not classes_processed.has_key(tinfo[2]):
! 864: classes_list.append(tinfo[2])
! 865: classes_processed[tinfo[2]] = ()
! 866:
! 867: ctypes.append(type)
! 868: ctypes_processed[type] = ()
! 869:
! 870: for name in functions.keys():
! 871: found = 0
! 872: (desc, ret, args, file, cond) = functions[name]
! 873: for type in ctypes:
! 874: classe = classes_type[type][2]
! 875:
! 876: if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type:
! 877: found = 1
! 878: func = nameFixup(name, classe, type, file)
! 879: info = (0, func, name, ret, args, file)
! 880: function_classes[classe].append(info)
! 881: elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type \
! 882: and file != "python_accessor":
! 883: found = 1
! 884: func = nameFixup(name, classe, type, file)
! 885: info = (1, func, name, ret, args, file)
! 886: function_classes[classe].append(info)
! 887: elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type:
! 888: found = 1
! 889: func = nameFixup(name, classe, type, file)
! 890: info = (0, func, name, ret, args, file)
! 891: function_classes[classe].append(info)
! 892: elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type \
! 893: and file != "python_accessor":
! 894: found = 1
! 895: func = nameFixup(name, classe, type, file)
! 896: info = (1, func, name, ret, args, file)
! 897: function_classes[classe].append(info)
! 898: if found == 1:
! 899: continue
! 900: if name[0:8] == "xmlXPath":
! 901: continue
! 902: if name[0:6] == "xmlStr":
! 903: continue
! 904: if name[0:10] == "xmlCharStr":
! 905: continue
! 906: func = nameFixup(name, "None", file, file)
! 907: info = (0, func, name, ret, args, file)
! 908: function_classes['None'].append(info)
! 909:
! 910: classes = open("libxml2class.py", "w")
! 911: txt = open("libxml2class.txt", "w")
! 912: txt.write(" Generated Classes for libxml2-python\n\n")
! 913:
! 914: txt.write("#\n# Global functions of the module\n#\n\n")
! 915: if function_classes.has_key("None"):
! 916: flist = function_classes["None"]
! 917: flist.sort(functionCompare)
! 918: oldfile = ""
! 919: for info in flist:
! 920: (index, func, name, ret, args, file) = info
! 921: if file != oldfile:
! 922: classes.write("#\n# Functions from module %s\n#\n\n" % file)
! 923: txt.write("\n# functions from module %s\n" % file)
! 924: oldfile = file
! 925: classes.write("def %s(" % func)
! 926: txt.write("%s()\n" % func)
! 927: n = 0
! 928: for arg in args:
! 929: if n != 0:
! 930: classes.write(", ")
! 931: classes.write("%s" % arg[0])
! 932: n = n + 1
! 933: classes.write("):\n")
! 934: writeDoc(name, args, ' ', classes)
! 935:
! 936: for arg in args:
! 937: if classes_type.has_key(arg[1]):
! 938: classes.write(" if %s is None: %s__o = None\n" %
! 939: (arg[0], arg[0]))
! 940: classes.write(" else: %s__o = %s%s\n" %
! 941: (arg[0], arg[0], classes_type[arg[1]][0]))
! 942: if ret[0] != "void":
! 943: classes.write(" ret = ")
! 944: else:
! 945: classes.write(" ")
! 946: classes.write("libxml2mod.%s(" % name)
! 947: n = 0
! 948: for arg in args:
! 949: if n != 0:
! 950: classes.write(", ")
! 951: classes.write("%s" % arg[0])
! 952: if classes_type.has_key(arg[1]):
! 953: classes.write("__o")
! 954: n = n + 1
! 955: classes.write(")\n")
! 956: if ret[0] != "void":
! 957: if classes_type.has_key(ret[0]):
! 958: #
! 959: # Raise an exception
! 960: #
! 961: if functions_noexcept.has_key(name):
! 962: classes.write(" if ret is None:return None\n")
! 963: elif string.find(name, "URI") >= 0:
! 964: classes.write(
! 965: " if ret is None:raise uriError('%s() failed')\n"
! 966: % (name))
! 967: elif string.find(name, "XPath") >= 0:
! 968: classes.write(
! 969: " if ret is None:raise xpathError('%s() failed')\n"
! 970: % (name))
! 971: elif string.find(name, "Parse") >= 0:
! 972: classes.write(
! 973: " if ret is None:raise parserError('%s() failed')\n"
! 974: % (name))
! 975: else:
! 976: classes.write(
! 977: " if ret is None:raise treeError('%s() failed')\n"
! 978: % (name))
! 979: classes.write(" return ")
! 980: classes.write(classes_type[ret[0]][1] % ("ret"))
! 981: classes.write("\n")
! 982: else:
! 983: classes.write(" return ret\n")
! 984: classes.write("\n")
! 985:
! 986: txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
! 987: for classname in classes_list:
! 988: if classname == "None":
! 989: pass
! 990: else:
! 991: if classes_ancestor.has_key(classname):
! 992: txt.write("\n\nClass %s(%s)\n" % (classname,
! 993: classes_ancestor[classname]))
! 994: classes.write("class %s(%s):\n" % (classname,
! 995: classes_ancestor[classname]))
! 996: classes.write(" def __init__(self, _obj=None):\n")
! 997: if classes_ancestor[classname] == "xmlCore" or \
! 998: classes_ancestor[classname] == "xmlNode":
! 999: classes.write(" if type(_obj).__name__ != ")
! 1000: classes.write("'PyCObject':\n")
! 1001: classes.write(" raise TypeError, ")
! 1002: classes.write("'%s needs a PyCObject argument'\n" % \
! 1003: classname)
! 1004: if reference_keepers.has_key(classname):
! 1005: rlist = reference_keepers[classname]
! 1006: for ref in rlist:
! 1007: classes.write(" self.%s = None\n" % ref[1])
! 1008: classes.write(" self._o = _obj\n")
! 1009: classes.write(" %s.__init__(self, _obj=_obj)\n\n" % (
! 1010: classes_ancestor[classname]))
! 1011: if classes_ancestor[classname] == "xmlCore" or \
! 1012: classes_ancestor[classname] == "xmlNode":
! 1013: classes.write(" def __repr__(self):\n")
! 1014: format = "<%s (%%s) object at 0x%%x>" % (classname)
! 1015: classes.write(" return \"%s\" %% (self.name, long(pos_id (self)))\n\n" % (
! 1016: format))
! 1017: else:
! 1018: txt.write("Class %s()\n" % (classname))
! 1019: classes.write("class %s:\n" % (classname))
! 1020: classes.write(" def __init__(self, _obj=None):\n")
! 1021: if reference_keepers.has_key(classname):
! 1022: list = reference_keepers[classname]
! 1023: for ref in list:
! 1024: classes.write(" self.%s = None\n" % ref[1])
! 1025: classes.write(" if _obj != None:self._o = _obj;return\n")
! 1026: classes.write(" self._o = None\n\n")
! 1027: destruct=None
! 1028: if classes_destructors.has_key(classname):
! 1029: classes.write(" def __del__(self):\n")
! 1030: classes.write(" if self._o != None:\n")
! 1031: classes.write(" libxml2mod.%s(self._o)\n" %
! 1032: classes_destructors[classname])
! 1033: classes.write(" self._o = None\n\n")
! 1034: destruct=classes_destructors[classname]
! 1035: flist = function_classes[classname]
! 1036: flist.sort(functionCompare)
! 1037: oldfile = ""
! 1038: for info in flist:
! 1039: (index, func, name, ret, args, file) = info
! 1040: #
! 1041: # Do not provide as method the destructors for the class
! 1042: # to avoid double free
! 1043: #
! 1044: if name == destruct:
! 1045: continue
! 1046: if file != oldfile:
! 1047: if file == "python_accessor":
! 1048: classes.write(" # accessors for %s\n" % (classname))
! 1049: txt.write(" # accessors\n")
! 1050: else:
! 1051: classes.write(" #\n")
! 1052: classes.write(" # %s functions from module %s\n" % (
! 1053: classname, file))
! 1054: txt.write("\n # functions from module %s\n" % file)
! 1055: classes.write(" #\n\n")
! 1056: oldfile = file
! 1057: classes.write(" def %s(self" % func)
! 1058: txt.write(" %s()\n" % func)
! 1059: n = 0
! 1060: for arg in args:
! 1061: if n != index:
! 1062: classes.write(", %s" % arg[0])
! 1063: n = n + 1
! 1064: classes.write("):\n")
! 1065: writeDoc(name, args, ' ', classes)
! 1066: n = 0
! 1067: for arg in args:
! 1068: if classes_type.has_key(arg[1]):
! 1069: if n != index:
! 1070: classes.write(" if %s is None: %s__o = None\n" %
! 1071: (arg[0], arg[0]))
! 1072: classes.write(" else: %s__o = %s%s\n" %
! 1073: (arg[0], arg[0], classes_type[arg[1]][0]))
! 1074: n = n + 1
! 1075: if ret[0] != "void":
! 1076: classes.write(" ret = ")
! 1077: else:
! 1078: classes.write(" ")
! 1079: classes.write("libxml2mod.%s(" % name)
! 1080: n = 0
! 1081: for arg in args:
! 1082: if n != 0:
! 1083: classes.write(", ")
! 1084: if n != index:
! 1085: classes.write("%s" % arg[0])
! 1086: if classes_type.has_key(arg[1]):
! 1087: classes.write("__o")
! 1088: else:
! 1089: classes.write("self")
! 1090: if classes_type.has_key(arg[1]):
! 1091: classes.write(classes_type[arg[1]][0])
! 1092: n = n + 1
! 1093: classes.write(")\n")
! 1094: if ret[0] != "void":
! 1095: if classes_type.has_key(ret[0]):
! 1096: #
! 1097: # Raise an exception
! 1098: #
! 1099: if functions_noexcept.has_key(name):
! 1100: classes.write(
! 1101: " if ret is None:return None\n")
! 1102: elif string.find(name, "URI") >= 0:
! 1103: classes.write(
! 1104: " if ret is None:raise uriError('%s() failed')\n"
! 1105: % (name))
! 1106: elif string.find(name, "XPath") >= 0:
! 1107: classes.write(
! 1108: " if ret is None:raise xpathError('%s() failed')\n"
! 1109: % (name))
! 1110: elif string.find(name, "Parse") >= 0:
! 1111: classes.write(
! 1112: " if ret is None:raise parserError('%s() failed')\n"
! 1113: % (name))
! 1114: else:
! 1115: classes.write(
! 1116: " if ret is None:raise treeError('%s() failed')\n"
! 1117: % (name))
! 1118:
! 1119: #
! 1120: # generate the returned class wrapper for the object
! 1121: #
! 1122: classes.write(" __tmp = ")
! 1123: classes.write(classes_type[ret[0]][1] % ("ret"))
! 1124: classes.write("\n")
! 1125:
! 1126: #
! 1127: # Sometime one need to keep references of the source
! 1128: # class in the returned class object.
! 1129: # See reference_keepers for the list
! 1130: #
! 1131: tclass = classes_type[ret[0]][2]
! 1132: if reference_keepers.has_key(tclass):
! 1133: list = reference_keepers[tclass]
! 1134: for pref in list:
! 1135: if pref[0] == classname:
! 1136: classes.write(" __tmp.%s = self\n" %
! 1137: pref[1])
! 1138: #
! 1139: # return the class
! 1140: #
! 1141: classes.write(" return __tmp\n")
! 1142: elif converter_type.has_key(ret[0]):
! 1143: #
! 1144: # Raise an exception
! 1145: #
! 1146: if functions_noexcept.has_key(name):
! 1147: classes.write(
! 1148: " if ret is None:return None")
! 1149: elif string.find(name, "URI") >= 0:
! 1150: classes.write(
! 1151: " if ret is None:raise uriError('%s() failed')\n"
! 1152: % (name))
! 1153: elif string.find(name, "XPath") >= 0:
! 1154: classes.write(
! 1155: " if ret is None:raise xpathError('%s() failed')\n"
! 1156: % (name))
! 1157: elif string.find(name, "Parse") >= 0:
! 1158: classes.write(
! 1159: " if ret is None:raise parserError('%s() failed')\n"
! 1160: % (name))
! 1161: else:
! 1162: classes.write(
! 1163: " if ret is None:raise treeError('%s() failed')\n"
! 1164: % (name))
! 1165: classes.write(" return ")
! 1166: classes.write(converter_type[ret[0]] % ("ret"))
! 1167: classes.write("\n")
! 1168: else:
! 1169: classes.write(" return ret\n")
! 1170: classes.write("\n")
! 1171:
! 1172: #
! 1173: # Generate enum constants
! 1174: #
! 1175: for type,enum in enums.items():
! 1176: classes.write("# %s\n" % type)
! 1177: items = enum.items()
! 1178: items.sort(lambda i1,i2: cmp(long(i1[1]),long(i2[1])))
! 1179: for name,value in items:
! 1180: classes.write("%s = %s\n" % (name,value))
! 1181: classes.write("\n")
! 1182:
! 1183: txt.close()
! 1184: classes.close()
! 1185:
! 1186: buildStubs()
! 1187: buildWrappers()
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>