(see http://wiki.wxpython.org/index.cgi/pywxrc for more info)
Usage: python pywxrc.py -h
- python pywxrc.py <resource.xrc> [-e] [-g] [-o filename]
+ python pywxrc.py [-p] [-g] [-e] [-o filename] xrc input files...
- -h, --help show help message
- -e, --embed embed resources in the output file
- -g, --gettext embed list of translatable strings in the output file
- -o, --output output filename, or - for stdout
+ -h, --help show help message
+ -p, --python generate python module
+ -g, --gettext output list of translatable strings (may be combined with -p)
+ -e, --embed embed XRC resources in the output file
+ -o, --output output filename, or - for stdout
"""
import sys, os, getopt, glob, re
class PythonTemplates:
FILE_HEADER = """\
# This file was automatically generated by pywxrc, do not edit by hand.
+# -*- coding: UTF-8 -*-
import wx
import wx.xrc as xrc
self.%(widgetName)s = xrc.XRCCTRL(self, \"%(widgetName)s\")
"""
+ MENU_CLASS_HEADER = """\
+class xrc%(windowName)s(wx.%(windowClass)s):
+ def __init__(self):
+ pre = get_resources().LoadMenu("%(windowName)s")
+
+ # This is a copy of Robin's PostCreate voodoo magic in wx.Window that
+ # relinks the self object with the menu object.
+ self.this = pre.this
+ self.thisown = pre.thisown
+ pre.thisown = 0
+ if hasattr(self, '_setOORInfo'):
+ self._setOORInfo(self)
+ if hasattr(self, '_setCallbackInfo'):
+ self._setCallbackInfo(self, self.__class__)
+
+ # Define variables for the menu items
+"""
+
+ CREATE_MENUITEM_VAR = """\
+ self.%(widgetName)s = self.FindItemById(xrc.XRCID(\"%(widgetName)s\"))
+"""
+
INIT_RESOURE_HEADER = """\
# ------------------------ Resource data ----------------------
def __init_resources():
+ global __res
+ __res = xrc.EmptyXmlResource()
"""
LOAD_RES_FILE = """\
- global __res
- __res = xrc.XmlResource('%(resourceFilename)s')
-"""
+ __res.Load('%(resourceFilename)s')"""
FILE_AS_STRING = """\
%(filename)s = '''\\
%(fileData)s'''
-
"""
PREPARE_MEMFS = """\
- # Load all the strings as memory files
-
wx.FileSystem.AddHandler(wx.MemoryFSHandler())
"""
"""
LOAD_RES_MEMFS = """\
- global __res
- __res = xrc.EmptyXmlResource()
__res.Load('memory:XRC/%(memoryPath)s/%(resourceFilename)s')
"""
- GETTEXT_DUMMY_FUNC = """\
+ GETTEXT_DUMMY_FUNC = """
# ----------------------- Gettext strings ---------------------
def __gettext_strings():
def _(str): pass
-%(gettextStrings)s
+%s
"""
#----------------------------------------------------------------------
"""This class generates Python code from XML resource files (XRC)."""
- def MakePythonModule(self, resourceFilename, outputFilename,
+ def MakePythonModule(self, inputFiles, outputFilename,
embedResources=False, generateGetText=False):
- if outputFilename == "-":
- outputFile = sys.stdout
- else:
- try:
- outputFile = open(outputFilename, "wt")
- except IOError:
- raise IOError("Can't write output to '%s'" % outputFilename)
- resourceDocument = minidom.parse(resourceFilename)
+ outputFile = self._OpenOutputFile(outputFilename)
+
+ classes = []
+ resources = []
+ gettextStrings = []
+
+ # process all the inputFiles, collecting the output data
+ for inFile in inputFiles:
+ resourceDocument = minidom.parse(inFile)
+ classes.append(self.GenerateClasses(resourceDocument))
+
+ if embedResources:
+ res = self.GenerateInitResourcesEmbedded(inFile, resourceDocument)
+ else:
+ res = self.GenerateInitResourcesFile(inFile, resourceDocument)
+ resources.append(res)
+
+ if generateGetText:
+ gettextStrings += self.FindStringsInNode(resourceDocument.firstChild)
+
+ # now write it all out
print >>outputFile, self.templates.FILE_HEADER
- print >>outputFile, self.GenerateClasses(resourceDocument)
-
+
+ # Note: Technically it is not legal to have anything other
+ # than ascii for class and variable names, but since the user
+ # can create the XML with non-ascii names we'll go ahead and
+ # allow for it here, and then let Python complain about it
+ # later when they try to run the program.
+ classes = u"\n".join(classes)
+ print >>outputFile, classes.encode("UTF-8")
+
+ print >>outputFile, self.templates.INIT_RESOURE_HEADER
if embedResources:
- print >>outputFile, self.GenerateInitResourcesEmbedded(resourceFilename, resourceDocument)
- else:
- print >>outputFile, self.GenerateInitResourcesFile(resourceFilename, resourceDocument)
+ print >>outputFile, self.templates.PREPARE_MEMFS
+ resources = u"\n".join(resources)
+ print >>outputFile, resources.encode("UTF-8")
if generateGetText:
- print >>outputFile, self.GenerateGetText(resourceDocument)
+ # These have already been converted to utf-8...
+ gettextStrings = [' _("%s")' % s for s in gettextStrings]
+ gettextStrings = "\n".join(gettextStrings)
+ print >>outputFile, self.templates.GETTEXT_DUMMY_FUNC % gettextStrings
+
+ #-------------------------------------------------------------------
+
+ def MakeGetTextOutput(self, inputFiles, outputFilename):
+ """
+ Just output the gettext strings by themselves, with no other
+ code generation.
+ """
+ outputFile = self._OpenOutputFile(outputFilename)
+ for inFile in inputFiles:
+ resourceDocument = minidom.parse(inFile)
+ resource = resourceDocument.firstChild
+ strings = self.FindStringsInNode(resource)
+ strings = ['_("%s");' % s for s in strings]
+ print >>outputFile, "\n".join(strings)
#-------------------------------------------------------------------
windowClass = topWindow.getAttribute("class")
windowClass = re.sub("^wx", "", windowClass)
windowName = topWindow.getAttribute("name")
- outputList.append(self.templates.CLASS_HEADER % locals())
+
+ if windowClass == "Menu":
+ outputList.append(self.templates.MENU_CLASS_HEADER % locals())
+ else:
+ outputList.append(self.templates.CLASS_HEADER % locals())
# Generate a variable for each control, and standard event handlers
# for standard controls.
widgetClass = widget.getAttribute("class")
widgetClass = re.sub("^wx", "", widgetClass)
widgetName = widget.getAttribute("name")
- if (widgetName != "" and widgetClass != "" and
- widgetClass not in
- ['tool', 'unknown', 'notebookpage',
- 'separator', 'sizeritem', 'MenuItem']):
- outputList.append(self.templates.CREATE_WIDGET_VAR % locals())
+ if (widgetName != "" and widgetClass != ""):
+ if widgetClass == "MenuItem":
+ outputList.append(self.templates.CREATE_MENUITEM_VAR % locals())
+ elif widgetClass not in \
+ ['tool', 'unknown', 'notebookpage', 'separator', 'sizeritem']:
+ outputList.append(self.templates.CREATE_WIDGET_VAR % locals())
outputList.append('\n\n')
return "".join(outputList)
#-------------------------------------------------------------------
- def GenerateGetText(self, resourceDocument):
- resource = resourceDocument.firstChild
- strings = self.FindStringsInNode(resource)
- strings = [' _("%s")\n' % s for s in strings]
- gettextStrings = "".join(strings)
- return self.templates.GETTEXT_DUMMY_FUNC % locals()
-
- #-------------------------------------------------------------------
-
def GenerateInitResourcesEmbedded(self, resourceFilename, resourceDocument):
outputList = []
-
- outputList.append(self.templates.INIT_RESOURE_HEADER)
-
files = []
resourcePath = os.path.split(resourceFilename)[0]
self.ReplaceFilenamesInXRC(resourceDocument.firstChild, files, resourcePath)
filename = resourceFilename
- fileData = resourceDocument.toxml()
+ fileData = resourceDocument.toxml() # what about this? encoding=resourceDocument.encoding)
outputList.append(self.templates.FILE_AS_STRING % locals())
for f in files:
fileData = self.FileToString(os.path.join(resourcePath, f))
outputList.append(self.templates.FILE_AS_STRING % locals())
- outputList.append(self.templates.PREPARE_MEMFS % locals())
-
for f in [resourceFilename] + files:
filename = self.GetMemoryFilename(f)
outputList.append(self.templates.ADD_FILE_TO_MEMFS % locals())
# take only the filename portion out of resourceFilename
resourceFilename = os.path.split(resourceFilename)[1]
outputList = []
- outputList.append(self.templates.INIT_RESOURE_HEADER)
outputList.append(self.templates.LOAD_RES_FILE % locals())
return "".join(outputList)
else:
st2 += dt[i]
- return st2
+ return st2.encode("UTF-8")
+
+
+ #-------------------------------------------------------------------
+
+ def _OpenOutputFile(self, outputFilename):
+ if outputFilename == "-":
+ outputFile = sys.stdout
+ else:
+ try:
+ outputFile = open(outputFilename, "wt")
+ except IOError:
+ raise IOError("Can't write output to '%s'" % outputFilename)
+ return outputFile
+
+
def main(args):
resourceFilename = ""
- outputFilename = ""
+ outputFilename = None
embedResources = False
generateGetText = False
+ generatePython = False
try:
- opts, args = getopt.gnu_getopt(args, "hego:", "help embed gettext output=".split())
+ opts, args = getopt.gnu_getopt(args,
+ "hpgeo:",
+ "help python gettext embed output=".split())
except getopt.GetoptError, e:
print "\nError : %s\n" % str(e)
print __doc__
sys.exit(1)
# If there is no input file argument, show help and exit
- if args:
- resourceFilename = args[0]
- else:
+ if not args:
print __doc__
+ print "No xrc input file was specified."
sys.exit(1)
# Parse options and arguments
print __doc__
sys.exit(1)
+ if opt in ["-p", "--python"]:
+ generatePython = True
+
if opt in ["-o", "--output"]:
outputFilename = val
if opt in ["-g", "--gettext"]:
generateGetText = True
- if outputFilename is None or outputFilename == "":
- outputFilename = os.path.splitext(resourceFilename)[0] + "_xrc.py"
+
+ # check for and expand any wildcards in the list of input files
+ inputFiles = []
+ for arg in args:
+ inputFiles += glob.glob(arg)
+
comp = XmlResourceCompiler()
try:
- comp.MakePythonModule(resourceFilename, outputFilename, embedResources, generateGetText)
+ if generatePython:
+ if not outputFilename:
+ outputFilename = os.path.splitext(args[0])[0] + "_xrc.py"
+ comp.MakePythonModule(inputFiles, outputFilename,
+ embedResources, generateGetText)
+
+ elif generateGetText:
+ if not outputFilename:
+ outputFilename = '-'
+ comp.MakeGetTextOutput(inputFiles, outputFilename)
+
+ else:
+ print __doc__
+ print "One or both of -p, -g must be specified."
+ sys.exit(1)
+
+
except IOError, e:
print >>sys.stderr, "%s." % str(e)
else: