]> git.saurik.com Git - wxWidgets.git/commitdiff
Run swig from the main setup.py when building the renamer's XML
authorRobin Dunn <robin@alldunn.com>
Thu, 11 Dec 2003 20:03:42 +0000 (20:03 +0000)
committerRobin Dunn <robin@alldunn.com>
Thu, 11 Dec 2003 20:03:42 +0000 (20:03 +0000)
instead of from build_renamers.py.  This makes it easy to ensure that
the same flags are used.  Also, use the new swig flag to generate the
XML after the python language module has run, rather than instead of.
This gives us more info in the xml output.

Updated build_renamers.py to expect the xml file to already be
generated, and also allow it to run with a xml doc tree from libxml2
rather than the xml.sax module.  This makes the extraction of info
much cleaner and logical since we usually need info from child or
grandchild nodes.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24780 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/distrib/build_renamers.py
wxPython/setup.py

index 03f043a8d60e8b86ce2536fece78a6ffc3ebd816..022051b8dc0c787600fb3e6e2da153e85da1a535 100755 (executable)
@@ -1,12 +1,12 @@
 #!/usr/bin/env python
 #---------------------------------------------------------------------------
 """
-Usage:  build_renamers.py filename.i
+Usage:  build_renamers.py destdir modulename filename.xml
 
-Run SWIG on file.i using the XML language module and then scan the XML
-file produced and generate the %rename directives needed to implement
-the new wx namespace.  The rename directives are output in a file
-named _filename_rename.i in the same dir as filename.i.
+Scans the XML file produced by SWIG (see setup.py) and generate the
+%rename directives needed to implement the new wx namespace.  The
+rename directives are output in a file named _modulename_rename.i in
+the destdir given.
 
 Also output a reverse 'renamer' Python module located in
 wxPython/filename.py (relative the the current dir) to make a
@@ -14,37 +14,25 @@ backwards compatibility interface for the old wxPython packages.
 """
 
 import sys, os, tempfile, pprint
-import xml.sax
+import xml.sax            
 from distutils.spawn import spawn
 
-
-
-#---------------------------------------------------------------------------
-
-DO_UNLINK = True
+try:
+    import libxml2
+    USE_LIBXML2 = True
+except ImportError:
+    USE_LIBXML2 = False
 
 wxPythonDir = "wxPython"
-swig_cmd = "/opt/swig/bin/swig"
-if os.name == 'nt':
-    swig_cmd = 'e:/projects/SWIG-cvs/swig.exe'
 
-swig_args = ['-c++',
-             '-Wall',
-             '-nodefault',
-
-             '-xml',
-             '-xmllite',
-
-             '-I./src',
-             '-noruntime'
-             ]
+#---------------------------------------------------------------------------
 
 
 renamerTemplateStart = """\
 // A bunch of %%rename directives generated by %s
 // in order to remove the wx prefix from all global scope names.
 
-#ifndef SWIGXML
+#ifndef BUILDING_RENAMERS
 
 """
 
