mirror of
https://gitlab.gnome.org/GNOME/libxml2
synced 2025-03-28 21:33:13 +00:00

This will probably cause many warnings in downstream code abusing libxml2 internals, but we can always undeprecate some members later.
1383 lines
53 KiB
Python
Executable File
1383 lines
53 KiB
Python
Executable File
#!/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"),
|
|
'const xmlError *': ('O', "Error", "xmlErrorPtr", "const xmlError *"),
|
|
'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,
|
|
'htmlHandleOmittedElem': True,
|
|
'htmlInitAutoClose': True,
|
|
'htmlParseCharRef': True,
|
|
'htmlParseElement': True,
|
|
'namePop': True,
|
|
'namePush': True,
|
|
'nodePop': True,
|
|
'nodePush': True,
|
|
'xmlCheckFilename': True,
|
|
'xmlCheckLanguageID': True,
|
|
'xmlCleanupCharEncodingHandlers': True,
|
|
'xmlCleanupGlobals': True,
|
|
'xmlDefaultSAXHandlerInit': True,
|
|
'xmlDecodeEntities': True,
|
|
'xmlDictCleanup': True,
|
|
'xmlEncodeEntities': True,
|
|
'xmlFileMatch': True,
|
|
'xmlGetCompressMode': True,
|
|
'xmlHandleEntity': True,
|
|
'xmlInitCharEncodingHandlers': True,
|
|
'xmlInitGlobals': True,
|
|
'xmlInitializeDict': True,
|
|
'xmlInitializePredefinedEntities': True,
|
|
'xmlIOFTPMatch': True,
|
|
'xmlIOHTTPMatch': True,
|
|
'xmlIsRef': True,
|
|
'xmlKeepBlanksDefault': True,
|
|
'xmlLineNumbersDefault': True,
|
|
'xmlNamespaceParseNCName': True,
|
|
'xmlNamespaceParseNSDef': True,
|
|
'xmlNanoFTPCleanup': True,
|
|
'xmlNanoFTPInit': True,
|
|
'xmlNanoFTPProxy': True,
|
|
'xmlNanoFTPScanProxy': True,
|
|
'xmlNanoHTTPCleanup': True,
|
|
'xmlNanoHTTPInit': True,
|
|
'xmlNanoHTTPScanProxy': True,
|
|
'xmlNewGlobalNs': True,
|
|
'xmlNextChar': True,
|
|
'xmlNormalizeWindowsPath': 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,
|
|
'xmlParserHandlePEReference': True,
|
|
'xmlParserHandleReference': True,
|
|
'xmlParserSetLineNumbers': True,
|
|
'xmlParserSetLoadSubset': True,
|
|
'xmlParserSetPedantic': True,
|
|
'xmlParserSetReplaceEntities': True,
|
|
'xmlParserSetValidate': True,
|
|
'xmlPedanticParserDefault': True,
|
|
'xmlRecoverDoc': True,
|
|
'xmlRecoverFile': True,
|
|
'xmlRecoverMemory': True,
|
|
'xmlRegisterHTTPPostCallbacks': True,
|
|
'xmlRelaxNGCleanupTypes': True,
|
|
'xmlRelaxNGInitTypes': True,
|
|
'xmlRemoveRef': True,
|
|
'xmlSAXDefaultVersion': True,
|
|
'xmlScanName': True,
|
|
'xmlSchemaCleanupTypes': True,
|
|
'xmlSchemaInitTypes': True,
|
|
'xmlSetCompressMode': True,
|
|
'xmlSetupParserForBuffer': True,
|
|
'xmlSkipBlankChars': True,
|
|
'xmlStringDecodeEntities': True,
|
|
'xmlStringLenDecodeEntities': True,
|
|
'xmlSubstituteEntitiesDefault': True,
|
|
'xmlThrDefDefaultBufferSize': True,
|
|
'xmlThrDefDoValidityCheckingDefaultValue': True,
|
|
'xmlThrDefGetWarningsDefaultValue': True,
|
|
'xmlThrDefIndentTreeOutput': True,
|
|
'xmlThrDefKeepBlanksDefaultValue': True,
|
|
'xmlThrDefLineNumbersDefaultValue': True,
|
|
'xmlThrDefLoadExtDtdDefaultValue': True,
|
|
'xmlThrDefParserDebugEntities': True,
|
|
'xmlThrDefPedanticParserDefaultValue': True,
|
|
'xmlThrDefSaveNoEmptyTags': True,
|
|
'xmlThrDefSubstituteEntitiesDefaultValue': True,
|
|
'xmlThrDefTreeIndentString': True,
|
|
'xmlValidCtxtNormalizeAttributeValue': True,
|
|
'xmlValidNormalizeAttributeValue': True,
|
|
'xmlValidateAttributeValue': True,
|
|
'xmlValidateDocumentFinal': True,
|
|
'xmlValidateDtdFinal': True,
|
|
'xmlValidateNotationUse': True,
|
|
'xmlValidateOneAttribute': True,
|
|
'xmlValidateOneElement': True,
|
|
'xmlValidateOneNamespace': True,
|
|
'xmlValidatePopElement': True,
|
|
'xmlValidatePushCData': True,
|
|
'xmlValidatePushElement': True,
|
|
'xmlValidateRoot': True,
|
|
'xmlValidate': True,
|
|
'xmlXPathInit': True,
|
|
'xmlXPtrEvalRangePredicate': True,
|
|
'xmlXPtrNewCollapsedRange': True,
|
|
'xmlXPtrNewContext': 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
|
|
|
|
if name.startswith('xmlUCSIs'):
|
|
is_deprecated = name != 'xmlUCSIsBlock' and name != 'xmlUCSIsCat'
|
|
else:
|
|
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"),
|
|
"const xmlError *": ("._o", "Error(_obj=%s)", "Error"),
|
|
"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()
|