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