* find a better way to do the decoding.
* break it all in the process * misc. cleanups
This commit is contained in:
+1
-2
@@ -22,7 +22,6 @@
|
||||
files are specification files for PISI source packages. This module
|
||||
provides read and write access to PSPEC files."""
|
||||
|
||||
|
||||
# standard python modules
|
||||
from os.path import basename
|
||||
|
||||
@@ -33,7 +32,6 @@ from pisi.xmlfile import XmlFile
|
||||
from pisi.dependency import DepInfo
|
||||
from pisi.util import Checks
|
||||
|
||||
|
||||
#class Packager:
|
||||
# __metaclass__ = xmlfile.autoxml
|
||||
|
||||
@@ -285,6 +283,7 @@ class SourceInfo:
|
||||
|
||||
return err.list
|
||||
|
||||
|
||||
class PackageInfo:
|
||||
"""A structure to hold package information. Package information is
|
||||
located under <Package> tag in PSPEC file. Opposite to Source each
|
||||
|
||||
+74
-43
@@ -208,14 +208,16 @@ class autoxml(type):
|
||||
|
||||
cls.decoders = decoders
|
||||
def decode(self, node):
|
||||
for decoder in self.__class__.decoders:
|
||||
decoder(self, node)
|
||||
for decode_member in self.__class__.decoders:
|
||||
decode_member(self, node)
|
||||
cls.decode = decode
|
||||
|
||||
cls.encoders = encoders
|
||||
def encode(self, xml):
|
||||
for encoder in self.__class__.encoders:
|
||||
encoder(self, xml)
|
||||
node = xml.newNode(cls.tag)
|
||||
for encode_member in self.__class__.encoders:
|
||||
encode_member(self, xml, node)
|
||||
return node
|
||||
cls.encode = encode
|
||||
|
||||
cls.formatters = formatters
|
||||
@@ -236,22 +238,33 @@ class autoxml(type):
|
||||
assert type(tag_type) == type(type)
|
||||
def readtext(node, attr):
|
||||
return getNodeAttribute(node, attr)
|
||||
def writetext(xml, node, attr, value):
|
||||
node.setAttribute(attr, value)
|
||||
anonfuns = cls.gen_anon_basic(attr, spec, readtext, writetext)
|
||||
return cls.gen_named_comp(attr, spec, anonfuns)
|
||||
def createnode(xml, attr):
|
||||
return xml.newAttribute(attr)
|
||||
def writetext(node, attr, text):
|
||||
attr.value = text
|
||||
node.setAttributeNode(attr)
|
||||
anonfuns = cls.gen_anon_basic(attr, spec, readtext, createnode, writetext)
|
||||
def mergetext(node, attr):
|
||||
pass
|
||||
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, tag):
|
||||
return getNodeText(getNode(node, tag))
|
||||
def writetext(xml, node, tag, value):
|
||||
xml.addTextNodeUnder(node, tag, value)
|
||||
anonfuns = cls.gen_tag(tag, spec, readtext, writetext)
|
||||
return cls.gen_named_comp(tag, spec, anonfuns)
|
||||
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)
|
||||
return cls.gen_named_comp(tag, spec, anonfuns, mergetext)
|
||||
|
||||
def gen_named_comp(cls, token, spec, anonfuns):
|
||||
def gen_named_comp(cls, token, spec, anonfuns, createnode):
|
||||
"""generate a named component tag/attr. a decoration of
|
||||
anonymous functions that do not bind to variable names"""
|
||||
name = cls.mixed_case(token)
|
||||
@@ -260,17 +273,20 @@ class autoxml(type):
|
||||
(init_a, decode_a, encode_a, format_a) = anonfuns
|
||||
|
||||
def init(self):
|
||||
"""initialize component"""
|
||||
setattr(self, name, init_a())
|
||||
|
||||
def decode(self, node):
|
||||
"""decode component from DOM node"""
|
||||
setattr(self, name, decode_a(node))
|
||||
|
||||
def encode(self, xml):
|
||||
def encode(self, xml, node):
|
||||
"""encode self inside, possibly new, DOM node using xml"""
|
||||
if hasattr(self, name):
|
||||
value = getattr(self, name)
|
||||
else:
|
||||
value = None
|
||||
encode_a(xml, value)
|
||||
return encode_a(xml, self.dom.documentElement, value)
|
||||
|
||||
def format(self):
|
||||
if hasattr(self, name):
|
||||
@@ -283,11 +299,11 @@ class autoxml(type):
|
||||
|
||||
return (init, decode, encode, format)
|
||||
|
||||
def gen_tag(cls, tag, spec, readtext, writetext):
|
||||
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, writetext)
|
||||
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:
|
||||
@@ -298,9 +314,16 @@ class autoxml(type):
|
||||
identifier_p = identifier[0].lower() + identifier[1:]
|
||||
return identifier_p
|
||||
|
||||
def tagpath_head_last(cls, tag_path):
|
||||
"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:])
|
||||
|
||||
def parse_spec(cls, token, spec):
|
||||
"""decompose member specification"""
|
||||
|
||||
name = cls.mixed_case(token)
|
||||
token_type = spec[0]
|
||||
req = spec[1]
|
||||
@@ -312,14 +335,14 @@ class autoxml(type):
|
||||
# the token
|
||||
return name, token_type, req, path
|
||||
|
||||
def gen_anon_basic(cls, token, spec, readtext, writetext):
|
||||
def gen_anon_basic(cls, token, spec, readtext, createnode, writetext):
|
||||
"""Generate a tag or attribute with one of the basic
|
||||
types like integer. This has got to be pretty generic
|
||||
so we can invoke it from the complex types such as Class
|
||||
so that we can invoke it from the complex types such as Class
|
||||
and List. The readtext and writetext arguments achieve
|
||||
the text input I/O for this datatype."""
|
||||
the DOM text access for this datatype."""
|
||||
|
||||
name, token_type, req, path = cls.parse_spec(token, spec)
|
||||
name, token_type, req, tagpath = cls.parse_spec(token, spec)
|
||||
|
||||
def initialize():
|
||||
"""default value for all basic types is None"""
|
||||
@@ -327,7 +350,7 @@ class autoxml(type):
|
||||
|
||||
def decode(node):
|
||||
"""decode from DOM node, the value, watching the spec"""
|
||||
text = readtext(node, token)
|
||||
text = readtext(node, tagpath)
|
||||
print 'read text ', text
|
||||
if text:
|
||||
try:
|
||||
@@ -341,16 +364,19 @@ class autoxml(type):
|
||||
else:
|
||||
return None
|
||||
|
||||
def encode(xml, value):
|
||||
"""encode given value into xml file"""
|
||||
node = xml.newNode(cls.tag)
|
||||
def encode(xml, node, value):
|
||||
"""encode given value inside DOM node"""
|
||||
if value:
|
||||
writetext(xml, node, token, str(value))
|
||||
path = cls.tagpath_head_last(tagpath)
|
||||
node = createnode(xml, token)
|
||||
writetext(node, str(value))
|
||||
return node
|
||||
else:
|
||||
if req == mandatory:
|
||||
raise Error('Mandatory argument not available')
|
||||
|
||||
def format(value):
|
||||
"""format value for pretty printing"""
|
||||
return str(value)
|
||||
|
||||
return initialize, decode, encode, format
|
||||
@@ -383,7 +409,7 @@ class autoxml(type):
|
||||
def encode(xml, obj):
|
||||
if obj:
|
||||
try:
|
||||
obj.encode(xml)
|
||||
return obj.encode(xml)
|
||||
except Error:
|
||||
raise Error('Object cannot be encoded')
|
||||
else:
|
||||
@@ -401,12 +427,14 @@ class autoxml(type):
|
||||
if len(tag_type) != 1:
|
||||
raise Error('List type must contain only one element')
|
||||
|
||||
def readtext_item(node, tag):
|
||||
return getNodeText(node)
|
||||
def writetext_item(xml, node, tag, value):
|
||||
xml.addTextNode(node, value)
|
||||
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_item, writetext_item)
|
||||
readtext, createnode, writetext)
|
||||
(init_item, decode_item, encode_item, format_item) = x
|
||||
|
||||
def init():
|
||||
@@ -422,11 +450,13 @@ class autoxml(type):
|
||||
l.append(decode_item(node))
|
||||
return l
|
||||
|
||||
def encode(xml, l):
|
||||
def encode(xml, node, l):
|
||||
if len(l) > 0:
|
||||
for elt in l:
|
||||
node = xml.newNode(path)
|
||||
encode_item(xml, node)
|
||||
for item in l:
|
||||
item_node = xml.newNode(path)
|
||||
encode_item(xml, item, item_node)
|
||||
xml.addTextNodeUnder(item_node)
|
||||
return node
|
||||
else:
|
||||
if req is mandatory:
|
||||
raise Error('Mandatory list empty')
|
||||
@@ -488,7 +518,7 @@ class XmlFile(object):
|
||||
def newTextNode(self, text):
|
||||
return self.dom.createTextNode(text)
|
||||
|
||||
def newAttribute(self, name):
|
||||
def newAttribute(self, attr):
|
||||
return self.dom.createAttribute(name)
|
||||
|
||||
# read helpers
|
||||
@@ -535,17 +565,18 @@ class XmlFile(object):
|
||||
# write helpers
|
||||
|
||||
def addNode(self, tagPath, newnode = None):
|
||||
"this adds the newnode under given tag path"
|
||||
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"
|
||||
"this adds the new stuff under node and then following tag path"
|
||||
self.verifyRootTag()
|
||||
return addNode(self.dom, node, tagPath, newnode)
|
||||
|
||||
def addChild(self, newnode):
|
||||
"""add a new child node right under root element document"""
|
||||
"add a new child node right under root element document"
|
||||
self.dom.documentElement.appendChild(newnode)
|
||||
|
||||
def addText(self, node, text):
|
||||
@@ -553,7 +584,7 @@ class XmlFile(object):
|
||||
node.appendChild(self.newTextNode(text))
|
||||
|
||||
def addTextNode(self, tagPath, text):
|
||||
"add a text node with tag path"
|
||||
"add a text node with given tag path"
|
||||
node = self.addNode(tagPath, self.newTextNode(text))
|
||||
return node
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@ import os
|
||||
sys.path.append('.')
|
||||
sys.path.append('..')
|
||||
|
||||
import pisi
|
||||
import pisi.api
|
||||
|
||||
runTestSuite = lambda(x): unittest.TextTestRunner(verbosity=2).run(x)
|
||||
|
||||
def run_all():
|
||||
@@ -62,7 +59,6 @@ def run_all():
|
||||
runTestSuite(alltests)
|
||||
|
||||
if __name__ == "__main__":
|
||||
pisi.api.init(False)
|
||||
args = sys.argv
|
||||
if len(args) > 1: # run modules given from the command line
|
||||
tests = sys.argv[1:]
|
||||
|
||||
@@ -22,6 +22,7 @@ import pisi.util as util
|
||||
from pisi.xmlext import *
|
||||
|
||||
class XmlFileTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pisi.api.init(False)
|
||||
|
||||
@@ -55,7 +56,7 @@ class XmlFileTestCase(unittest.TestCase):
|
||||
print '*', string
|
||||
#self.assert_(string.startswith('Name'))
|
||||
xml = xmlfile.XmlFile('A')
|
||||
elta = a.encode(xml)
|
||||
a.encode(xml)
|
||||
xml.writexml('/tmp/a.xml')
|
||||
xml = xmlfile.XmlFile('A')
|
||||
a2 = A()
|
||||
@@ -63,7 +64,7 @@ class XmlFileTestCase(unittest.TestCase):
|
||||
a2.email = "baris@uludag.org.tr"
|
||||
a2.href = 'http://cekirdek.uludag.org.tr/~baris'
|
||||
a2.projects = [ 'pisi', 'tasma', 'plasma' ]
|
||||
elta2 = a2.encode(xml)
|
||||
a2.encode(xml)
|
||||
xml.writexml('/tmp/a2.xml')
|
||||
string = a2.format()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user