diff options
-rw-r--r-- | layman/overlay.py | 91 | ||||
-rw-r--r-- | layman/overlays/bzr.py | 1 | ||||
-rw-r--r-- | layman/overlays/cvs.py | 5 | ||||
-rw-r--r-- | layman/overlays/darcs.py | 1 | ||||
-rw-r--r-- | layman/overlays/git.py | 1 | ||||
-rw-r--r-- | layman/overlays/mercurial.py | 1 | ||||
-rw-r--r-- | layman/overlays/overlay.py | 134 | ||||
-rw-r--r-- | layman/overlays/rsync.py | 1 | ||||
-rw-r--r-- | layman/overlays/svn.py | 1 | ||||
-rw-r--r-- | layman/overlays/tar.py | 13 | ||||
-rw-r--r-- | layman/utils.py | 131 |
11 files changed, 150 insertions, 230 deletions
diff --git a/layman/overlay.py b/layman/overlay.py index 5b8c73f..5372ba7 100644 --- a/layman/overlay.py +++ b/layman/overlay.py @@ -15,6 +15,7 @@ # Author(s): # Gunnar Wrobel <wrobel@gentoo.org> # Sebastian Pipping <sebastian@pipping.org> +# Christian Groschupp <christian@groschupp.org> # '''Main handler for overlays.''' @@ -26,7 +27,8 @@ __version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $" # #------------------------------------------------------------------------------- -import sys, codecs, os, os.path, xml.dom.minidom +import sys, codecs, os, os.path +import elementtree.ElementTree as ET from layman.overlays.bzr import BzrOverlay from layman.overlays.darcs import DarcsOverlay @@ -45,14 +47,16 @@ from layman.debug import OUT # #------------------------------------------------------------------------------- -OVERLAY_TYPES = {'git' : GitOverlay, - 'cvs' : CvsOverlay, - 'svn' : SvnOverlay, - 'rsync' : RsyncOverlay, - 'tar' : TarOverlay, - 'bzr' : BzrOverlay, - 'mercurial' : MercurialOverlay, - 'darcs' : DarcsOverlay} +OVERLAY_TYPES = dict((e.type_key, e) for e in ( + GitOverlay, + CvsOverlay, + SvnOverlay, + RsyncOverlay, + TarOverlay, + BzrOverlay, + MercurialOverlay, + DarcsOverlay +)) #=============================================================================== # @@ -81,17 +85,15 @@ class Overlays: '''Read the overlay definition file.''' try: - - document = open(path).read() + document = open(path, 'r').read() except Exception, error: raise IOError('Failed to read the overlay list at ("' + path + '")!\nError was:\n' + str(error)) - self.read(document) - def read(self, document): + def read(self, text): ''' Read an xml list of overlays. @@ -101,34 +103,28 @@ class Overlays: >>> a.overlays.keys() [u'wrobel', u'wrobel-stable'] - >>> a.overlays['wrobel-stable'].data['&src'] + >>> a.overlays['wrobel-stable'].src u'rsync://gunnarwrobel.de/wrobel-stable' ''' - try: - - document = xml.dom.minidom.parseString(document) - - except Exception, error: - raise Exception('Failed to parse the overlay list!\nError was:\n' - + str(error)) - - overlays = document.getElementsByTagName('overlay') + \ - document.getElementsByTagName('repo') + document = ET.fromstring(text) + overlays = document.findall('overlay') + \ + document.findall('repo') for overlay in overlays: - OUT.debug('Parsing overlay entry', 8) - try: - element_to_scan = overlay.getElementsByTagName('source')[0] - except IndexError: + + _source = overlay.find('source') + if _source != None: + element_to_scan = _source + else: element_to_scan = overlay - for index in range(0, element_to_scan.attributes.length): - attr = element_to_scan.attributes.item(index) - if attr.name == 'type': - if attr.nodeValue in OVERLAY_TYPES.keys(): + for attr_name in element_to_scan.attrib.keys(): + if attr_name == 'type': + overlay_type = element_to_scan.attrib['type'] + if overlay_type in OVERLAY_TYPES.keys(): try: - ovl = OVERLAY_TYPES[attr.nodeValue](overlay, + ovl = OVERLAY_TYPES[overlay_type](overlay, self.ignore, self.quiet) self.overlays[ovl.name] = ovl @@ -136,7 +132,8 @@ class Overlays: OUT.warn(str(error), 3) else: raise Exception('Unknown overlay type "' + - attr.nodeValue + '"!') + overlay_type + '"!') + break def write(self, path): ''' @@ -156,22 +153,16 @@ class Overlays: >>> os.unlink(write) ''' - imp = xml.dom.minidom.getDOMImplementation() - - doc = imp.createDocument('layman', 'repositories', None) - - root = doc.childNodes[0] - - for name, overlay in self.overlays.items(): - - root.appendChild(overlay.to_minidom(doc)) - + xml = ET.Element('repositories', version="1.0") + xml[:] = [e.to_minidom() for e in self.overlays.values()] + tree = ET.ElementTree(xml) try: - - out_file = codecs.open(path, 'w', 'utf-8') - - doc.writexml(out_file, '', ' ', '\n') - + f = open(path, 'w') + f.write("""\ +<?xml version="1.0" encoding="UTF-8"?> +""") + tree.write(f, encoding='utf-8') + f.close() except Exception, error: raise Exception('Failed to write to local overlays file: ' + path + '\nError was:\n' + str(error)) @@ -182,7 +173,7 @@ class Overlays: >>> here = os.path.dirname(os.path.realpath(__file__)) >>> a = Overlays([here + '/tests/testfiles/global-overlays.xml', ]) - >>> a.select('wrobel-stable').data['&src'] + >>> a.select('wrobel-stable').src u'rsync://gunnarwrobel.de/wrobel-stable' ''' if overlay in self.overlays.keys(): diff --git a/layman/overlays/bzr.py b/layman/overlays/bzr.py index 4c14278..64fbbdd 100644 --- a/layman/overlays/bzr.py +++ b/layman/overlays/bzr.py @@ -39,6 +39,7 @@ class BzrOverlay(Overlay): ''' Handles bzr overlays.''' type = 'Bzr' + type_key = 'bzr' binary_command = '/usr/bin/bzr' diff --git a/layman/overlays/cvs.py b/layman/overlays/cvs.py index d9710de..a28889a 100644 --- a/layman/overlays/cvs.py +++ b/layman/overlays/cvs.py @@ -37,6 +37,7 @@ class CvsOverlay(Overlay): ''' Handles cvs overlays.''' type = 'cvs' + type_key = 'cvs' binary = '/usr/bin/cvs' @@ -44,8 +45,8 @@ class CvsOverlay(Overlay): Overlay.__init__(self, xml, ignore, quiet) - if '&subpath' in self.data.keys(): - self.subpath = self.data['&subpath'] + if 'subpath' in xml.attrib: + self.subpath = xml.attrib['subpath'] else: self.subpath = '' diff --git a/layman/overlays/darcs.py b/layman/overlays/darcs.py index 0d27d5e..e066eee 100644 --- a/layman/overlays/darcs.py +++ b/layman/overlays/darcs.py @@ -38,6 +38,7 @@ class DarcsOverlay(Overlay): ''' Handles darcs overlays.''' type = 'Darcs' + type_key = 'darcs' binary_command = '/usr/bin/darcs' diff --git a/layman/overlays/git.py b/layman/overlays/git.py index bda2df0..3bcb3e3 100644 --- a/layman/overlays/git.py +++ b/layman/overlays/git.py @@ -37,6 +37,7 @@ class GitOverlay(Overlay): ''' Handles git overlays.''' type = 'Git' + type_key = 'git' binary_command = '/usr/bin/git' diff --git a/layman/overlays/mercurial.py b/layman/overlays/mercurial.py index b010c8b..03af63b 100644 --- a/layman/overlays/mercurial.py +++ b/layman/overlays/mercurial.py @@ -38,6 +38,7 @@ class MercurialOverlay(Overlay): ''' Handles mercurial overlays.''' type = 'Mercurial' + type_key = 'mercurial' binary_command = '/usr/bin/hg' diff --git a/layman/overlays/overlay.py b/layman/overlays/overlay.py index bee7529..f1e38a3 100644 --- a/layman/overlays/overlay.py +++ b/layman/overlays/overlay.py @@ -15,6 +15,7 @@ # Author(s): # Gunnar Wrobel <wrobel@gentoo.org> # Sebastian Pipping <sebastian@pipping.org> +# Christian Groschupp <christian@groschupp.org> # ''' Basic overlay class.''' @@ -27,8 +28,9 @@ __version__ = "$Id: overlay.py 273 2006-12-30 15:54:50Z wrobel $" #------------------------------------------------------------------------------- import sys, types, re, os, os.path, shutil, subprocess +import elementtree.ElementTree as ET -from layman.utils import node_to_dict, dict_to_node, path +from layman.utils import path, ensure_unicode from layman.debug import OUT @@ -46,10 +48,9 @@ class Overlay: def __init__(self, xml, ignore = 0, quiet = False): ''' >>> here = os.path.dirname(os.path.realpath(__file__)) - >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read() - >>> import xml.dom.minidom - >>> document = xml.dom.minidom.parseString(document) - >>> overlays = document.getElementsByTagName('overlay') + >>> import elementtree.ElementTree as ET + >>> document = ET.parse(here + '/../tests/testfiles/global-overlays.xml') + >>> overlays = document.findall('overlay') + document.findall('repo') >>> a = Overlay(overlays[0]) >>> a.name u'wrobel' @@ -69,32 +70,36 @@ class Overlay: ''' self.quiet = quiet - self.data = node_to_dict(xml) - - if '<name>1' in self.data.keys(): - self.name = self.data['<name>1']['@'].strip() - elif '&name' in self.data.keys(): - self.name = self.data['&name'] + _name = xml.find('name') + if _name != None: + self.name = ensure_unicode(_name.text) + elif 'name' in xml.attrib: + self.name = ensure_unicode(xml.attrib['name']) else: raise Exception('Overlay is missing a "name" entry!') - if '<source>1' in self.data.keys(): - self.src = self.data['<source>1']['@'].strip() - elif '&src' in self.data.keys(): - self.src = self.data['&src'] + _source = xml.find('source') + if _source != None: + self.src = ensure_unicode(_source.text.strip()) + elif 'src' in xml.attrib: + self.src = ensure_unicode(xml.attrib['src']) + else: + raise Exception('Overlay "' + self.name + '" is missing a "source" entry!') + + _owner = xml.find('owner') + if _owner == None: + _email = None else: - raise Exception('Overlay "' + self.name + '" is missing a "source" ' - 'entry!') - - if '<owner>1' in self.data.keys() and \ - '<email>1' in self.data['<owner>1']: - self.owner_email = self.data['<owner>1']['<email>1']['@'].strip() - if '<name>1' in self.data['<owner>1']: - self.owner_name = self.data['<owner>1']['<name>1']['@'].strip() + _email = _owner.find('email') + if _owner != None and _email != None: + self.owner_email = ensure_unicode(_email.text.strip()) + _name = _owner.find('name') + if _name != None: + self.owner_name = ensure_unicode(_name.text.strip()) else: self.owner_name = None - elif '&contact' in self.data.keys(): - self.owner_email = self.data['&contact'] + elif 'contact' in xml.attrib: + self.owner_email = ensure_unicode(xml.attrib['contact']) self.owner_name = None else: self.owner_email = '' @@ -106,37 +111,73 @@ class Overlay: OUT.warn('Overlay "' + self.name + '" is missing a ' '"owner.email" entry!', 4) - if '<description>1' in self.data.keys(): - self.description = self.data['<description>1']['@'].strip() + + _desc = xml.find('description') + if _desc != None: + self.description = ensure_unicode(_desc.text.strip()) else: self.description = '' if not ignore: raise Exception('Overlay "' + self.name + '" is missing a ' - '"description" entry!') + '"description" entry!') elif ignore == 1: OUT.warn('Overlay "' + self.name + '" is missing a ' - '"description" entry!', 4) + '"description" entry!', 4) - if '&status' in self.data.keys(): - self.status = self.data['&status'] + if 'status' in xml.attrib: + self.status = ensure_unicode(xml.attrib['status']) else: - self.status = '' + self.status = None - if '&priority' in self.data.keys(): - self.priority = int(self.data['&priority']) + if 'priority' in xml.attrib: + self.priority = int(xml.attrib['priority']) else: self.priority = 50 + h = xml.find('homepage') + l = xml.find('link') + if h != None: + self.homepage = ensure_unicode(h.text.strip()) + elif l != None: + self.homepage = ensure_unicode(l.text.strip()) + else: + self.homepage = None + def set_priority(self, priority): '''Set the priority of this overlay.''' - self.data['&priority'] = str(priority) self.priority = int(priority) - def to_minidom(self, document): + def to_minidom(self): '''Convert to xml.''' - return dict_to_node(self.data, document, 'overlay') + repo = ET.Element('repo') + if self.status != None: + repo.attrib['status'] = self.status + repo.attrib['priority'] = str(self.priority) + name = ET.Element('name') + name.text = self.name + repo.append(name) + desc = ET.Element('description') + desc.text = self.description + repo.append(desc) + if self.homepage != None: + homepage = ET.Element('homepage') + homepage.text = self.homepage + repo.append(homepage) + owner = ET.Element('owner') + repo.append(owner) + owner_email = ET.Element('email') + owner_email.text = self.owner_email + owner.append(owner_email) + if self.owner_name != None: + owner_name = ET.Element('name') + owner_name.text = self.owner_name + owner.append(owner_name) + source = ET.Element('source', type=self.__class__.type_key) + source.text = self.src + repo.append(source) + return repo def add(self, base, quiet = False): '''Add the overlay.''' @@ -186,10 +227,9 @@ class Overlay: def __str__(self): ''' >>> here = os.path.dirname(os.path.realpath(__file__)) - >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read() - >>> import xml.dom.minidom - >>> document = xml.dom.minidom.parseString(document) - >>> overlays = document.getElementsByTagName('overlay') + >>> import elementtree.ElementTree as ET + >>> document = ET.parse(here + '/../tests/testfiles/global-overlays.xml') + >>> overlays = document.findall('overlay') + document.findall('repo') >>> a = Overlay(overlays[0]) >>> print str(a) wrobel @@ -222,24 +262,22 @@ class Overlay: result += u'\n '.join((u'\n' + description).split(u'\n')) result += u'\n' - for key in (e for e in ('<homepage>1', '<link>1') if e in self.data.keys()): - link = self.data[key]['@'].strip() + if self.homepage != None: + link = self.homepage link = re.compile(u' +').sub(u' ', link) link = re.compile(u'\n ').sub(u'\n', link) result += u'\nLink:\n' result += u'\n '.join((u'\n' + link).split(u'\n')) result += u'\n' - break return result def short_list(self, width = 0): ''' >>> here = os.path.dirname(os.path.realpath(__file__)) - >>> document = open(here + '/../tests/testfiles/global-overlays.xml').read() - >>> import xml.dom.minidom - >>> document = xml.dom.minidom.parseString(document) - >>> overlays = document.getElementsByTagName('overlay') + >>> import elementtree.ElementTree as ET + >>> document = ET.parse(here + '/../tests/testfiles/global-overlays.xml') + >>> overlays = document.findall('repo') + document.findall('overlay') >>> a = Overlay(overlays[0]) >>> print a.short_list(80) wrobel [None ] (https://o.g.o/svn/dev/wrobel ) diff --git a/layman/overlays/rsync.py b/layman/overlays/rsync.py index 6052bd0..1fc767f 100644 --- a/layman/overlays/rsync.py +++ b/layman/overlays/rsync.py @@ -37,6 +37,7 @@ class RsyncOverlay(Overlay): ''' Handles rsync overlays.''' type = 'Rsync' + type_key = 'rsync' binary = '/usr/bin/rsync' diff --git a/layman/overlays/svn.py b/layman/overlays/svn.py index 4ff3da4..8fef998 100644 --- a/layman/overlays/svn.py +++ b/layman/overlays/svn.py @@ -37,6 +37,7 @@ class SvnOverlay(Overlay): ''' Handles subversion overlays.''' type = 'Subversion' + type_key = 'svn' binary = '/usr/bin/svn' diff --git a/layman/overlays/tar.py b/layman/overlays/tar.py index 5786931..4990b2b 100644 --- a/layman/overlays/tar.py +++ b/layman/overlays/tar.py @@ -62,6 +62,7 @@ class TarOverlay(Overlay): ''' type = 'Tar' + type_key = 'tar' binary = u'/bin/tar' @@ -69,22 +70,22 @@ class TarOverlay(Overlay): Overlay.__init__(self, xml, ignore) - if '&format' in self.data.keys(): - self.format = self.data['&format'] + if 'format' in xml.attrib: + self.format = xml.attrib['format'] else: self.format = '' - if '&subpath' in self.data.keys(): - self.subpath = self.data['&subpath'] + if 'subpath' in xml.attrib: + self.subpath = xml.attrib['subpath'] else: self.subpath = '' - if '&category' in self.data.keys(): + if 'category' in xml.attrib: if self.subpath: raise Exception('Cannot use "category" and "subpath" at the same' ' time!') - self.category = self.data['&category'] + self.category = xml.attrib['category'] else: self.category = '' diff --git a/layman/utils.py b/layman/utils.py index 695b996..55df876 100644 --- a/layman/utils.py +++ b/layman/utils.py @@ -13,6 +13,8 @@ # # Author(s): # Gunnar Wrobel <wrobel@gentoo.org> +# Sebastian Pipping <sebastian@pipping.org> +# Christian Groschupp <christian@groschupp.org> # '''Utility functions to deal with xml nodes. ''' @@ -33,130 +35,11 @@ import types, re # #------------------------------------------------------------------------------- -def node_to_text(node): - ''' - Reduces an xml node to its text elements. The function does not - collect the text nodes recursively. - - >>> import xml.dom.minidom - >>> imp = xml.dom.minidom.getDOMImplementation() - >>> doc = imp.createDocument('test', 'root', None) - >>> root = doc.childNodes[0] - >>> node = doc.createTextNode('text') - >>> a = root.appendChild(node) - >>> node = doc.createElement('text') - >>> node2 = doc.createTextNode('text') - >>> a = node.appendChild(node2) - >>> a = root.appendChild(node) - >>> node = doc.createTextNode('text') - >>> a = root.appendChild(node) - >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS - '<?xml version="1.0" ?>...<root>text<text>text</text>text</root>' - - >>> node_to_text(root) - 'texttext' - - ''' - text = '' - - for child in node.childNodes: - if child.nodeType == child.TEXT_NODE: - text = text + child.data - - return text - -def node_to_dict(node): - ''' Converts a xml node to a dictionary. The function collects the - nodes recursively. Attributes will be prepended with '&', child - nodes will be surrounded with tags. An index will be appended - since several child nodes with the same tag may exist. Text - elements will be collapsed and stored in a n entry prepended with - '@'. Comments will be ignored. - - >>> import xml.dom.minidom - >>> imp = xml.dom.minidom.getDOMImplementation() - >>> doc = imp.createDocument('test', 'root', None) - >>> root = doc.childNodes[0] - >>> node = doc.createTextNode('text') - >>> a = root.appendChild(node) - >>> node = doc.createElement('text') - >>> node2 = doc.createTextNode('text') - >>> comm = doc.createComment('comment') - >>> attr = doc.createAttribute('&attr') - >>> a = node.appendChild(node2) - >>> a = root.appendChild(comm) - >>> node.setAttributeNode(attr) - >>> node.setAttribute('&attr','test') - >>> a = root.appendChild(node) - >>> node3 = doc.createElement('text') - >>> a = root.appendChild(node3) - >>> node = doc.createTextNode('text') - >>> a = root.appendChild(node) - >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS - '<?xml version="1.0" ?>...<root>text<!--comment--><text &attr="test">text</text><text/>text</root>' - - >>> node_to_dict(root) - {'<text>1': {'@': 'text', '&&attr': 'test'}, '<text>2': {'@': ''}, '@': 'texttext'} - - ''' - result = {} - - # Map the attributes - for index in range(0, node.attributes.length): - attr = node.attributes.item(index) - result['&' + attr.name] = attr.nodeValue - - text = '' - - # Map the nodes - for child in node.childNodes: - if child.nodeType == child.TEXT_NODE: - text = text + child.data - elif child.nodeType == child.CDATA_SECTION_NODE: - text = text + child.data - elif child.nodeType == child.ELEMENT_NODE: - index = 1 - while ('<' + child.tagName + '>' + str(index)) in result.keys(): - index += 1 - result['<' + child.tagName + '>' + str(index)] = node_to_dict(child) - - result['@'] = text - - return result - -def dict_to_node(data, document, root_name): - ''' Reverts the node_to_dict operation. - - >>> import xml.dom.minidom - >>> imp = xml.dom.minidom.getDOMImplementation() - >>> doc = imp.createDocument('test', 'root', None) - >>> a = {'<text>1': {'@': 'text', '&&attr': 'test'}, '<text>2': {'@': ''}, '@': 'texttext'} - >>> doc.childNodes[0] = dict_to_node(a, doc, 'root') - >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS - '<?xml version="1.0" ?>...<root><text &attr="test">text</text><text></text>texttext</root>' - - ''' - node = document.createElement(root_name) - - for i, j in data.items(): - - if i[0] == '&': - attr = document.createAttribute(i[1:]) - node.setAttributeNode(attr) - node.setAttribute(i[1:], j) - if i[0] == '<': - k = i[1:] - while k[-1] in '0123456789': - k = k[:-1] - child = dict_to_node(data[i], - document, - k[:-1]) - node.appendChild(child) - if i[0] == '@': - child = document.createTextNode(j) - node.appendChild(child) - - return node +def ensure_unicode(obj, encoding='utf-8'): + if isinstance(obj, basestring): + if not isinstance(obj, unicode): + obj = unicode(obj, encoding) + return obj def path(path_elements): ''' |