summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Groschupp <christian@groschupp.org>2009-12-28 01:43:18 +0100
committerChristian Groschupp <christian@groschupp.org>2009-12-28 21:01:57 +0100
commit507e8f4451e53de613228761b9bbf1a5d82f25cb (patch)
tree86613eeb26fe2430ed4bb0a139049eccaac0c126
parent63b1dff9da3df8a63708a4ecb5f646af6951ecfd (diff)
downloadlayman-507e8f4451e53de613228761b9bbf1a5d82f25cb.tar.gz
layman-507e8f4451e53de613228761b9bbf1a5d82f25cb.tar.bz2
layman-507e8f4451e53de613228761b9bbf1a5d82f25cb.zip
Migrate XML handling to ElementTree
-rw-r--r--layman/overlay.py91
-rw-r--r--layman/overlays/bzr.py1
-rw-r--r--layman/overlays/cvs.py5
-rw-r--r--layman/overlays/darcs.py1
-rw-r--r--layman/overlays/git.py1
-rw-r--r--layman/overlays/mercurial.py1
-rw-r--r--layman/overlays/overlay.py134
-rw-r--r--layman/overlays/rsync.py1
-rw-r--r--layman/overlays/svn.py1
-rw-r--r--layman/overlays/tar.py13
-rw-r--r--layman/utils.py131
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):
'''