diff --git a/pisi/specfile.py b/pisi/specfile.py index 47884aa9..031f34fa 100644 --- a/pisi/specfile.py +++ b/pisi/specfile.py @@ -2,7 +2,8 @@ # read/write PISI source package specification file import xml.dom.minidom -from xmlfile import * +from xmlext import * +from xmlfile import XmlFile from os.path import basename from ui import ui @@ -15,22 +16,47 @@ class PatchInfo: self.filename = getNodeText(node) self.compressionType = getNodeAttribute(node, "compressionType") + def addNode(self, xml): + node = xml.addNode("Source/Patches/Patch") + node.setAttribute("filename", self.filename) + node.setAttribute("compressionType", self.compressionType) + class DepInfo: def __init__(self, node): self.package = getNodeText(node).strip() - self.versionFrom = getNodeAttribute(node, "versionFrom") + self.versionFrom = getNodeAttribute(node, "versionFrom") + self.versionTo = getNodeAttribute(node, "versionTo") -class HistoryInfo: + def elt(self, xml): + node = xml.newNode("Dependency") + node.setAttribute("versionFrom", self.versionFrom) + node.setAttribute("versionTo", self.versionTo) + return node + +class UpdateInfo: def __init__(self, node): self.date = getNodeText(getNode(node, "Date")) self.version = getNodeText(getNode(node, "Version")) self.release = getNodeText(getNode(node, "Release")) + def elt(self, xml): + node = xml.newNode("Update") + xml.addTextNodeUnder(node, "Date", self.date) + xml.addTextNodeUnder(node, "Version", self.version) + xml.addTextNodeUndeR(node, "Release", self.release) + return node + class PathInfo: def __init__(self, node): self.pathname = getNodeText(node) self.fileType = getNodeAttribute(node, "fileType") + def elt(self, xml): + node = xml.newNode("Path") + xml.addText(node, self.pathname) + node.setAttribute("fileType", self.fileType) + return node + # a structure to hold source information class SourceInfo: pass @@ -47,6 +73,15 @@ class PackageInfo: self.runtimeDeps = [DepInfo(x) for x in rtDepElts] self.paths = [PathInfo(x) for x in getAllNodes(node, "Files/Path")] + def elt(self, xml): + node = xml.newNode("Package") + xml.addTextNodeUnder(node, "Name", self.name) + xml.addTextNodeUnder(node, "Summary", self.summary) + xml.addTextNodeUnder(node, "Description", self.description) + xml.addTextNodeUnder(node, "Category", self.category) + + return node + class SpecFile(XmlFile): """A class for reading/writing from/to a PSPEC (PISI SPEC) file.""" @@ -71,7 +106,7 @@ class SpecFile(XmlFile): buildDepElts = self.getAllNodes("Source/BuildDependencies/Dependency") self.source.buildDeps = [DepInfo(d) for d in buildDepElts] historyElts = self.getAllNodes("History/Update") - self.source.history = [HistoryInfo(x) for x in historyElts] + self.source.history = [UpdateInfo(x) for x in historyElts] # As we have no Source/Version tag we need to get # the last version and release information @@ -92,9 +127,12 @@ class SpecFile(XmlFile): def write(self, filename): """Write PSPEC file""" self.newDOM() - self.addNodeText("Source/Name", self.source.name) + self.addTextNode("Source/Name", self.source.name) archiveNode = self.addNode("Source/Archive") archiveNode.setAttribute("archType", self.source.archiveType) archiveNode.setAttribute("sha1sum", self.source.archiveSHA1) - #patchElts + for patch in self.source.patches: + patch.addNode(self) + for dep in map(lambda x : x.elt(self), self.source.buildDeps): + self.addNode("Source/BuildDependencies", dep) self.writexml(filename) diff --git a/pisi/xmlext.py b/pisi/xmlext.py new file mode 100644 index 00000000..792606b7 --- /dev/null +++ b/pisi/xmlext.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# some helper functions for using minidom + +import xml.dom.minidom as mdom + +class XmlError(Exception): + pass + +def getNodeAttribute(node, attrname): + """get named attribute from DOM node""" + for i in range(node.attributes.length): + attr = node.attributes.item(i) + if attr.name == attrname: + return attr.childNodes[0].data + +def getNodeText(node): + """get the first child and expect it to be text!""" + try: + child = node.childNodes[0] + except IndexError: + return None + except AttributeError: # no node by that name + return None + if child.nodeType == child.TEXT_NODE: + return child.data + else: + raise XmlError("getNodeText: Expected text node, got something else!") + +def getChildText(node_s, tagpath): + """get the text of a child at the end of a tag path""" + node = getNode(node_s, tagpath) + if not node: + return None + return getNodeText(node) + +def getChildElts(node): + """get only child elements""" + return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes) + +def getNode(node, tagpath): + """returns the *first* matching node for given tag path.""" + + tags = tagpath.split('/') + assert len(tags)>0 + + # iterative code to search for the path + + # get DOM for top node + nodeList = node.getElementsByTagName(tags[0]) + if len(nodeList) == 0: + return None # not found + + node = nodeList[0] # discard other matches + for tag in tags[1:]: + nodeList = node.getElementsByTagName(tag) + if len(nodeList) == 0: + return None + else: + node = nodeList[0] + + return node + +def getAllNodes(node, tagPath): + """retrieve all nodes that match a given tag path.""" + + tags = tagPath.split('/') + + if len(tags) == 0: + return [] + + nodeList = node.getElementsByTagName(tags[0]) + if len(nodeList) == 0: + return [] + + for tag in tags[1:]: + results = map(lambda x: x.getElementsByTagName(tag),nodeList) + nodeList = [] + for x in results: + nodeList.extend(x) + pass # emacs indentation error, keep it here + + if len(nodeList) == 0: + return [] + + return nodeList + + +def createTagPath(dom, node, tags): + """create new child at the end of a tag chain starting from node + no matter what""" + if len(tags)==0: + return node + for tag in tags: + node = node.appendChild(dom.createElement(tag)) + return node + +def addTagPath(dom, node, tags, newnode=None): + """add newnode at the end of a tag chain, smart one""" + if newnode: # node to add specified + last = len(tags)-1 + if last >= 0: + node = createTagPath(dom, node, tags[0:last]) + node.appendChild(newnode) + else: + raise XmlError("addNodePath: not enough tags") + else: + return createTagPath(dom, node, tags) + +def addNode(dom, node, tagpath, newnode = None): + """add a new node at the end of the tree""" + + tags = tagpath.split('/') # tag chain + assert len(tags)>0 # we want a chain + + # iterative code to search for the path + + # get DOM for top node + nodeList = node.getElementsByTagName(tags[0]) + + if len(nodeList) == 0: + return addTagPath(dom, node, tags, newnode) + + node = nodeList[len(nodeList)-1] # discard other matches + tags.pop(0) + while len(tags)>0: + tag = tags.pop(0) + nodeList = node.getElementsByTagName(tag) + if len(nodeList) == 0: # couldn't find + tags.insert(0, tag) # put it back in + return addTagPath(dom, node, tags, newnode) + else: + node = nodeList[len(nodeList)-1] + + return node diff --git a/pisi/xmlfile.py b/pisi/xmlfile.py index 1b564b28..7ca448f0 100644 --- a/pisi/xmlfile.py +++ b/pisi/xmlfile.py @@ -3,139 +3,11 @@ import xml.dom.minidom as mdom -class XmlError(Exception): - pass - -# static functions - -def getNodeAttribute(node, attrname): - """get named attribute from DOM node""" - for i in range(node.attributes.length): - attr = node.attributes.item(i) - if attr.name == attrname: - return attr.childNodes[0].data - -def getNodeText(node): - """get the first child and expect it to be text!""" - try: - child = node.childNodes[0] - except IndexError: - return None - except AttributeError: # no node by that name - return None - if child.nodeType == child.TEXT_NODE: - return child.data - else: - raise XmlError("getNodeText: Expected text node, got something else!") - -def getChildText(node_s, tagpath): - """get the text of a child at the end of a tag path""" - node = getNode(node_s, tagpath) - if not node: - return None - return getNodeText(node) - -def getChildElts(node): - """get only child elements""" - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes) - -def getNode(node, tagpath): - """returns the *first* matching node for given tag path.""" - - tags = tagpath.split('/') - assert len(tags)>0 - - # iterative code to search for the path - - # get DOM for top node - nodeList = node.getElementsByTagName(tags[0]) - if len(nodeList) == 0: - return None # not found - - node = nodeList[0] # discard other matches - for tag in tags[1:]: - nodeList = node.getElementsByTagName(tag) - if len(nodeList) == 0: - return None - else: - node = nodeList[0] - - return node - -def getAllNodes(node, tagPath): - """retrieve all nodes that match a given tag path.""" - - tags = tagPath.split('/') - - if len(tags) == 0: - return [] - - nodeList = node.getElementsByTagName(tags[0]) - if len(nodeList) == 0: - return [] - - for tag in tags[1:]: - results = map(lambda x: x.getElementsByTagName(tag),nodeList) - nodeList = [] - for x in results: - nodeList.extend(x) - pass # emacs indentation error, keep it here - - if len(nodeList) == 0: - return [] - - return nodeList - - -def createTagPath(dom, node, tags): - """create new child at the end of a tag chain starting from node - no matter what""" - if len(tags)==0: - return node - for tag in tags: - node = node.appendChild(dom.createElement(tag)) - return node - -def addTagPath(dom, node, tags, newnode=None): - """add newnode at the end of a tag chain, smart one""" - if newnode: # node to add specified - last = len(newnode)-1 - if last >= 0: - node = createTagPath(dom, node, tags[0:last]) - node.appendChild(newnode) - else: - raise XmlError("addNodePath: not enough tags") - else: - return createTagPath(dom, node, tags) - -def addNode(dom, node, tagpath, newnode = None): - """add a new node at the end of the tree""" - - tags = tagpath.split('/') # tag chain - assert len(tags)>0 # we want a chain - - # iterative code to search for the path - - # get DOM for top node - nodeList = node.getElementsByTagName(tags[0]) - - if len(nodeList) == 0: - return addTagPath(dom, node, tags, newnode) - - node = nodeList[len(nodeList)-1] # discard other matches - tags.pop(0) - while len(tags)>0: - tag = tags.pop(0) - nodeList = node.getElementsByTagName(tag) - if len(nodeList) == 0: # couldn't find - tags.insert(0, tag) # put it back in - return addTagPath(dom, node, tags, newnode) - else: - node = nodeList[len(nodeList)-1] - - return node +from xmlext import * # xmlfile class that further abstracts a dom object +# using the high-level dom functions provided in xml module +# (and sorely lacking in xml.dom :( ) class XmlFile(object): """A class for retrieving information from an XML file""" @@ -224,11 +96,23 @@ class XmlFile(object): self.verifyRootTag() return addNode(self.dom, self.dom.documentElement, tagPath, newnode) + def addNodeUnder(self, node, tagPath, newnode = None): + "this adds the new stuff under node" + self.verifyRootTag() + return addNode(self.dom, node, tagPath, newnode) + def addText(self, node, text): + "add text to node" node.appendChild(self.newTextNode(text)) - def addNodeText(self, tagPath, text): + def addTextNode(self, tagPath, text): + "add a text node with tag path" node = self.addNode(tagPath, self.newTextNode(text)) return node + def addTextNodeUnder(self, node, tagPath, text): + "add a text node under given node with tag path (phew)" + node = self.addNodeUnder(tagPath, self.newTextNode(text)) + return node +