# HG changeset patch # User paulb # Date 1105838137 0 # Node ID 86d588cf616cda8596481fb880a9f5b4c59afbba # Parent d9a4838ae8fe5d23bb6bfbaeb8e0b702b2e8672c [project @ 2005-01-16 01:15:37 by paulb] Updated libxml2macro to handle numerous transformation cases. Made the macrotest program much more demanding. diff -r d9a4838ae8fe -r 86d588cf616c libxml2macro.py --- a/libxml2macro.py Sun Jan 16 01:15:01 2005 +0000 +++ b/libxml2macro.py Sun Jan 16 01:15:37 2005 +0000 @@ -1,12 +1,43 @@ #!/usr/bin/env python import compiler +import marshal, imp, os, stat, struct + +# Originally from Analysis/Writers/Python. + +def write_module(module, source_filename, target_filename, syntax_check=1): + + """ + Write the given 'module', associated with the given 'source_filename', to a + file with the given 'target_filename'. The optional 'syntax_check' flag (set + by default) ensures that the module is syntactically correct. + """ + + if syntax_check: + compiler.syntax.check(module) + compiler.misc.set_filename(source_filename, module) + generator = compiler.pycodegen.ModuleCodeGenerator(module) + f = open(target_filename, "wb") + f.write(get_header(source_filename)) + marshal.dump(generator.getCode(), f) + f.close() + +def get_header(filename): + + "Taken from compiler.pycodegen. Prepare the compiled module header." + + MAGIC = imp.get_magic() + mtime = os.stat(filename)[stat.ST_MTIME] + mtime = struct.pack(' Node_attr(node, args) + # fn(node.attr) -> fn(Node_attr(node)) if isinstance(parent, compiler.ast.CallFunc): - parent.node = compiler.ast.Name("Node_%s" % node.attrname) - parent.args.insert(0, compiler.ast.Name(target.name)) + + # If this node is not an argument, transform the call. + + if index is None: + parent.node = compiler.ast.Name("Node_%s" % node.attrname) + parent.args.insert(0, node.expr) + + else: + replacement = compiler.ast.CallFunc( + compiler.ast.Name("Node_%s" % node.attrname), + [node.expr] + ) + parent.args[index] = replacement # Replace plain Getattr nodes: # node.attr -> Node_attr(node) @@ -56,8 +140,41 @@ except TypeError: if value is node: parent.__dict__[key] = replacement + + # Propagate whether the kind of result might need transforming itself. + + return node.attrname + else: process_nodes(node, prefix) + return None + +def propagated_prefix(attrname): + + """ + Return whether the given 'attrname' used in a transformation should be + considered significant at the parent level. + """ + + return attrname in ("ownerElement", "ownerDocument") + +def getattr_has_prefix(node, prefix): + + """ + Determine whether the given Getattr 'node' employs the special 'prefix' in a + number of ways. + """ + + # Check the expression as a simple name: + # node.attr + if isinstance(node.expr, compiler.ast.Name) and node.expr.name.startswith(prefix): + return 1 + # Check the attribute name of child expressions: + # (obj.node).attr + elif isinstance(node.expr, compiler.ast.Getattr) and node.expr.attrname.startswith(prefix): + return 1 + else: + return 0 def process_file(filename, prefix="x2_"): @@ -73,6 +190,17 @@ # Find references to special variables. process_nodes(module, prefix) + + # Write the module. + + write_module(module, filename, os.path.splitext(filename)[0] + ".pyc") return module +if __name__ == "__main__": + import sys + if len(sys.argv) < 2: + print "libxml2macro.py " + sys.exit(1) + process_file(sys.argv[1]) + # vim: tabstop=4 expandtab shiftwidth=4 diff -r d9a4838ae8fe -r 86d588cf616c macrotest.py --- a/macrotest.py Sun Jan 16 01:15:01 2005 +0000 +++ b/macrotest.py Sun Jan 16 01:15:37 2005 +0000 @@ -5,15 +5,79 @@ from libxml2dom.macrolib import * import libxml2 import xml.dom -import sys + +class Container: + pass + +doc = """ + + + + + +""" + +def find_root(x2_d): + x2_root = None + + # Property access should be transformed. + + for x2_n in x2_d.childNodes: + if x2_n.nodeType == xml.dom.Node.ELEMENT_NODE: + x2_root = x2_n + break + + return x2_root + +def test(): + global doc + + # Assignment should not be transformed. + + x2_d = parseString(doc) + + # Not even within containers, and not special names alone. + + c = Container() + c.x2_d = x2_d -x2_d = libxml2.parseFile(sys.argv[1]) -x2_root = None -for x2_n in x2_d.childNodes: - if x2_n.nodeType == xml.dom.Node.ELEMENT_NODE: - x2_root = x2_n - break + # Find the root element. + + x2_root = find_root(x2_d) + c.x2_root = x2_root + + # Create new attributes. + # Method access should be transformed. + + x2_root.setAttributeNS("ns", "xxx:yyy", "zzz") + c.x2_root.setAttributeNS("ns", "XXX:YYY", "ZZZ") + + # Create new elements. + # Method access should be transformed. + + x2_new = x2_d.createElementNS("ns2", "ppp:qqq") + x2_root.appendChild(x2_new) + x2_new2 = c.x2_d.createElementNS("ns2", "PPP:QQQ") + c.x2_root.appendChild(x2_new2) -print x2_root.localName, x2_root.namespaceURI, x2_root.getAttributeNS(None, "xmlns") + # Create new elements using ownerDocument. + # Chaining properties is not + + x2_new3 = x2_new.ownerDocument.createElement("fff") + x2_new.appendChild(x2_new3) + x2_new4 = x2_new2.ownerDocument.createElement("FFF") + x2_new2.appendChild(x2_new4) + + # Create a new document. + + x2_d2 = createDocument("nsD", "newdoc", None) + x2_root2 = find_root(x2_d2) + + # Attempt to import nodes from the original document. + + x2_imported = x2_d2.importNode(x2_root, 1) + x2_d2.replaceChild(x2_imported, x2_root2) + + return x2_d, x2_d2 # vim: tabstop=4 expandtab shiftwidth=4