| #!/usr/bin/env python3 | |
| # | |
| # generate python wrappers from the XML API description | |
| # | |
| functions = {} | |
| enums = {} # { enumType: { enumConstant: enumValue } } | |
| import os | |
| import sys | |
| import string | |
| if __name__ == "__main__": | |
| # launched as a script | |
| srcPref = os.path.dirname(sys.argv[0]) | |
| else: | |
| # imported | |
| srcPref = os.path.dirname(__file__) | |
| ####################################################################### | |
| # | |
| # That part if purely the API acquisition phase from the | |
| # XML API description | |
| # | |
| ####################################################################### | |
| import os | |
| import xml.sax | |
| debug = 0 | |
| def getparser(): | |
| # Attach parser to an unmarshalling object. return both objects. | |
| target = docParser() | |
| parser = xml.sax.make_parser() | |
| parser.setContentHandler(target) | |
| return parser, target | |
| class docParser(xml.sax.handler.ContentHandler): | |
| def __init__(self): | |
| self._methodname = None | |
| self._data = [] | |
| self.in_function = 0 | |
| self.startElement = self.start | |
| self.endElement = self.end | |
| self.characters = self.data | |
| def close(self): | |
| if debug: | |
| print("close") | |
| def getmethodname(self): | |
| return self._methodname | |
| def data(self, text): | |
| if debug: | |
| print("data %s" % text) | |
| self._data.append(text) | |
| def start(self, tag, attrs): | |
| if debug: | |
| print("start %s, %s" % (tag, attrs)) | |
| if tag == 'function': | |
| self._data = [] | |
| self.in_function = 1 | |
| self.function = None | |
| self.function_cond = None | |
| self.function_args = [] | |
| self.function_descr = None | |
| self.function_return = None | |
| self.function_file = None | |
| if 'name' in attrs.keys(): | |
| self.function = attrs['name'] | |
| if 'file' in attrs.keys(): | |
| self.function_file = attrs['file'] | |
| elif tag == 'cond': | |
| self._data = [] | |
| elif tag == 'info': | |
| self._data = [] | |
| elif tag == 'arg': | |
| if self.in_function == 1: | |
| self.function_arg_name = None | |
| self.function_arg_type = None | |
| self.function_arg_info = None | |
| if 'name' in attrs.keys(): | |
| self.function_arg_name = attrs['name'] | |
| if 'type' in attrs.keys(): | |
| self.function_arg_type = attrs['type'] | |
| if 'info' in attrs.keys(): | |
| self.function_arg_info = attrs['info'] | |
| elif tag == 'return': | |
| if self.in_function == 1: | |
| self.function_return_type = None | |
| self.function_return_info = None | |
| self.function_return_field = None | |
| if 'type' in attrs.keys(): | |
| self.function_return_type = attrs['type'] | |
| if 'info' in attrs.keys(): | |
| self.function_return_info = attrs['info'] | |
| if 'field' in attrs.keys(): | |
| self.function_return_field = attrs['field'] | |
| elif tag == 'enum': | |
| enum(attrs['type'],attrs['name'],attrs['value']) | |
| def end(self, tag): | |
| if debug: | |
| print("end %s" % tag) | |
| if tag == 'function': | |
| if self.function != None: | |
| function(self.function, self.function_descr, | |
| self.function_return, self.function_args, | |
| self.function_file, self.function_cond) | |
| self.in_function = 0 | |
| elif tag == 'arg': | |
| if self.in_function == 1: | |
| self.function_args.append([self.function_arg_name, | |
| self.function_arg_type, | |
| self.function_arg_info]) | |
| elif tag == 'return': | |
| if self.in_function == 1: | |
| self.function_return = [self.function_return_type, | |
| self.function_return_info, | |
| self.function_return_field] | |
| elif tag == 'info': | |
| str = '' | |
| for c in self._data: | |
| str = str + c | |
| if self.in_function == 1: | |
| self.function_descr = str | |
| elif tag == 'cond': | |
| str = '' | |
| for c in self._data: | |
| str = str + c | |
| if self.in_function == 1: | |
| self.function_cond = str | |
| def function(name, desc, ret, args, file, cond): | |
| functions[name] = (desc, ret, args, file, cond) | |
| def enum(type, name, value): | |
| if type not in enums: | |
| enums[type] = {} | |
| enums[type][name] = value | |
| ####################################################################### | |
| # | |
| # Some filtering rukes to drop functions/types which should not | |
| # be exposed as-is on the Python interface | |
| # | |
| ####################################################################### | |
| skipped_modules = { | |
| 'xmlmemory': None, | |
| 'SAX': None, | |
| 'hash': None, | |
| 'list': None, | |
| 'threads': None, | |
| # 'xpointer': None, | |
| } | |
| skipped_types = { | |
| 'int *': "usually a return type", | |
| 'xmlSAXHandlerPtr': "not the proper interface for SAX", | |
| 'htmlSAXHandlerPtr': "not the proper interface for SAX", | |
| 'xmlRMutexPtr': "thread specific, skipped", | |
| 'xmlMutexPtr': "thread specific, skipped", | |
| 'xmlGlobalStatePtr': "thread specific, skipped", | |
| 'xmlListPtr': "internal representation not suitable for python", | |
| 'xmlBufferPtr': "internal representation not suitable for python", | |
| 'FILE *': None, | |
| } | |
| ####################################################################### | |
| # | |
| # Table of remapping to/from the python type or class to the C | |
| # counterpart. | |
| # | |
| ####################################################################### | |
| py_types = { | |
| 'void': (None, None, None, None), | |
| 'int': ('i', None, "int", "int"), | |
| 'long': ('l', None, "long", "long"), | |
| 'double': ('d', None, "double", "double"), | |
| 'unsigned int': ('i', None, "int", "int"), | |
| 'xmlChar': ('c', None, "int", "int"), | |
| 'unsigned char *': ('z', None, "charPtr", "char *"), | |
| 'char *': ('z', None, "charPtr", "char *"), | |
| 'const char *': ('z', None, "charPtrConst", "const char *"), | |
| 'xmlChar *': ('z', None, "xmlCharPtr", "xmlChar *"), | |
| 'const xmlChar *': ('z', None, "xmlCharPtrConst", "const xmlChar *"), | |
| 'xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlDtdPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlDtd *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlAttrPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlAttr *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlEntityPtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const xmlEntity *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"), | |
| 'const xmlElementPtr': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"), | |
| 'xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"), | |
| 'const xmlElement *': ('O', "xmlElement", "xmlElementPtr", "xmlElementPtr"), | |
| 'xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"), | |
| 'const xmlAttributePtr': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"), | |
| 'xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"), | |
| 'const xmlAttribute *': ('O', "xmlAttribute", "xmlAttributePtr", "xmlAttributePtr"), | |
| 'xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), | |
| 'const xmlNsPtr': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), | |
| 'xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), | |
| 'const xmlNs *': ('O', "xmlNode", "xmlNsPtr", "xmlNsPtr"), | |
| 'xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'const xmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'const xmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'const htmlDocPtr': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'const htmlDoc *': ('O', "xmlNode", "xmlDocPtr", "xmlDocPtr"), | |
| 'htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const htmlNodePtr': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'const htmlNode *': ('O', "xmlNode", "xmlNodePtr", "xmlNodePtr"), | |
| 'xmlXPathContextPtr': ('O', "xmlXPathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"), | |
| 'xmlXPathContext *': ('O', "xpathContext", "xmlXPathContextPtr", "xmlXPathContextPtr"), | |
| 'xmlXPathParserContextPtr': ('O', "xmlXPathParserContext", "xmlXPathParserContextPtr", "xmlXPathParserContextPtr"), | |
| 'xmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), | |
| 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), | |
| 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), | |
| 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), | |
| 'xmlValidCtxtPtr': ('O', "ValidCtxt", "xmlValidCtxtPtr", "xmlValidCtxtPtr"), | |
| 'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"), | |
| 'FILE *': ('O', "File", "FILEPtr", "FILE *"), | |
| 'xmlURIPtr': ('O', "URI", "xmlURIPtr", "xmlURIPtr"), | |
| 'xmlErrorPtr': ('O', "Error", "xmlErrorPtr", "xmlErrorPtr"), | |
| 'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutputBufferPtr"), | |
| 'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"), | |
| 'xmlRegexpPtr': ('O', "xmlReg", "xmlRegexpPtr", "xmlRegexpPtr"), | |
| 'xmlTextReaderLocatorPtr': ('O', "xmlTextReaderLocator", "xmlTextReaderLocatorPtr", "xmlTextReaderLocatorPtr"), | |
| 'xmlTextReaderPtr': ('O', "xmlTextReader", "xmlTextReaderPtr", "xmlTextReaderPtr"), | |
| 'xmlRelaxNGPtr': ('O', "relaxNgSchema", "xmlRelaxNGPtr", "xmlRelaxNGPtr"), | |
| 'xmlRelaxNGParserCtxtPtr': ('O', "relaxNgParserCtxt", "xmlRelaxNGParserCtxtPtr", "xmlRelaxNGParserCtxtPtr"), | |
| 'xmlRelaxNGValidCtxtPtr': ('O', "relaxNgValidCtxt", "xmlRelaxNGValidCtxtPtr", "xmlRelaxNGValidCtxtPtr"), | |
| 'xmlSchemaPtr': ('O', "Schema", "xmlSchemaPtr", "xmlSchemaPtr"), | |
| 'xmlSchemaParserCtxtPtr': ('O', "SchemaParserCtxt", "xmlSchemaParserCtxtPtr", "xmlSchemaParserCtxtPtr"), | |
| 'xmlSchemaValidCtxtPtr': ('O', "SchemaValidCtxt", "xmlSchemaValidCtxtPtr", "xmlSchemaValidCtxtPtr"), | |
| } | |
| py_return_types = { | |
| 'xmlXPathObjectPtr': ('O', "foo", "xmlXPathObjectPtr", "xmlXPathObjectPtr"), | |
| } | |
| unknown_types = {} | |
| foreign_encoding_args = ( | |
| 'htmlCreateMemoryParserCtxt', | |
| 'htmlCtxtReadMemory', | |
| 'htmlParseChunk', | |
| 'htmlReadMemory', | |
| 'xmlCreateMemoryParserCtxt', | |
| 'xmlCtxtReadMemory', | |
| 'xmlCtxtResetPush', | |
| 'xmlParseChunk', | |
| 'xmlParseMemory', | |
| 'xmlReadMemory', | |
| 'xmlRecoverMemory', | |
| ) | |
| ####################################################################### | |
| # | |
| # This part writes the C <-> Python stubs libxml2-py.[ch] and | |
| # the table libxml2-export.c to add when registrering the Python module | |
| # | |
| ####################################################################### | |
| # Class methods which are written by hand in libxml.c but the Python-level | |
| # code is still automatically generated (so they are not in skip_function()). | |
| skip_impl = ( | |
| 'xmlSaveFileTo', | |
| 'xmlSaveFormatFileTo', | |
| ) | |
| deprecated_funcs = { | |
| 'htmlDefaultSAXHandlerInit': True, | |
| 'htmlInitAutoClose': True, | |
| 'htmlParseCharRef': True, | |
| 'htmlParseElement': True, | |
| 'xmlCleanupCharEncodingHandlers': True, | |
| 'xmlCleanupGlobals': True, | |
| 'xmlDefaultSAXHandlerInit': True, | |
| 'xmlDecodeEntities': True, | |
| 'xmlDictCleanup': True, | |
| 'xmlEncodeEntities': True, | |
| 'xmlHandleEntity': True, | |
| 'xmlInitCharEncodingHandlers': True, | |
| 'xmlInitGlobals': True, | |
| 'xmlInitializeDict': True, | |
| 'xmlInitializePredefinedEntities': True, | |
| 'xmlIsRef': True, | |
| 'xmlNamespaceParseNCName': True, | |
| 'xmlNamespaceParseNSDef': True, | |
| 'xmlNanoFTPCleanup': True, | |
| 'xmlNanoFTPInit': True, | |
| 'xmlNanoFTPProxy': True, | |
| 'xmlNanoFTPScanProxy': True, | |
| 'xmlNewGlobalNs': True, | |
| 'xmlParseAttValue': True, | |
| 'xmlParseAttributeListDecl': True, | |
| 'xmlParseCDSect': True, | |
| 'xmlParseCharData': True, | |
| 'xmlParseCharRef': True, | |
| 'xmlParseComment': True, | |
| 'xmlParseDocTypeDecl': True, | |
| 'xmlParseElement': True, | |
| 'xmlParseElementDecl': True, | |
| 'xmlParseEncName': True, | |
| 'xmlParseEncodingDecl': True, | |
| 'xmlParseEndTag': True, | |
| 'xmlParseEntity': True, | |
| 'xmlParseEntityDecl': True, | |
| 'xmlParseEntityRef': True, | |
| 'xmlParseMarkupDecl': True, | |
| 'xmlParseMisc': True, | |
| 'xmlParseName': True, | |
| 'xmlParseNamespace': True, | |
| 'xmlParseNmtoken': True, | |
| 'xmlParseNotationDecl': True, | |
| 'xmlParsePEReference': True, | |
| 'xmlParsePI': True, | |
| 'xmlParsePITarget': True, | |
| 'xmlParsePubidLiteral': True, | |
| 'xmlParseQuotedString': True, | |
| 'xmlParseReference': True, | |
| 'xmlParseSDDecl': True, | |
| 'xmlParseStartTag': True, | |
| 'xmlParseSystemLiteral': True, | |
| 'xmlParseTextDecl': True, | |
| 'xmlParseVersionInfo': True, | |
| 'xmlParseVersionNum': True, | |
| 'xmlParseXMLDecl': True, | |
| 'xmlParserHandleReference': True, | |
| 'xmlRecoverDoc': True, | |
| 'xmlRecoverFile': True, | |
| 'xmlRecoverMemory': True, | |
| 'xmlRelaxNGCleanupTypes': True, | |
| 'xmlRelaxNGInitTypes': True, | |
| 'xmlRemoveRef': True, | |
| 'xmlSAXDefaultVersion': True, | |
| 'xmlScanName': True, | |
| 'xmlSchemaCleanupTypes': True, | |
| 'xmlSchemaInitTypes': True, | |
| 'xmlSetupParserForBuffer': True, | |
| 'xmlStringDecodeEntities': True, | |
| 'xmlStringLenDecodeEntities': True, | |
| 'xmlThrDefDefaultBufferSize': True, | |
| 'xmlThrDefLineNumbersDefaultValue': True, | |
| 'xmlThrDefPedanticParserDefaultValue': True, | |
| 'xmlXPathInit': True, | |
| 'xmlXPtrEvalRangePredicate': True, | |
| 'xmlXPtrNewCollapsedRange': True, | |
| 'xmlXPtrNewLocationSetNodes': True, | |
| 'xmlXPtrNewRange': True, | |
| 'xmlXPtrNewRangeNodes': True, | |
| 'xmlXPtrRangeToFunction': True, | |
| } | |
| def skip_function(name): | |
| if name[0:12] == "xmlXPathWrap": | |
| return 1 | |
| if name == "xmlFreeParserCtxt": | |
| return 1 | |
| if name == "xmlCleanupParser": | |
| return 1 | |
| if name == "xmlFreeTextReader": | |
| return 1 | |
| # if name[0:11] == "xmlXPathNew": | |
| # return 1 | |
| # the next function is defined in libxml.c | |
| if name == "xmlRelaxNGFreeValidCtxt": | |
| return 1 | |
| if name == "xmlFreeValidCtxt": | |
| return 1 | |
| if name == "xmlSchemaFreeValidCtxt": | |
| return 1 | |
| # | |
| # Those are skipped because the Const version is used of the bindings | |
| # instead. | |
| # | |
| if name == "xmlTextReaderBaseUri": | |
| return 1 | |
| if name == "xmlTextReaderLocalName": | |
| return 1 | |
| if name == "xmlTextReaderName": | |
| return 1 | |
| if name == "xmlTextReaderNamespaceUri": | |
| return 1 | |
| if name == "xmlTextReaderPrefix": | |
| return 1 | |
| if name == "xmlTextReaderXmlLang": | |
| return 1 | |
| if name == "xmlTextReaderValue": | |
| return 1 | |
| if name == "xmlOutputBufferClose": # handled by by the superclass | |
| return 1 | |
| if name == "xmlOutputBufferFlush": # handled by by the superclass | |
| return 1 | |
| if name == "xmlErrMemory": | |
| return 1 | |
| if name == "xmlValidBuildContentModel": | |
| return 1 | |
| if name == "xmlValidateElementDecl": | |
| return 1 | |
| if name == "xmlValidateAttributeDecl": | |
| return 1 | |
| if name == "xmlPopInputCallbacks": | |
| return 1 | |
| return 0 | |
| def print_function_wrapper(name, output, export, include): | |
| global py_types | |
| global unknown_types | |
| global functions | |
| global skipped_modules | |
| try: | |
| (desc, ret, args, file, cond) = functions[name] | |
| except: | |
| print("failed to get function %s infos") | |
| return | |
| if file in skipped_modules: | |
| return 0 | |
| if skip_function(name) == 1: | |
| return 0 | |
| if name in skip_impl: | |
| # Don't delete the function entry in the caller. | |
| return 1 | |
| is_deprecated = name in deprecated_funcs | |
| c_call = "" | |
| format="" | |
| format_args="" | |
| c_args="" | |
| c_return="" | |
| c_convert="" | |
| c_release="" | |
| num_bufs=0 | |
| for arg in args: | |
| # This should be correct | |
| if arg[1][0:6] == "const ": | |
| arg[1] = arg[1][6:] | |
| c_args = c_args + " %s %s;\n" % (arg[1], arg[0]) | |
| if arg[1] in py_types: | |
| (f, t, n, c) = py_types[arg[1]] | |
| if (f == 'z') and (name in foreign_encoding_args) and (num_bufs == 0): | |
| f = 's#' | |
| if f != None: | |
| format = format + f | |
| if t != None: | |
| format_args = format_args + ", &pyobj_%s" % (arg[0]) | |
| c_args = c_args + " PyObject *pyobj_%s;\n" % (arg[0]) | |
| c_convert = c_convert + \ | |
| " %s = (%s) Py%s_Get(pyobj_%s);\n" % (arg[0], | |
| arg[1], t, arg[0]) | |
| else: | |
| format_args = format_args + ", &%s" % (arg[0]) | |
| if f == 's#': | |
| format_args = format_args + ", &py_buffsize%d" % num_bufs | |
| c_args = c_args + " Py_ssize_t py_buffsize%d;\n" % num_bufs | |
| num_bufs = num_bufs + 1 | |
| if c_call != "": | |
| c_call = c_call + ", " | |
| c_call = c_call + "%s" % (arg[0]) | |
| if t == "File": | |
| c_release = c_release + \ | |
| " PyFile_Release(%s);\n" % (arg[0]) | |
| else: | |
| if arg[1] in skipped_types: | |
| return 0 | |
| if arg[1] in unknown_types: | |
| lst = unknown_types[arg[1]] | |
| lst.append(name) | |
| else: | |
| unknown_types[arg[1]] = [name] | |
| return -1 | |
| if format != "": | |
| format = format + ":%s" % (name) | |
| if ret[0] == 'void': | |
| if file == "python_accessor": | |
| if args[1][1] == "char *" or args[1][1] == "xmlChar *": | |
| c_call = "\n if (%s->%s != NULL) xmlFree(%s->%s);\n" % ( | |
| args[0][0], args[1][0], args[0][0], args[1][0]) | |
| c_call = c_call + " %s->%s = (%s)xmlStrdup((const xmlChar *)%s);\n" % (args[0][0], | |
| args[1][0], args[1][1], args[1][0]) | |
| else: | |
| c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0], | |
| args[1][0]) | |
| else: | |
| c_call = "\n %s(%s);\n" % (name, c_call) | |
| ret_convert = " Py_INCREF(Py_None);\n return(Py_None);\n" | |
| elif ret[0] in py_types: | |
| (f, t, n, c) = py_types[ret[0]] | |
| c_return = c_return + " %s c_retval;\n" % (ret[0]) | |
| if file == "python_accessor" and ret[2] != None: | |
| c_call = "\n c_retval = %s->%s;\n" % (args[0][0], ret[2]) | |
| else: | |
| c_call = "\n c_retval = %s(%s);\n" % (name, c_call) | |
| ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c) | |
| ret_convert = ret_convert + " return(py_retval);\n" | |
| elif ret[0] in py_return_types: | |
| (f, t, n, c) = py_return_types[ret[0]] | |
| c_return = c_return + " %s c_retval;\n" % (ret[0]) | |
| c_call = "\n c_retval = %s(%s);\n" % (name, c_call) | |
| ret_convert = " py_retval = libxml_%sWrap((%s) c_retval);\n" % (n,c) | |
| ret_convert = ret_convert + " return(py_retval);\n" | |
| else: | |
| if ret[0] in skipped_types: | |
| return 0 | |
| if ret[0] in unknown_types: | |
| lst = unknown_types[ret[0]] | |
| lst.append(name) | |
| else: | |
| unknown_types[ret[0]] = [name] | |
| return -1 | |
| if cond != None and cond != "": | |
| include.write("#if %s\n" % cond) | |
| export.write("#if %s\n" % cond) | |
| output.write("#if %s\n" % cond) | |
| include.write("PyObject * ") | |
| include.write("libxml_%s(PyObject *self, PyObject *args);\n" % (name)) | |
| export.write(" { (char *)\"%s\", libxml_%s, METH_VARARGS, NULL },\n" % | |
| (name, name)) | |
| if file == "python": | |
| # Those have been manually generated | |
| if cond != None and cond != "": | |
| include.write("#endif\n") | |
| export.write("#endif\n") | |
| output.write("#endif\n") | |
| return 1 | |
| if file == "python_accessor" and ret[0] != "void" and ret[2] is None: | |
| # Those have been manually generated | |
| if cond != None and cond != "": | |
| include.write("#endif\n") | |
| export.write("#endif\n") | |
| output.write("#endif\n") | |
| return 1 | |
| if is_deprecated: | |
| output.write("XML_IGNORE_DEPRECATION_WARNINGS\n") | |
| output.write("PyObject *\n") | |
| output.write("libxml_%s(PyObject *self ATTRIBUTE_UNUSED," % (name)) | |
| output.write(" PyObject *args") | |
| if format == "": | |
| output.write(" ATTRIBUTE_UNUSED") | |
| output.write(") {\n") | |
| if ret[0] != 'void': | |
| output.write(" PyObject *py_retval;\n") | |
| if c_return != "": | |
| output.write(c_return) | |
| if c_args != "": | |
| output.write(c_args) | |
| if is_deprecated: | |
| output.write("\n if (libxml_deprecationWarning(\"%s\") == -1)\n" % | |
| name) | |
| output.write(" return(NULL);\n") | |
| if format != "": | |
| output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" % | |
| (format, format_args)) | |
| output.write(" return(NULL);\n") | |
| if c_convert != "": | |
| output.write(c_convert) | |
| output.write(c_call) | |
| if c_release != "": | |
| output.write(c_release) | |
| output.write(ret_convert) | |
| output.write("}\n") | |
| if is_deprecated: | |
| output.write("XML_POP_WARNINGS\n") | |
| output.write("\n") | |
| if cond != None and cond != "": | |
| include.write("#endif /* %s */\n" % cond) | |
| export.write("#endif /* %s */\n" % cond) | |
| output.write("#endif /* %s */\n" % cond) | |
| return 1 | |
| def buildStubs(): | |
| global py_types | |
| global py_return_types | |
| global unknown_types | |
| try: | |
| f = open(os.path.join(srcPref,"libxml2-api.xml")) | |
| data = f.read() | |
| (parser, target) = getparser() | |
| parser.feed(data) | |
| parser.close() | |
| except IOError as msg: | |
| try: | |
| f = open(os.path.join(srcPref,"..","doc","libxml2-api.xml")) | |
| data = f.read() | |
| (parser, target) = getparser() | |
| parser.feed(data) | |
| parser.close() | |
| except IOError as msg: | |
| print(file, ":", msg) | |
| sys.exit(1) | |
| n = len(list(functions.keys())) | |
| print("Found %d functions in libxml2-api.xml" % (n)) | |
| py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject") | |
| try: | |
| f = open(os.path.join(srcPref,"libxml2-python-api.xml")) | |
| data = f.read() | |
| (parser, target) = getparser() | |
| parser.feed(data) | |
| parser.close() | |
| except IOError as msg: | |
| print(file, ":", msg) | |
| print("Found %d functions in libxml2-python-api.xml" % ( | |
| len(list(functions.keys())) - n)) | |
| nb_wrap = 0 | |
| failed = 0 | |
| skipped = 0 | |
| include = open("libxml2-py.h", "w") | |
| include.write("/* Generated */\n\n") | |
| export = open("libxml2-export.c", "w") | |
| export.write("/* Generated */\n\n") | |
| wrapper = open("libxml2-py.c", "w") | |
| wrapper.write("/* Generated */\n\n") | |
| wrapper.write("#define PY_SSIZE_T_CLEAN\n") | |
| wrapper.write("#include <Python.h>\n") | |
| wrapper.write("#include <libxml/xmlversion.h>\n") | |
| wrapper.write("#include <libxml/tree.h>\n") | |
| wrapper.write("#include <libxml/xmlschemastypes.h>\n") | |
| wrapper.write("#include \"libxml_wrap.h\"\n") | |
| wrapper.write("#include \"libxml2-py.h\"\n\n") | |
| for function in sorted(functions.keys()): | |
| ret = print_function_wrapper(function, wrapper, export, include) | |
| if ret < 0: | |
| failed = failed + 1 | |
| del functions[function] | |
| if ret == 0: | |
| skipped = skipped + 1 | |
| del functions[function] | |
| if ret == 1: | |
| nb_wrap = nb_wrap + 1 | |
| include.close() | |
| export.close() | |
| wrapper.close() | |
| print("Generated %d wrapper functions, %d failed, %d skipped" % (nb_wrap, | |
| failed, skipped)) | |
| # print("Missing type converters: ") | |
| # for type in list(unknown_types.keys()): | |
| # print("%s:%d " % (type, len(unknown_types[type]))) | |
| # print() | |
| ####################################################################### | |
| # | |
| # This part writes part of the Python front-end classes based on | |
| # mapping rules between types and classes and also based on function | |
| # renaming to get consistent function names at the Python level | |
| # | |
| ####################################################################### | |
| # | |
| # The type automatically remapped to generated classes | |
| # | |
| classes_type = { | |
| "xmlNodePtr": ("._o", "xmlNode(_obj=%s)", "xmlNode"), | |
| "xmlNode *": ("._o", "xmlNode(_obj=%s)", "xmlNode"), | |
| "xmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), | |
| "xmlDoc *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), | |
| "htmlDocPtr": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), | |
| "htmlxmlDocPtr *": ("._o", "xmlDoc(_obj=%s)", "xmlDoc"), | |
| "xmlAttrPtr": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"), | |
| "xmlAttr *": ("._o", "xmlAttr(_obj=%s)", "xmlAttr"), | |
| "xmlNsPtr": ("._o", "xmlNs(_obj=%s)", "xmlNs"), | |
| "xmlNs *": ("._o", "xmlNs(_obj=%s)", "xmlNs"), | |
| "xmlDtdPtr": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"), | |
| "xmlDtd *": ("._o", "xmlDtd(_obj=%s)", "xmlDtd"), | |
| "xmlEntityPtr": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"), | |
| "xmlEntity *": ("._o", "xmlEntity(_obj=%s)", "xmlEntity"), | |
| "xmlElementPtr": ("._o", "xmlElement(_obj=%s)", "xmlElement"), | |
| "xmlElement *": ("._o", "xmlElement(_obj=%s)", "xmlElement"), | |
| "xmlAttributePtr": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), | |
| "xmlAttribute *": ("._o", "xmlAttribute(_obj=%s)", "xmlAttribute"), | |
| "xmlXPathContextPtr": ("._o", "xpathContext(_obj=%s)", "xpathContext"), | |
| "xmlXPathContext *": ("._o", "xpathContext(_obj=%s)", "xpathContext"), | |
| "xmlXPathParserContext *": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"), | |
| "xmlXPathParserContextPtr": ("._o", "xpathParserContext(_obj=%s)", "xpathParserContext"), | |
| "xmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), | |
| "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), | |
| "htmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), | |
| "htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), | |
| "xmlValidCtxtPtr": ("._o", "ValidCtxt(_obj=%s)", "ValidCtxt"), | |
| "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"), | |
| "xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"), | |
| "xmlErrorPtr": ("._o", "Error(_obj=%s)", "Error"), | |
| "xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"), | |
| "xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"), | |
| "xmlRegexpPtr": ("._o", "xmlReg(_obj=%s)", "xmlReg"), | |
| "xmlTextReaderLocatorPtr": ("._o", "xmlTextReaderLocator(_obj=%s)", "xmlTextReaderLocator"), | |
| "xmlTextReaderPtr": ("._o", "xmlTextReader(_obj=%s)", "xmlTextReader"), | |
| 'xmlRelaxNGPtr': ('._o', "relaxNgSchema(_obj=%s)", "relaxNgSchema"), | |
| 'xmlRelaxNGParserCtxtPtr': ('._o', "relaxNgParserCtxt(_obj=%s)", "relaxNgParserCtxt"), | |
| 'xmlRelaxNGValidCtxtPtr': ('._o', "relaxNgValidCtxt(_obj=%s)", "relaxNgValidCtxt"), | |
| 'xmlSchemaPtr': ("._o", "Schema(_obj=%s)", "Schema"), | |
| 'xmlSchemaParserCtxtPtr': ("._o", "SchemaParserCtxt(_obj=%s)", "SchemaParserCtxt"), | |
| 'xmlSchemaValidCtxtPtr': ("._o", "SchemaValidCtxt(_obj=%s)", "SchemaValidCtxt"), | |
| } | |
| converter_type = { | |
| "xmlXPathObjectPtr": "xpathObjectRet(%s)", | |
| } | |
| primary_classes = ["xmlNode", "xmlDoc"] | |
| classes_ancestor = { | |
| "xmlNode" : "xmlCore", | |
| "xmlDtd" : "xmlNode", | |
| "xmlDoc" : "xmlNode", | |
| "xmlAttr" : "xmlNode", | |
| "xmlNs" : "xmlNode", | |
| "xmlEntity" : "xmlNode", | |
| "xmlElement" : "xmlNode", | |
| "xmlAttribute" : "xmlNode", | |
| "outputBuffer": "ioWriteWrapper", | |
| "inputBuffer": "ioReadWrapper", | |
| "parserCtxt": "parserCtxtCore", | |
| "xmlTextReader": "xmlTextReaderCore", | |
| "ValidCtxt": "ValidCtxtCore", | |
| "SchemaValidCtxt": "SchemaValidCtxtCore", | |
| "relaxNgValidCtxt": "relaxNgValidCtxtCore", | |
| } | |
| classes_destructors = { | |
| "parserCtxt": "xmlFreeParserCtxt", | |
| "catalog": "xmlFreeCatalog", | |
| "URI": "xmlFreeURI", | |
| # "outputBuffer": "xmlOutputBufferClose", | |
| "inputBuffer": "xmlFreeParserInputBuffer", | |
| "xmlReg": "xmlRegFreeRegexp", | |
| "xmlTextReader": "xmlFreeTextReader", | |
| "relaxNgSchema": "xmlRelaxNGFree", | |
| "relaxNgParserCtxt": "xmlRelaxNGFreeParserCtxt", | |
| "relaxNgValidCtxt": "xmlRelaxNGFreeValidCtxt", | |
| "Schema": "xmlSchemaFree", | |
| "SchemaParserCtxt": "xmlSchemaFreeParserCtxt", | |
| "SchemaValidCtxt": "xmlSchemaFreeValidCtxt", | |
| "ValidCtxt": "xmlFreeValidCtxt", | |
| } | |
| functions_noexcept = { | |
| "xmlHasProp": 1, | |
| "xmlHasNsProp": 1, | |
| "xmlDocSetRootElement": 1, | |
| "xmlNodeGetNs": 1, | |
| "xmlNodeGetNsDefs": 1, | |
| "xmlNextElementSibling": 1, | |
| "xmlPreviousElementSibling": 1, | |
| "xmlFirstElementChild": 1, | |
| "xmlLastElementChild": 1, | |
| } | |
| reference_keepers = { | |
| "xmlTextReader": [('inputBuffer', 'input')], | |
| "relaxNgValidCtxt": [('relaxNgSchema', 'schema')], | |
| "SchemaValidCtxt": [('Schema', 'schema')], | |
| } | |
| function_classes = {} | |
| function_classes["None"] = [] | |
| def nameFixup(name, classe, type, file): | |
| listname = classe + "List" | |
| ll = len(listname) | |
| l = len(classe) | |
| if name[0:l] == listname: | |
| func = name[l:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:12] == "xmlParserGet" and file == "python_accessor": | |
| func = name[12:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:12] == "xmlParserSet" and file == "python_accessor": | |
| func = name[12:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:10] == "xmlNodeGet" and file == "python_accessor": | |
| func = name[10:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:9] == "xmlURIGet" and file == "python_accessor": | |
| func = name[9:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:9] == "xmlURISet" and file == "python_accessor": | |
| func = name[6:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:11] == "xmlErrorGet" and file == "python_accessor": | |
| func = name[11:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:17] == "xmlXPathParserGet" and file == "python_accessor": | |
| func = name[17:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:11] == "xmlXPathGet" and file == "python_accessor": | |
| func = name[11:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:11] == "xmlXPathSet" and file == "python_accessor": | |
| func = name[8:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:15] == "xmlOutputBuffer" and file != "python": | |
| func = name[15:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:20] == "xmlParserInputBuffer" and file != "python": | |
| func = name[20:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:9] == "xmlRegexp" and file == "xmlregexp": | |
| func = "regexp" + name[9:] | |
| elif name[0:6] == "xmlReg" and file == "xmlregexp": | |
| func = "regexp" + name[6:] | |
| elif name[0:20] == "xmlTextReaderLocator" and file == "xmlreader": | |
| func = name[20:] | |
| elif name[0:18] == "xmlTextReaderConst" and file == "xmlreader": | |
| func = name[18:] | |
| elif name[0:13] == "xmlTextReader" and file == "xmlreader": | |
| func = name[13:] | |
| elif name[0:12] == "xmlReaderNew" and file == "xmlreader": | |
| func = name[9:] | |
| elif name[0:11] == "xmlACatalog": | |
| func = name[11:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:l] == classe: | |
| func = name[l:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:7] == "libxml_": | |
| func = name[7:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:6] == "xmlGet": | |
| func = name[6:] | |
| func = func[0:1].lower() + func[1:] | |
| elif name[0:3] == "xml": | |
| func = name[3:] | |
| func = func[0:1].lower() + func[1:] | |
| else: | |
| func = name | |
| if func[0:5] == "xPath": | |
| func = "xpath" + func[5:] | |
| elif func[0:4] == "xPtr": | |
| func = "xpointer" + func[4:] | |
| elif func[0:8] == "xInclude": | |
| func = "xinclude" + func[8:] | |
| elif func[0:2] == "iD": | |
| func = "ID" + func[2:] | |
| elif func[0:3] == "uRI": | |
| func = "URI" + func[3:] | |
| elif func[0:4] == "uTF8": | |
| func = "UTF8" + func[4:] | |
| elif func[0:3] == 'sAX': | |
| func = "SAX" + func[3:] | |
| return func | |
| def functionCompare(info1, info2): | |
| (index1, func1, name1, ret1, args1, file1) = info1 | |
| (index2, func2, name2, ret2, args2, file2) = info2 | |
| if file1 == file2: | |
| if func1 < func2: | |
| return -1 | |
| if func1 > func2: | |
| return 1 | |
| if file1 == "python_accessor": | |
| return -1 | |
| if file2 == "python_accessor": | |
| return 1 | |
| if file1 < file2: | |
| return -1 | |
| if file1 > file2: | |
| return 1 | |
| return 0 | |
| def cmp_to_key(mycmp): | |
| 'Convert a cmp= function into a key= function' | |
| class K(object): | |
| def __init__(self, obj, *args): | |
| self.obj = obj | |
| def __lt__(self, other): | |
| return mycmp(self.obj, other.obj) < 0 | |
| def __gt__(self, other): | |
| return mycmp(self.obj, other.obj) > 0 | |
| def __eq__(self, other): | |
| return mycmp(self.obj, other.obj) == 0 | |
| def __le__(self, other): | |
| return mycmp(self.obj, other.obj) <= 0 | |
| def __ge__(self, other): | |
| return mycmp(self.obj, other.obj) >= 0 | |
| def __ne__(self, other): | |
| return mycmp(self.obj, other.obj) != 0 | |
| return K | |
| def writeDoc(name, args, indent, output): | |
| if functions[name][0] is None or functions[name][0] == "": | |
| return | |
| val = functions[name][0] | |
| val = val.replace("NULL", "None") | |
| output.write(indent) | |
| output.write('"""') | |
| while len(val) > 60: | |
| if val[0] == " ": | |
| val = val[1:] | |
| continue | |
| str = val[0:60] | |
| i = str.rfind(" ") | |
| if i < 0: | |
| i = 60 | |
| str = val[0:i] | |
| val = val[i:] | |
| output.write(str) | |
| output.write('\n ') | |
| output.write(indent) | |
| output.write(val) | |
| output.write(' """\n') | |
| def buildWrappers(): | |
| global ctypes | |
| global py_types | |
| global py_return_types | |
| global unknown_types | |
| global functions | |
| global function_classes | |
| global classes_type | |
| global classes_list | |
| global converter_type | |
| global primary_classes | |
| global converter_type | |
| global classes_ancestor | |
| global converter_type | |
| global primary_classes | |
| global classes_ancestor | |
| global classes_destructors | |
| global functions_noexcept | |
| for type in classes_type.keys(): | |
| function_classes[classes_type[type][2]] = [] | |
| # | |
| # Build the list of C types to look for ordered to start | |
| # with primary classes | |
| # | |
| ctypes = [] | |
| classes_list = [] | |
| ctypes_processed = {} | |
| classes_processed = {} | |
| for classe in primary_classes: | |
| classes_list.append(classe) | |
| classes_processed[classe] = () | |
| for type in classes_type.keys(): | |
| tinfo = classes_type[type] | |
| if tinfo[2] == classe: | |
| ctypes.append(type) | |
| ctypes_processed[type] = () | |
| for type in sorted(classes_type.keys()): | |
| if type in ctypes_processed: | |
| continue | |
| tinfo = classes_type[type] | |
| if tinfo[2] not in classes_processed: | |
| classes_list.append(tinfo[2]) | |
| classes_processed[tinfo[2]] = () | |
| ctypes.append(type) | |
| ctypes_processed[type] = () | |
| for name in functions.keys(): | |
| found = 0 | |
| (desc, ret, args, file, cond) = functions[name] | |
| for type in ctypes: | |
| classe = classes_type[type][2] | |
| if name[0:3] == "xml" and len(args) >= 1 and args[0][1] == type: | |
| found = 1 | |
| func = nameFixup(name, classe, type, file) | |
| info = (0, func, name, ret, args, file) | |
| function_classes[classe].append(info) | |
| elif name[0:3] == "xml" and len(args) >= 2 and args[1][1] == type \ | |
| and file != "python_accessor": | |
| found = 1 | |
| func = nameFixup(name, classe, type, file) | |
| info = (1, func, name, ret, args, file) | |
| function_classes[classe].append(info) | |
| elif name[0:4] == "html" and len(args) >= 1 and args[0][1] == type: | |
| found = 1 | |
| func = nameFixup(name, classe, type, file) | |
| info = (0, func, name, ret, args, file) | |
| function_classes[classe].append(info) | |
| elif name[0:4] == "html" and len(args) >= 2 and args[1][1] == type \ | |
| and file != "python_accessor": | |
| found = 1 | |
| func = nameFixup(name, classe, type, file) | |
| info = (1, func, name, ret, args, file) | |
| function_classes[classe].append(info) | |
| if found == 1: | |
| continue | |
| if name[0:8] == "xmlXPath": | |
| continue | |
| if name[0:6] == "xmlStr": | |
| continue | |
| if name[0:10] == "xmlCharStr": | |
| continue | |
| func = nameFixup(name, "None", file, file) | |
| info = (0, func, name, ret, args, file) | |
| function_classes['None'].append(info) | |
| classes = open("libxml2class.py", "w") | |
| txt = open("libxml2class.txt", "w") | |
| txt.write(" Generated Classes for libxml2-python\n\n") | |
| txt.write("#\n# Global functions of the module\n#\n\n") | |
| if "None" in function_classes: | |
| flist = function_classes["None"] | |
| flist = sorted(flist, key=cmp_to_key(functionCompare)) | |
| oldfile = "" | |
| for info in flist: | |
| (index, func, name, ret, args, file) = info | |
| if file != oldfile: | |
| classes.write("#\n# Functions from module %s\n#\n\n" % file) | |
| txt.write("\n# functions from module %s\n" % file) | |
| oldfile = file | |
| classes.write("def %s(" % func) | |
| txt.write("%s()\n" % func) | |
| n = 0 | |
| for arg in args: | |
| if n != 0: | |
| classes.write(", ") | |
| classes.write("%s" % arg[0]) | |
| n = n + 1 | |
| classes.write("):\n") | |
| writeDoc(name, args, ' ', classes) | |
| for arg in args: | |
| if arg[1] in classes_type: | |
| classes.write(" if %s is None: %s__o = None\n" % | |
| (arg[0], arg[0])) | |
| classes.write(" else: %s__o = %s%s\n" % | |
| (arg[0], arg[0], classes_type[arg[1]][0])) | |
| if arg[1] in py_types: | |
| (f, t, n, c) = py_types[arg[1]] | |
| if t == "File": | |
| classes.write(" if %s is not None: %s.flush()\n" % ( | |
| arg[0], arg[0])) | |
| if ret[0] != "void": | |
| classes.write(" ret = ") | |
| else: | |
| classes.write(" ") | |
| classes.write("libxml2mod.%s(" % name) | |
| n = 0 | |
| for arg in args: | |
| if n != 0: | |
| classes.write(", ") | |
| classes.write("%s" % arg[0]) | |
| if arg[1] in classes_type: | |
| classes.write("__o") | |
| n = n + 1 | |
| classes.write(")\n") | |
| # This may be needed to reposition the I/O, but likely to cause more harm | |
| # than good. Those changes in Python3 really break the model. | |
| # for arg in args: | |
| # if arg[1] in py_types: | |
| # (f, t, n, c) = py_types[arg[1]] | |
| # if t == "File": | |
| # classes.write(" if %s is not None: %s.seek(0,0)\n"%( | |
| # arg[0], arg[0])) | |
| if ret[0] != "void": | |
| if ret[0] in classes_type: | |
| # | |
| # Raise an exception | |
| # | |
| if name in functions_noexcept: | |
| classes.write(" if ret is None:return None\n") | |
| elif name.find("URI") >= 0: | |
| classes.write( | |
| " if ret is None:raise uriError('%s() failed')\n" | |
| % (name)) | |
| elif name.find("XPath") >= 0: | |
| classes.write( | |
| " if ret is None:raise xpathError('%s() failed')\n" | |
| % (name)) | |
| elif name.find("Parse") >= 0: | |
| classes.write( | |
| " if ret is None:raise parserError('%s() failed')\n" | |
| % (name)) | |
| else: | |
| classes.write( | |
| " if ret is None:raise treeError('%s() failed')\n" | |
| % (name)) | |
| classes.write(" return ") | |
| classes.write(classes_type[ret[0]][1] % ("ret")) | |
| classes.write("\n") | |
| else: | |
| classes.write(" return ret\n") | |
| classes.write("\n") | |
| txt.write("\n\n#\n# Set of classes of the module\n#\n\n") | |
| for classname in classes_list: | |
| if classname == "None": | |
| pass | |
| else: | |
| if classname in classes_ancestor: | |
| txt.write("\n\nClass %s(%s)\n" % (classname, | |
| classes_ancestor[classname])) | |
| classes.write("class %s(%s):\n" % (classname, | |
| classes_ancestor[classname])) | |
| classes.write(" def __init__(self, _obj=None):\n") | |
| if classes_ancestor[classname] == "xmlCore" or \ | |
| classes_ancestor[classname] == "xmlNode": | |
| classes.write(" if checkWrapper(_obj) != 0:") | |
| classes.write(" raise TypeError") | |
| classes.write("('%s got a wrong wrapper object type')\n" % \ | |
| classname) | |
| if classname in reference_keepers: | |
| rlist = reference_keepers[classname] | |
| for ref in rlist: | |
| classes.write(" self.%s = None\n" % ref[1]) | |
| classes.write(" self._o = _obj\n") | |
| classes.write(" %s.__init__(self, _obj=_obj)\n\n" % ( | |
| classes_ancestor[classname])) | |
| if classes_ancestor[classname] == "xmlCore" or \ | |
| classes_ancestor[classname] == "xmlNode": | |
| classes.write(" def __repr__(self):\n") | |
| format = "<%s (%%s) object at 0x%%x>" % (classname) | |
| classes.write(" return \"%s\" %% (self.name, int(pos_id (self)))\n\n" % ( | |
| format)) | |
| else: | |
| txt.write("Class %s()\n" % (classname)) | |
| classes.write("class %s:\n" % (classname)) | |
| classes.write(" def __init__(self, _obj=None):\n") | |
| if classname in reference_keepers: | |
| list = reference_keepers[classname] | |
| for ref in list: | |
| classes.write(" self.%s = None\n" % ref[1]) | |
| classes.write(" if _obj != None:self._o = _obj;return\n") | |
| classes.write(" self._o = None\n\n") | |
| destruct=None | |
| if classname in classes_destructors: | |
| classes.write(" def __del__(self):\n") | |
| classes.write(" if self._o != None:\n") | |
| classes.write(" libxml2mod.%s(self._o)\n" % | |
| classes_destructors[classname]) | |
| classes.write(" self._o = None\n\n") | |
| destruct=classes_destructors[classname] | |
| flist = function_classes[classname] | |
| flist = sorted(flist, key=cmp_to_key(functionCompare)) | |
| oldfile = "" | |
| for info in flist: | |
| (index, func, name, ret, args, file) = info | |
| # | |
| # Do not provide as method the destructors for the class | |
| # to avoid double free | |
| # | |
| if name == destruct: | |
| continue | |
| if file != oldfile: | |
| if file == "python_accessor": | |
| classes.write(" # accessors for %s\n" % (classname)) | |
| txt.write(" # accessors\n") | |
| else: | |
| classes.write(" #\n") | |
| classes.write(" # %s functions from module %s\n" % ( | |
| classname, file)) | |
| txt.write("\n # functions from module %s\n" % file) | |
| classes.write(" #\n\n") | |
| oldfile = file | |
| classes.write(" def %s(self" % func) | |
| txt.write(" %s()\n" % func) | |
| n = 0 | |
| for arg in args: | |
| if n != index: | |
| classes.write(", %s" % arg[0]) | |
| n = n + 1 | |
| classes.write("):\n") | |
| writeDoc(name, args, ' ', classes) | |
| n = 0 | |
| for arg in args: | |
| if arg[1] in classes_type: | |
| if n != index: | |
| classes.write(" if %s is None: %s__o = None\n" % | |
| (arg[0], arg[0])) | |
| classes.write(" else: %s__o = %s%s\n" % | |
| (arg[0], arg[0], classes_type[arg[1]][0])) | |
| n = n + 1 | |
| if ret[0] != "void": | |
| classes.write(" ret = ") | |
| else: | |
| classes.write(" ") | |
| classes.write("libxml2mod.%s(" % name) | |
| n = 0 | |
| for arg in args: | |
| if n != 0: | |
| classes.write(", ") | |
| if n != index: | |
| classes.write("%s" % arg[0]) | |
| if arg[1] in classes_type: | |
| classes.write("__o") | |
| else: | |
| classes.write("self") | |
| if arg[1] in classes_type: | |
| classes.write(classes_type[arg[1]][0]) | |
| n = n + 1 | |
| classes.write(")\n") | |
| if ret[0] != "void": | |
| if ret[0] in classes_type: | |
| # | |
| # Raise an exception | |
| # | |
| if name in functions_noexcept: | |
| classes.write( | |
| " if ret is None:return None\n") | |
| elif name.find("URI") >= 0: | |
| classes.write( | |
| " if ret is None:raise uriError('%s() failed')\n" | |
| % (name)) | |
| elif name.find("XPath") >= 0: | |
| classes.write( | |
| " if ret is None:raise xpathError('%s() failed')\n" | |
| % (name)) | |
| elif name.find("Parse") >= 0: | |
| classes.write( | |
| " if ret is None:raise parserError('%s() failed')\n" | |
| % (name)) | |
| else: | |
| classes.write( | |
| " if ret is None:raise treeError('%s() failed')\n" | |
| % (name)) | |
| # | |
| # generate the returned class wrapper for the object | |
| # | |
| classes.write(" __tmp = ") | |
| classes.write(classes_type[ret[0]][1] % ("ret")) | |
| classes.write("\n") | |
| # | |
| # Sometime one need to keep references of the source | |
| # class in the returned class object. | |
| # See reference_keepers for the list | |
| # | |
| tclass = classes_type[ret[0]][2] | |
| if tclass in reference_keepers: | |
| list = reference_keepers[tclass] | |
| for pref in list: | |
| if pref[0] == classname: | |
| classes.write(" __tmp.%s = self\n" % | |
| pref[1]) | |
| # | |
| # return the class | |
| # | |
| classes.write(" return __tmp\n") | |
| elif ret[0] in converter_type: | |
| # | |
| # Raise an exception | |
| # | |
| if name in functions_noexcept: | |
| classes.write( | |
| " if ret is None:return None") | |
| elif name.find("URI") >= 0: | |
| classes.write( | |
| " if ret is None:raise uriError('%s() failed')\n" | |
| % (name)) | |
| elif name.find("XPath") >= 0: | |
| classes.write( | |
| " if ret is None:raise xpathError('%s() failed')\n" | |
| % (name)) | |
| elif name.find("Parse") >= 0: | |
| classes.write( | |
| " if ret is None:raise parserError('%s() failed')\n" | |
| % (name)) | |
| else: | |
| classes.write( | |
| " if ret is None:raise treeError('%s() failed')\n" | |
| % (name)) | |
| classes.write(" return ") | |
| classes.write(converter_type[ret[0]] % ("ret")) | |
| classes.write("\n") | |
| else: | |
| classes.write(" return ret\n") | |
| classes.write("\n") | |
| # | |
| # Generate enum constants | |
| # | |
| for type,enum in enums.items(): | |
| classes.write("# %s\n" % type) | |
| items = enum.items() | |
| items = sorted(items, key=(lambda i: int(i[1]))) | |
| for name,value in items: | |
| classes.write("%s = %s\n" % (name,value)) | |
| classes.write("\n") | |
| txt.close() | |
| classes.close() | |
| buildStubs() | |
| buildWrappers() |