+
+####################################
+# BuildRenamers
+####################################
+
+import pprint, shutil
+try:
+ import libxml2
+ FOUND_LIBXML2 = True
+except ImportError:
+ FOUND_LIBXML2 = False
+
+#---------------------------------------------------------------------------
+
+renamerTemplateStart = """\
+// A bunch of %rename directives generated by BuildRenamers in config.py
+// in order to remove the wx prefix from all global scope names.
+
+#ifndef BUILDING_RENAMERS
+
+"""
+
+renamerTemplateEnd = """
+#endif
+"""
+
+wxPythonTemplateStart = """\
+## This file reverse renames symbols in the wx package to give
+## them their wx prefix again, for backwards compatibility.
+##
+## Generated by BuildRenamers in config.py
+
+# This silly stuff here is so the wxPython.wx module doesn't conflict
+# with the wx package. We need to import modules from the wx package
+# here, then we'll put the wxPython.wx entry back in sys.modules.
+import sys
+_wx = None
+if sys.modules.has_key('wxPython.wx'):
+ _wx = sys.modules['wxPython.wx']
+ del sys.modules['wxPython.wx']
+
+import wx.%s
+
+sys.modules['wxPython.wx'] = _wx
+del sys, _wx
+
+
+# Now assign all the reverse-renamed names:
+"""
+
+wxPythonTemplateEnd = """
+
+"""
+
+
+
+#---------------------------------------------------------------------------
+class BuildRenamers:
+ def run(self, destdir, modname, xmlfile, wxPythonDir="wxPython"):
+
+ assert FOUND_LIBXML2, "The libxml2 module is required to use the BuildRenamers functionality."
+
+ if not os.path.exists(wxPythonDir):
+ os.mkdir(wxPythonDir)
+
+ swigDest = os.path.join(destdir, "_"+modname+"_rename.i")
+ pyDest = os.path.join(wxPythonDir, modname + '.py')
+
+ swigDestTemp = tempfile.mktemp('.tmp')
+ swigFile = open(swigDestTemp, "w")
+ swigFile.write(renamerTemplateStart)
+
+ pyDestTemp = tempfile.mktemp('.tmp')
+ pyFile = open(pyDestTemp, "w")
+ pyFile.write(wxPythonTemplateStart % modname)
+
+ print "Parsing XML and building renamers..."
+ self.processXML(xmlfile, modname, swigFile, pyFile)
+
+ self.checkOtherNames(pyFile, modname,
+ os.path.join(destdir, '_'+modname+'_reverse.txt'))
+ pyFile.write(wxPythonTemplateEnd)
+ pyFile.close()
+
+ swigFile.write(renamerTemplateEnd)
+ swigFile.close()
+
+ # Compare the files just created with the existing one and
+ # blow away the old one if they are different.
+ for dest, temp in [(swigDest, swigDestTemp),
+ (pyDest, pyDestTemp)]:
+ # NOTE: we don't use shutil.move() because it was introduced
+ # in Python 2.3. Eventually we can switch to it when people
+ # stop building using 2.2.
+ if not os.path.exists(dest):
+ shutil.copyfile(temp, dest)
+ elif open(dest).read() != open(temp).read():
+ os.unlink(dest)
+ shutil.copyfile(temp, dest)
+ else:
+ print dest + " not changed."
+ os.unlink(temp)
+
+ #---------------------------------------------------------------------------
+
+
+ def GetAttr(self, node, name):
+ path = "./attributelist/attribute[@name='%s']/@value" % name
+ n = node.xpathEval2(path)
+ if len(n):
+ return n[0].content
+ else:
+ return None
+
+
+ def processXML(self, xmlfile, modname, swigFile, pyFile):
+
+ topnode = libxml2.parseFile(xmlfile).children
+
+ # remove any import nodes as we don't need to do renamers for symbols found therein
+ imports = topnode.xpathEval2("*/import")
+ for n in imports:
+ n.unlinkNode()
+ n.freeNode()
+
+ # do a depth first iteration over what's left
+ for node in topnode:
+ doRename = False
+ addWX = False
+ revOnly = False
+
+
+ if node.name == "class":
+ lastClassName = name = self.GetAttr(node, "name")
+ lastClassSymName = sym_name = self.GetAttr(node, "sym_name")
+ doRename = True
+ if sym_name != name:
+ name = sym_name
+ addWX = True
+
+ # renamed constructors
+ elif node.name == "constructor":
+ name = self.GetAttr(node, "name")
+ sym_name = self.GetAttr(node, "sym_name")
+ if sym_name != name:
+ name = sym_name
+ addWX = True
+ doRename = True
+
+ # only enumitems at the top level
+ elif node.name == "enumitem" and node.parent.parent.name == "include":
+ name = self.GetAttr(node, "name")
+ sym_name = self.GetAttr(node, "sym_name")
+ doRename = True
+
+
+ elif node.name in ["cdecl", "constant"]:
+ name = self.GetAttr(node, "name")
+ sym_name = self.GetAttr(node, "sym_name")
+ toplevel = node.parent.name == "include"
+
+ # top-level functions
+ if toplevel and self.GetAttr(node, "view") == "globalfunctionHandler":
+ doRename = True
+
+ # top-level global vars
+ elif toplevel and self.GetAttr(node, "feature_immutable") == "1":
+ doRename = True
+
+ # static methods
+ elif self.GetAttr(node, "view") == "staticmemberfunctionHandler":
+ name = lastClassName + '_' + name
+ sym_name = lastClassSymName + '_' + sym_name
+ # only output the reverse renamer in this case
+ doRename = revOnly = True
+
+ if doRename and name != sym_name:
+ name = sym_name
+ addWX = True
+
+
+ if doRename and name:
+ old = new = name
+ if old.startswith('wx') and not old.startswith('wxEVT_'):
+ # remove all wx prefixes except wxEVT_ and write a %rename directive for it
+ new = old[2:]
+ if not revOnly:
+ swigFile.write("%%rename(%s) %35s;\n" % (new, old))
+
+ # Write assignments to import into the old wxPython namespace
+ if addWX and not old.startswith('wx'):
+ old = 'wx'+old
+ pyFile.write("%s = wx.%s.%s\n" % (old, modname, new))
+
+
+ #---------------------------------------------------------------------------
+
+ def checkOtherNames(self, pyFile, moduleName, filename):
+ if os.path.exists(filename):
+ prefixes = []
+ for line in file(filename):
+ if line.endswith('\n'):
+ line = line[:-1]
+ if line and not line.startswith('#'):
+ if line.endswith('*'):
+ prefixes.append(line[:-1])
+ elif line.find('=') != -1:
+ pyFile.write("%s\n" % line)
+ else:
+ wxname = 'wx' + line
+ if line.startswith('wx') or line.startswith('WX') or line.startswith('EVT'):
+ wxname = line
+ pyFile.write("%s = wx.%s.%s\n" % (wxname, moduleName, line))
+
+ if prefixes:
+ pyFile.write(
+ "\n\nd = globals()\nfor k, v in wx.%s.__dict__.iteritems():"
+ % moduleName)
+ first = True
+ for p in prefixes:
+ if first:
+ pyFile.write("\n if ")
+ first = False
+ else:
+ pyFile.write("\n elif ")
+ pyFile.write("k.startswith('%s'):\n d[k] = v" % p)
+ pyFile.write("\ndel d, k, v\n\n")
+
+
+#---------------------------------------------------------------------------