generator.py 48 KB

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