# codegenUtilitiesAutomatic.py - Utilities for Code Generation with the ElementTree # Library # This code is released under the BSD License below. # # Copyright (c) 2008-2009, Jason Breti (http://breti.org/codegen) # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * The name of the contributor may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #------------------------------------------------------------------------------ import sys import xml.etree.ElementTree as et #------------------------------------------------------------------------------ # This is used to figure out which nodes are implemented or not. # You will also get Not Implemented exceptions when this is set to true debugCodegen = False #------------------------------------------------------------------------------ class CodegenException(Exception): "General error during the codegen processing." def __init__(self, *args): Exception.__init__(self, *args) self.wrapped_exc = sys.exc_info() #------------------------------------------------------------------------------ class CodegenHandler(object): def __init__(self, codegenFactory, thisNode, rootNode): self.codegenFactory = codegenFactory self.thisNode = thisNode self.rootNode = rootNode def process(self): if debugCodegen: print 'CodegenHandler for node', self.thisNode.tag #------------------------------------------------------------------------------ class CodegenHandler_NotImplementedError(CodegenHandler): def process(self): CodegenHandler.process(self) output = "A handler is not implemented for node " + self.thisNode.tag raise CodegenException, output #------------------------------------------------------------------------------ class CodegenHandler_HandleChildNodes(CodegenHandler): def process(self): CodegenHandler.process(self) for node in self.thisNode.getchildren(): object = self.codegenFactory.makeObject(node) object.process() #------------------------------------------------------------------------------ class CodegenHandler_IgnoreNode(CodegenHandler_HandleChildNodes): """ This class does not extend any methods from the base class. """ #------------------------------------------------------------------------------ class CodegenFactory(object): def __init__(self, classPrefix, nodeNotFound, rootNode): self.classPrefix = classPrefix self.nodeNotFound = nodeNotFound self.rootNode = rootNode # Artificially create an exception. This allows Python to use the # traceback facility to gain access to the globals() namespace for the # parent. The parent's globals() namespace contains the list of classes # that can be used by the factory. try: raise CodegenException except CodegenException: # Get the traceback information for the exception namespace (ignore , ignore, traceBack) = sys.exc_info() exceptionTraceBackFrame = traceBack.tb_frame # Get the traceback information for the codegenUtilities parent parentTraceBackFrame = exceptionTraceBackFrame.f_back # Get the traceback information for the codegen parent parentTraceBackFrame = parentTraceBackFrame.f_back # Save the parent's globals() namespace that contains the list of # classes that can be used by the factory. self.nodeLookup = parentTraceBackFrame.f_globals def makeObject(self, node): nodeName = self.classPrefix + node.tag if nodeName in self.nodeLookup: object = self.nodeLookup[nodeName](self, node, self.rootNode) else: object = self.nodeNotFound(self, node, self.rootNode) return object #------------------------------------------------------------------------------ class CodegenPhase(object): nodeNotFound = CodegenHandler_NotImplementedError def __init__(self, rootNode, classPrefix): self.rootNode = rootNode self.classPrefix = classPrefix if not debugCodegen: self.nodeNotFound = CodegenHandler_IgnoreNode self.codegenFactory = \ CodegenFactory(self.classPrefix, self.nodeNotFound, self.rootNode) def process(self): for node in self.rootNode.getchildren(): object = self.codegenFactory.makeObject(node) object.process() #------------------------------------------------------------------------------