@@ -86,7 +74,7 @@ wxPythonTemplateEnd = """
 
 def main(args):
     # check args
-    if len(args) < 1:
+    if len(args) < 3:
         print __doc__
         sys.exit(1)
 
@@ -97,69 +85,147 @@ def main(args):
         sys.exit(1)
         
 
-    source = args[0]
-    sourcePath, sourceBase = os.path.split(source)
-    sourceBase = os.path.splitext(sourceBase)[0]
-
-    tempfile.tempdir = sourcePath
-    xmlDest = tempfile.mktemp('.xml')
-    swigDest = os.path.join(sourcePath, "_"+sourceBase+"_rename.i")
-    pyDest = os.path.join(wxPythonDir, sourceBase + '.py')
-
-    #print "source:      ", source
-    #print "xmlDest:     ", xmlDest
-    #print "swigDest:    ", swigDest
-    #print "pyDest:      ", pyDest
-
-    cmd = [ swig_cmd ] + swig_args + args[1:] + ['-I'+sourcePath, '-o', xmlDest, source]
-    print ' '.join(cmd)
-    spawn(cmd)
+    destdir = args[0]
+    modname = args[1]
+    xmlfile = args[2]
+    
+    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 % sys.argv[0])
 
-    pyFile = open(pyDest, "w")
-    pyFile.write(wxPythonTemplateStart % (sys.argv[0], sourceBase))
-    
-    print "Parsing and building renamers", 
+    pyDestTemp = tempfile.mktemp('.tmp')
+    pyFile = open(pyDestTemp, "w")
+    pyFile.write(wxPythonTemplateStart % (sys.argv[0], modname))
+
     try:
-##         try:
-##             import libxml2
-##             print "using libxml2..."
-##             ctxt = libxml2.createPushParser(ContentHandler(source, sourceBase, swigFile, pyFile),
-##                                             '', 0, xmlDest)
-##             for line in file(xmlDest):
-##                 if not line:
-##                     ctxt.parseChunck('', 0, 1)
-##                     break
-##                 ctxt.parseChunk(line, len(line), 0)
-                
-##         except ImportError:
-        print "using xml.sax..."
-        xml.sax.parse(xmlDest, ContentHandler(source, sourceBase, swigFile, pyFile))
+        print "Parsing and building renamers", 
+        if USE_LIBXML2:
+            processXML(xmlfile, modname, swigFile, pyFile)
+        else:
+            print "using xml.sax..."
+            xml.sax.parse(xmlfile, ContentHandler(modname, swigFile, pyFile))
 
     finally:
-        checkOtherNames(pyFile, sourceBase,
-                        os.path.join(sourcePath, '_'+sourceBase+'_reverse.txt'))
+
+        checkOtherNames(pyFile, modname,
+                        os.path.join(destdir, '_'+modname+'_reverse.txt'))
         pyFile.write(wxPythonTemplateEnd)        
         pyFile.close()
 
         swigFile.write(renamerTemplateEnd)
         swigFile.close()
 
-        # Compare the file just created with the existing one and
+        # Compare the files just created with the existing one and
         # blow away the old one if they are different.
-        if open(swigDest).read() != open(swigDestTemp).read():
-            os.unlink(swigDest)
-            os.rename(swigDestTemp, swigDest)
-        else:
-            print swigDest + " not changed."
-            os.unlink(swigDestTemp)
+        for dest, temp in [(swigDest, swigDestTemp),
+                           (pyDest, pyDestTemp)]:
+            if open(dest).read() != open(temp).read():
+                os.unlink(dest)
+                os.rename(temp, dest)
+            else:
+                print dest + " not changed."
+                os.unlink(temp)
+
+#---------------------------------------------------------------------------
+
+
+def GetAttr(node, name):
+    path = "./attributelist/attribute[@name='%s']/@value" % name
+    n = node.xpathEval(path)
+    if len(n):
+        return n[0].content
+    else:
+        return None
+    
+
+def processXML(xmlfile, modname, swigFile, pyFile):
+    import libxml2
+    print "using libxml2..."
+
+    topnode = libxml2.parseFile(xmlfile).children
+
+    # remove any import nodes as we don't need to do renamers for symbols found therein
+    imports = topnode.xpathEval("*/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 DO_UNLINK:
-            os.unlink(xmlDest)
 
+        if node.name == "class":
+            lastClassName = name = GetAttr(node, "name")
+            lastClassSymName = sym_name = GetAttr(node, "sym_name")
+            doRename = True
+            doPtr = True
+            if sym_name != name:
+                name = sym_name
+                addWX = True
+
+        # renamed constructors
+        elif node.name == "constructor":
+            name     = GetAttr(node, "name")
+            sym_name = 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     = GetAttr(node, "name")
+            sym_name = GetAttr(node, "sym_name")
+            doRename = True
+
+
+        elif node.name in ["cdecl", "constant"]:
+            name      = GetAttr(node, "name")
+            sym_name  = GetAttr(node, "sym_name")
+            toplevel  = node.parent.name == "include"
+
+            # top-level functions
+            if toplevel and GetAttr(node, "view") == "globalfunctionHandler":
+                doRename = True
+
+            # top-level global vars
+            elif toplevel and GetAttr(node, "feature_immutable") == "1":
+                doRename = True
+
+            # static methods
+            elif 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:
+            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))
+            
 
 #---------------------------------------------------------------------------
 
@@ -304,10 +370,9 @@ class Element:
 #---------------------------------------------------------------------------
 
 class ContentHandler(xml.sax.ContentHandler):
-    def __init__(self, source, sourceBase, swigFile, pyFile):
+    def __init__(self, modname, swigFile, pyFile):
         xml.sax.ContentHandler.__init__(self)
-        self.source = source
-        self.sourceBase = sourceBase
+        self.modname = modname
         self.swigFile = swigFile
         self.pyFile   = pyFile
         self.elements = []
@@ -398,7 +463,7 @@ class ContentHandler(xml.sax.ContentHandler):
             
             if self.imports == 0:
                 # only write for items that are in this file, not imported
-                ce.write(self.sourceBase, self.swigFile, self.pyFile)
+                ce.write(self.modname, self.swigFile, self.pyFile)
             
         if name == 'import':
             self.imports -= 1
index 09b44e21922a5a01814975f6299195e0d22fb943..ba32bc46af702fb570c1fae2cc5e856dc23dcc5d 100755 (executable)
@@ -246,6 +246,9 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=
     if not os.path.exists(os.path.join(dir, gendir)):
         os.mkdir(os.path.join(dir, gendir))
 
+    if not os.path.exists(os.path.join("docs", "xml-raw")):
+        os.mkdir(os.path.join("docs", "xml-raw"))
+
     sources = []
 
     for file in files:
@@ -253,6 +256,7 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=
         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')
 
         sources.append(cpp_file)
 
@@ -268,13 +272,27 @@ 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:
-                    # first run build_renamers
+                    #info_file = "./distrib/swig_info"
+                    #info_dict = { 'cmd'  : swig_cmd,
+                    #              'args' : swig_args +  ['-I'+dir]
+                    #              }
+                    #open(info_file, "w").write(str(args_dict))
+
+                    # First run swig to produce the XML file, adding
+                    # an extra -D that prevents the old rename
+                    # directives from being used
+                    cmd = [ swig_cmd ] + swig_args + \
+                          [ '-DBUILDING_RENAMERS', '-xmlout', xml_file ] + \
+                          ['-I'+dir, '-o', cpp_file, i_file]
+                    msg(' '.join(cmd))
+                    spawn(cmd)
+
+                    # Next run build_renamers to process the XML
                     cmd = [ sys.executable, '-u',
-                            './distrib/build_renamers.py',
-                            i_file, '-D'+WXPLAT, ] + \
-                            [x for x in swig_args if x.startswith('-I')]
+                            './distrib/build_renamers.py', dir, basefile, xml_file] 
                     msg(' '.join(cmd))
                     spawn(cmd)
+                    #os.remove(info_file)
 
                 # Then run swig for real
                 cmd = [ swig_cmd ] + swig_args + ['-I'+dir, '-o', cpp_file, i_file]