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