X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9896cf5ef76d288f30084786fe064c706002504a..015fd9ef4833ec3d8b0043a1c7e448c8be4f734a:/wxPython/config.py diff --git a/wxPython/config.py b/wxPython/config.py index 937fdf189c..04a6739ad4 100644 --- a/wxPython/config.py +++ b/wxPython/config.py @@ -31,15 +31,461 @@ import distutils.command.install_data import distutils.command.install_headers import distutils.command.clean +#################################### +# BuildRenamers +#################################### + +import pprint +import xml.sax +from distutils.spawn import spawn + +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)]: + if not os.path.exists(dest): + os.rename(temp, dest) + elif open(dest).read() != open(temp).read(): + os.unlink(dest) + os.rename(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 + doPtr = 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 + doPtr = 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)) + if doPtr: + pyFile.write("%sPtr = wx.%s.%sPtr\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") + + +#--------------------------------------------------------------------------- + +## interestingTypes = [ 'class', 'cdecl', 'enumitem', 'constructor', 'constant' ] +## interestingAttrs = [ 'name', 'sym_name', 'decl', 'feature_immutable', 'module', +## 'storage', 'type' ] + + +## class Element: +## def __init__(self, tagtype): +## self.tagtype = tagtype +## self.level = -1 +## self.name = None +## self.sym_name = None +## self.decl = None +## self.immutable = None +## self.klass = None +## self.module = None +## self.storage = None +## self.type = None +## self.startLine = -1 + + +## def write(self, moduleName, swigFile, pyFile): +## doRename = False +## doPtr = False +## addWX = False +## revOnly = False + +## #if self.name.find('DefaultPosition') != -1: +## # pprint.pprint(self.__dict__) + +## if self.tagtype in ['cdecl', 'constant']: +## if self.storage == 'typedef': +## pass + +## # top level functions +## elif self.level == 0 and self.decl != "": +## doRename = True + +## # top level global vars +## elif self.level == 0 and self.immutable == '1': +## doRename = True + +## # static methods +## elif self.storage == 'static': +## if not self.klass: +## pprint.pprint(self.__dict__) +## else: +## self.name = self.klass + '_' + self.name +## self.sym_name = self.sym_klass + '_' + self.sym_name +## # only output the reverse renamer in this case +## doRename = revOnly = True + + + +## if doRename and self.name != self.sym_name: +## #print "%-25s %-25s" % (self.name, self.sym_name) +## self.name = self.sym_name +## addWX = True + + +## elif self.tagtype == 'class' and self.module == moduleName: +## doRename = True +## doPtr = True +## if self.sym_name != self.klass: +## #print self.sym_name +## self.name = self.sym_name +## addWX = True + +## elif self.tagtype == 'constructor': +## #print "%-25s %-25s" % (self.name, self.sym_name) +## if self.sym_name != self.klass: +## #print self.sym_name +## self.name = self.sym_name +## addWX = True +## doRename = True + +## elif self.tagtype == 'enumitem' and self.level == 0: +## doRename = True + + +## if doRename: +## #print "%-25s %-25s" % (self.name, self.sym_name) +## old = new = self.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, moduleName, new)) +## if doPtr: +## pyFile.write("%sPtr = wx.%s.%sPtr\n" % (old, moduleName, new)) + + + +## #else: +## # text = "%07d %d %10s %-35s %s\n" % ( +## # self.startLine, self.level, self.tagtype, self.name, self.decl) +## # #rejects.write(text) +## # print text, + + +## #--------------------------------------------------------------------------- + +## class ContentHandler(xml.sax.ContentHandler): +## def __init__(self, modname, swigFile, pyFile): +## xml.sax.ContentHandler.__init__(self) +## self.modname = modname +## self.swigFile = swigFile +## self.pyFile = pyFile +## self.elements = [] +## self.imports = 0 +## self.klass = None +## self.sym_klass = None + + +## def setDocumentLocator(self, locator): +## self.locator = locator + + + +## def startElement(self, name, attrs): +## if name in interestingTypes: +## # start of a new element that we are interested in +## ce = Element(name) +## ce.startLine = self.locator.getLineNumber() +## ce.level = len(self.elements) +## if name == 'constructor': +## ce.klass = self.elements[0].name +## else: +## ce.klass = self.klass +## ce.sym_klass = self.sym_klass +## self.elements.insert(0, ce) + + +## elif len(self.elements) and name == 'attribute' and attrs['name'] in interestingAttrs: +## attrName = attrs['name'] +## attrVal = attrs['value'] +## if attrName.startswith('feature_'): +## attrName = attrName.replace('feature_', '') +## ce = self.elements[0] +## if getattr(ce, attrName) is None: +## setattr(ce, attrName, attrVal) +## if ce.tagtype == 'class' and attrName == 'name' and self.klass is None: +## self.klass = attrVal +## if ce.tagtype == 'class' and attrName == 'sym_name' and self.sym_klass is None: +## self.sym_klass = attrVal + + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'name': +## ## # save the elements name +## ## ce = self.elements[0] +## ## if ce.name is None: +## ## ce.name = attrs['value'] +## ## ce.nameLine = self.locator.getLineNumber() + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'sym_name': +## ## # save the elements name +## ## ce = self.elements[0] +## ## if ce.sym_name is None: +## ## ce.sym_name = attrs['value'] + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'decl': +## ## # save the elements decl +## ## ce = self.elements[0] +## ## ce.decl = attrs['value'] + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'feature_immutable': +## ## # save the elements decl +## ## ce = self.elements[0] +## ## ce.immutable = int(attrs['value']) + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'module': +## ## # save the elements decl +## ## ce = self.elements[0] +## ## ce.module = attrs['value'] + +## elif name == 'import': +## self.imports += 1 + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'storage': +## ## # save the elements decl +## ## ce = self.elements[0] +## ## ce.storage = attrs['value'] + +## ## elif len(self.elements) and name == 'attribute' and attrs['name'] == 'type': +## ## # save the elements decl +## ## ce = self.elements[0] +## ## ce.type = attrs['value'] + + +## def endElement(self, name): +## if name in interestingTypes: +## # end of an element that we are interested in +## ce = self.elements.pop(0) + +## if self.imports == 0: +## # only write for items that are in this file, not imported +## ce.write(self.modname, self.swigFile, self.pyFile) + +## if name == 'import': +## self.imports -= 1 + +## if name == 'class': +## self.klass = None +## self.sym_klass = None + + +#--------------------------------------------------------------------------- #---------------------------------------------------------------------- # flags and values that affect this script #---------------------------------------------------------------------- VER_MAJOR = 2 # The first three must match wxWidgets VER_MINOR = 5 -VER_RELEASE = 1 -VER_SUBREL = 3 # wxPython release num for x.y.z release of wxWidgets -VER_FLAGS = "" # release flags, such as prerelease num, unicode, etc. +VER_RELEASE = 2 +VER_SUBREL = 2 # wxPython release num for x.y.z release of wxWidgets +VER_FLAGS = "p" # release flags, such as prerelease num, unicode, etc. DESCRIPTION = "Cross platform GUI toolkit for Python" AUTHOR = "Robin Dunn" @@ -87,7 +533,7 @@ BUILD_DLLWIDGET = 0# Build a module that enables unknown wx widgets # Internet Explorer wrapper (experimental) BUILD_IEWIN = (os.name == 'nt') -BUILD_ACTIVEX = (os.name == 'nt') # new version of IEWIN +BUILD_ACTIVEX = (os.name == 'nt') # new version of IEWIN and more CORE_ONLY = 0 # if true, don't build any of the above @@ -101,6 +547,11 @@ SWIG = "swig" # The swig executable to use. BUILD_RENAMERS = 1 # Should we build the renamer modules too? +FULL_DOCS = 0 # Some docstrings are split into a basic docstring and a + # details string. Setting this flag to 1 will + # cause the two strings to be combined and output + # as the full docstring. + UNICODE = 0 # This will pass the 'wxUSE_UNICODE' flag to SWIG and # will ensure that the right headers are found and the # right libs are linked. @@ -154,16 +605,19 @@ HYBRID = 1 # If set and not debug or FINAL, then build a # Version part of wxWidgets LIB/DLL names WXDLLVER = '%d%d' % (VER_MAJOR, VER_MINOR) +WXPY_SRC = '.' # Assume we're in the source tree already, but allow the + # user to change it, particularly for extension building. + #---------------------------------------------------------------------- def msg(text): - if sys.setup_is_main: + if hasattr(sys, 'setup_is_main') and sys.setup_is_main: print text def opj(*args): - path = apply(os.path.join, args) + path = os.path.join(*args) return os.path.normpath(path) @@ -211,6 +665,7 @@ for flag in ['BUILD_GLCANVAS', 'BUILD_OGL', 'BUILD_STC', 'BUILD_XRC', 'BUILD_GIZMOS', 'BUILD_DLLWIDGET', 'BUILD_IEWIN', 'BUILD_ACTIVEX', 'CORE_ONLY', 'PREP_ONLY', 'USE_SWIG', 'UNICODE', 'UNDEF_NDEBUG', 'NO_SCRIPTS', 'NO_HEADERS', 'BUILD_RENAMERS', + 'FULL_DOCS', 'FINAL', 'HYBRID', ]: for x in range(len(sys.argv)): if sys.argv[x].find(flag) == 0: @@ -221,7 +676,7 @@ for flag in ['BUILD_GLCANVAS', 'BUILD_OGL', 'BUILD_STC', 'BUILD_XRC', # String options for option in ['WX_CONFIG', 'WXDLLVER', 'BUILD_BASE', 'WXPORT', 'SWIG', - 'CONTRIBS_INC']: + 'CONTRIBS_INC', 'WXPY_SRC']: for x in range(len(sys.argv)): if sys.argv[x].find(option) == 0: pos = sys.argv[x].find('=') + 1 @@ -274,24 +729,35 @@ def Verify_WX_CONFIG(): -def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=[]): +def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, + swig_deps=[], add_under=False): """Run SWIG the way I want it done""" if USE_SWIG and not os.path.exists(os.path.join(dir, gendir)): os.mkdir(os.path.join(dir, gendir)) if USE_SWIG and not os.path.exists(os.path.join("docs", "xml-raw")): + if not os.path.exists("docs"): + os.mkdir("docs") os.mkdir(os.path.join("docs", "xml-raw")) sources = [] + if add_under: pre = '_' + else: pre = '' + for file in files: basefile = os.path.splitext(file)[0] i_file = os.path.join(dir, file) - py_file = os.path.join(dir, gendir, basefile+'.py') - cpp_file = os.path.join(dir, gendir, basefile+'_wrap.cpp') - xml_file = os.path.join("docs", "xml-raw", basefile+'_swig.xml') + py_file = os.path.join(dir, gendir, pre+basefile+'.py') + cpp_file = os.path.join(dir, gendir, pre+basefile+'_wrap.cpp') + xml_file = os.path.join("docs", "xml-raw", basefile+pre+'_swig.xml') + if add_under: + interface = ['-interface', '_'+basefile+'_'] + else: + interface = [] + sources.append(cpp_file) if not cleaning and USE_SWIG: @@ -306,7 +772,6 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps= #i_file = opj(i_file) #'/'.join(i_file.split('\\')) if BUILD_RENAMERS: - #tempfile.tempdir = sourcePath xmltemp = tempfile.mktemp('.xml') # First run swig to produce the XML file, adding @@ -319,15 +784,13 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps= spawn(cmd) # Next run build_renamers to process the XML - cmd = [ sys.executable, '-u', - './distrib/build_renamers.py', dir, basefile, xmltemp] - msg(' '.join(cmd)) - spawn(cmd) + myRenamer = BuildRenamers() + myRenamer.run(dir, pre+basefile, xmltemp) os.remove(xmltemp) # Then run swig for real - cmd = [ swig_cmd ] + swig_args + ['-I'+dir, '-o', cpp_file, - '-xmlout', xml_file, i_file] + cmd = [ swig_cmd ] + swig_args + interface + \ + ['-I'+dir, '-o', cpp_file, '-xmlout', xml_file, i_file] msg(' '.join(cmd)) spawn(cmd) @@ -408,7 +871,7 @@ class wx_install_headers(distutils.command.install_headers.install_headers): return root = self.root - if WXPREFIX.startswith(root): + if root is None or WXPREFIX.startswith(root): root = '' for header, location in headers: install_dir = os.path.normpath(root + WXPREFIX + location) @@ -705,6 +1168,9 @@ if UNICODE: BUILD_BASE = BUILD_BASE + '.unicode' VER_FLAGS += 'u' +if os.path.exists('DAILY_BUILD'): + + VER_FLAGS += '.' + open('DAILY_BUILD').read().strip() VERSION = "%s.%s.%s.%s%s" % (VER_MAJOR, VER_MINOR, VER_RELEASE, VER_SUBREL, VER_FLAGS) @@ -725,16 +1191,20 @@ swig_args = ['-c++', '-new_repr', '-modern', - '-I./src', + '-I' + opj(WXPY_SRC, 'src'), '-D'+WXPLAT, '-noruntime' ] if UNICODE: swig_args.append('-DwxUSE_UNICODE') -swig_deps = [ 'src/my_typemaps.i', - 'src/common.swg', - 'src/pyrun.swg', +if FULL_DOCS: + swig_args.append('-D_DO_FULL_DOCS') + + +swig_deps = [ opj(WXPY_SRC, 'src/my_typemaps.i'), + opj(WXPY_SRC, 'src/common.swg'), + opj(WXPY_SRC, 'src/pyrun.swg'), ] depends = [ #'include/wx/wxPython/wxPython.h',