From fb48f82574f51c3e345d3fb711100ac07c16c5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eray=20=C3=96zkural?= Date: Fri, 23 Sep 2005 17:44:21 +0000 Subject: [PATCH] * get encoding to work a bit, not there yet... so many changes to list :( --- pisi/xmlext.py | 7 ++- pisi/xmlfile.py | 119 +++++++++++++++++++++++------------------- tests/xmlfiletests.py | 4 +- 3 files changed, 74 insertions(+), 56 deletions(-) diff --git a/pisi/xmlext.py b/pisi/xmlext.py index f3dfe6e2..a97de5f2 100644 --- a/pisi/xmlext.py +++ b/pisi/xmlext.py @@ -31,7 +31,8 @@ def getNodeAttribute(node, attrname): return node.getAttribute(attrname) def getTagByName(parent, childName): - return [x for x in parent.childNodes if x.nodeType == x.ELEMENT_NODE if x.tagName == childName] + return [x for x in parent.childNodes + if x.nodeType == x.ELEMENT_NODE if x.tagName == childName] def getNodeText(node, tagpath = ""): """get the first child and expect it to be text!""" @@ -131,6 +132,10 @@ def addNode(dom, node, tagpath, newnode = None): tags = [] if tagpath != "": tags = tagpath.split('/') # tag chain + else: + addTagPath(dom, node, [], newnode) + return node + assert len(tags)>0 # we want a chain # iterative code to search for the path diff --git a/pisi/xmlfile.py b/pisi/xmlfile.py index d3e91b68..285a387b 100644 --- a/pisi/xmlfile.py +++ b/pisi/xmlfile.py @@ -163,6 +163,7 @@ class autoxml(type): """ def __init__(cls, name, bases, dict): + """entry point for metaclass code""" print 'generating class', name # add XmlFile as one of the superclasses, we're smart @@ -202,6 +203,7 @@ class autoxml(type): # generate top-level helper functions cls.initializers = inits def initialize(self): +# XmlFile.__init__(self, cls.tag) for init in self.__class__.initializers: init(self) cls.__init__ = initialize @@ -217,6 +219,7 @@ class autoxml(type): node = xml.newNode(cls.tag) for encode_member in self.__class__.encoders: encode_member(self, xml, node) + xml.dom.documentElement = node return node cls.encode = encode @@ -238,33 +241,42 @@ class autoxml(type): assert type(tag_type) == type(type) def readtext(node, attr): return getNodeAttribute(node, attr) - def createnode(xml, attr): - return xml.newAttribute(attr) - def writetext(node, attr, text): + def createnode(xml, attr_name): + return xml.newAttribute(attr_name) # create an attribute node + def writetext(xml, attr, nil, text): attr.value = text - node.setAttributeNode(attr) anonfuns = cls.gen_anon_basic(attr, spec, readtext, createnode, writetext) def mergetext(node, attr): - pass + node.setAttributeNode(node, attr) return cls.gen_named_comp(attr, spec, anonfuns, mergetext) def gen_tag_member(cls, tag): """generate helper funs for tag member of class""" spec = getattr(cls, 't_' + tag) - def readtext(node, tagpath): - return getNodeText(getNode(node, tagpath)) - def createnode(xml, tag): - return xml.newNode(tag) - def writetext(node, text): - node.addText(node, text) - anonfuns = cls.gen_tag(tag, spec, createnode, readtext, writetext) - def mergetext(xml, node, tagpath): - pass - head, tail = cls.tagpath_head_last(tagpath) - subnode = xml.newNode(tail) + anonfuns = cls.gen_tag(tag, spec) + def mergetext(node, newnode): + print 'mergenode', node, newnode + node.appendChild(newnode) return cls.gen_named_comp(tag, spec, anonfuns, mergetext) - def gen_named_comp(cls, token, spec, anonfuns, createnode): + def gen_tag(cls, tag, spec): + """generate readers and writers for the tag""" + tag_type = spec[0] + if type(tag_type) is types.TypeType: + def readtext(node, tagpath): + return getNodeText(node, tagpath) + def createnode(xml, tag): + return xml.newNode(tag) + def writetext(xml, node, tagpath, text): + xml.addTextNodeUnder(node, tagpath, text) + return cls.gen_anon_basic(tag, spec, readtext, + createnode, writetext) + elif type(tag_type) is types.ListType: + return cls.gen_list_tag(tag, spec) + elif type(tag_type) is autoxml or type(tag_type) is types.ClassType: + return cls.gen_class_tag(tag, spec) + + def gen_named_comp(cls, token, spec, anonfuns, mergetext): """generate a named component tag/attr. a decoration of anonymous functions that do not bind to variable names""" name = cls.mixed_case(token) @@ -286,7 +298,9 @@ class autoxml(type): value = getattr(self, name) else: value = None - return encode_a(xml, self.dom.documentElement, value) + newnode = encode_a(xml, value) + if newnode: + mergetext(node, newnode) def format(self): if hasattr(self, name): @@ -299,28 +313,20 @@ class autoxml(type): return (init, decode, encode, format) - def gen_tag(cls, tag, spec, readtext, createnode, writetext): - """generate readers and writers for the tag""" - tag_type = spec[0] - if type(tag_type) is types.TypeType: - return cls.gen_anon_basic(tag, spec, readtext, createnode, writetext) - elif type(tag_type) is types.ListType: - return cls.gen_list_tag(tag, spec) - elif type(tag_type) is autoxml or type(tag_type) is types.ClassType: - return cls.gen_class_tag(tag, spec) - def mixed_case(cls, identifier): """helper function to turn token name into mixed case""" - identifier_p = identifier[0].lower() + identifier[1:] - return identifier_p + if identifier is "": + return "" + else: + return identifier[0].lower() + identifier[1:] - def tagpath_head_last(cls, tag_path): + def tagpath_head_last(cls, tagpath): "returns split of the tag path into last tag and the rest" try: lastsep = tagpath.rindex('/') except ValueError, e: - return ('', tag_path) - return (tag_path[:laststep], tag_path[laststep+1:]) + return ('', tagpath) + return (tagpath[:lastsep], tagpath[lastsep+1:]) def parse_spec(cls, token, spec): """decompose member specification""" @@ -364,12 +370,12 @@ class autoxml(type): else: return None - def encode(xml, node, value): + def encode(xml, value): """encode given value inside DOM node""" if value: - path = cls.tagpath_head_last(tagpath) - node = createnode(xml, token) - writetext(node, str(value)) + head, last = cls.tagpath_head_last(tagpath) + node = createnode(xml, last) + writetext(xml, node, head, str(value)) return node else: if req == mandatory: @@ -424,17 +430,19 @@ class autoxml(type): def gen_list_tag(cls, tag, spec): """generate a list datatype""" name, tag_type, req, path = cls.parse_spec(tag, spec) + head, last = cls.tagpath_head_last(path) + if len(tag_type) != 1: raise Error('List type must contain only one element') - def readtext(node, tagpath): - return getNodeText(getNode(node, tagpath)) - def createnode(xml, tag): - return xml.newNode(tag) - def writetext(node, text): - node.addText(node, text) - x = cls.gen_tag(tag, [tag_type[0], mandatory], - readtext, createnode, writetext) +# def readtext(node, tagpath): +# print 'shit', node, tagpath +# return getNodeText(node) +# def createnode(xml, tag): +# return xml.newNode(last) +# def writetext(node, text): +# node.addText(node, text) + x = cls.gen_tag(last, [tag_type[0], mandatory]) (init_item, decode_item, encode_item, format_item) = x def init(): @@ -447,16 +455,18 @@ class autoxml(type): if len(nodes) is 0 and req is mandatory: raise Error('Mandatory list empty') for node in nodes: - l.append(decode_item(node)) + dummy = node.ownerDocument.createElement(last) + dummy.appendChild(node) + l.append(decode_item(dummy)) return l - def encode(xml, node, l): - if len(l) > 0: + def encode(xml, l): + dummy = xml.newNode("Dummy") + if len(l) > 0: for item in l: - item_node = xml.newNode(path) - encode_item(xml, item, item_node) - xml.addTextNodeUnder(item_node) - return node + item_node = encode_item(xml, item) + xml.addNodeUnder(dummy, last, item_node) + return getNode(dummy, "Dummy") else: if req is mandatory: raise Error('Mandatory list empty') @@ -519,11 +529,11 @@ class XmlFile(object): return self.dom.createTextNode(text) def newAttribute(self, attr): - return self.dom.createAttribute(name) + return self.dom.createAttribute(attr) # read helpers - def getNode(self, tagPath): + def getNode(self, tagPath = ""): """returns the *first* matching node for given tag path.""" self.verifyRootTag() return getNode(self.dom.documentElement, tagPath) @@ -590,4 +600,5 @@ class XmlFile(object): def addTextNodeUnder(self, node, tagPath, text): "add a text node under given node with tag path (phew)" + print "addtextnodeunder", node, tagPath, text return self.addNodeUnder(node, tagPath, self.newTextNode(text)) diff --git a/tests/xmlfiletests.py b/tests/xmlfiletests.py index 976fb730..e58bb819 100644 --- a/tests/xmlfiletests.py +++ b/tests/xmlfiletests.py @@ -56,8 +56,10 @@ class XmlFileTestCase(unittest.TestCase): print '*', string #self.assert_(string.startswith('Name')) xml = xmlfile.XmlFile('A') - a.encode(xml) + a.otherInfo.encode(xml) xml.writexml('/tmp/a.xml') + print 'A DONE' + return xml = xmlfile.XmlFile('A') a2 = A() a2.name = "Baris Metin"