diff --git a/TODO b/TODO index 3db8bab5..5ca31271 100644 --- a/TODO +++ b/TODO @@ -74,15 +74,9 @@ Legend: 3. Beta - configure-pending (eray) - / autoxml: automated xml processing (eray) - + design - + basic types - + list type - + class type - / localtext type / components (eray) + requirements - - xml format + / xml format - query components: list of components/packages in a component - install/remove components / API: we even have application users (eray) @@ -123,6 +117,12 @@ Legend: + Files - Index (o kadar onemli degil) ? non-interactive use (baris) + + autoxml: automated xml processing (eray) + + design + + basic types + + list type + + class type + + localtext type + implement missing unit tests + sourcedb + package (baris) diff --git a/pisi/data.py b/pisi/data.py index 94b6d0c0..1cb1fb3c 100644 --- a/pisi/data.py +++ b/pisi/data.py @@ -17,21 +17,26 @@ __metaclass__ = xmlfile.autoxml class Distribution: t_Name = [xmlfile.Text, xmlfile.mandatory] + t_Description = [xmlfile.LocalText, xmlfile.mandatory] t_Version = [xmlfile.Text, xmlfile.mandatory] t_Type = [xmlfile.Text, xmlfile.mandatory] t_Dependencies = [ [xmlfile.Text], xmlfile.optional, "Distribution"] class Component: "part-of representation for component declarations" - t_Name = [xmlfile.Text, xmlfile.mandatory] + + t_Name = [xmlfile.Text, xmlfile.mandatory] # fully qualified name t_PartOf = [xmlfile.Text, xmlfile.mandatory] + t_LocalName = [xmlfile.LocalText, xmlfile.mandatory] + t_Description = [xmlfile.LocalText, xmlfile.mandatory] #t_Icon = [xmlfile.Binary, xmlfile.mandatory] t_Dependencies = [ [xmlfile.String], xmlfile.optional, "Component"] class ComponentTree: "index representation for the component structure" tag = "Component" - t_Name = [xmlfile.Text, xmlfile.mandatory] + + t_Name = [xmlfile.Text, xmlfile.mandatory] # fully qualified name #t_Icon = [xmlfile.Binary, xmlfile.mandatory] t_Dependencies = [ [xmlfile.Text], xmlfile.optional, "Component"] t_Parts = [ [ComponentTree], xmlfile.optional, "Component"] diff --git a/pisi/xmlfile.py b/pisi/xmlfile.py index 3fcdf4f1..7e504118 100644 --- a/pisi/xmlfile.py +++ b/pisi/xmlfile.py @@ -47,7 +47,6 @@ import pisi.context as ctx class Error(pisi.Error): pass - mandatory, optional = range(2) # poor man's enum # basic types @@ -69,20 +68,20 @@ class LocalText(object): self.req = spec[1] self.locs = {} - def decode(self, node): + def decode(self, node, errs): # flags, tag name, instance attribute nodes = getAllNodes(node, self.tag) if not nodes: if self.req == mandatory: - pass - #errs.append("Tag '%s' should have at least one '%s' tag\n" % (parent.tagName, d[2])) + errs.append("LocalText '%s' should have at least one '%s' tag\n" % + self.tag) else: for node in nodes: lang = getNodeAttribute(node, "xml:lang") c = getNodeText(node) if not c: - #errs.append("Tag '%s' should have some text data\n" % node.tagName) - break + errs.append("'%s' language of tag '%s' should have some text data\n" % + (lang, self.tag)) # FIXME: check for dups and 'en' if not lang: lang = 'en' @@ -96,7 +95,7 @@ class LocalText(object): # return "" #retur - def encode(self, xml, node): + def encode(self, xml, node, errs): for key in self.locs.iterkeys(): newnode = newNode(node, self.tag) newnode.setAttribute('xml:lang', key) @@ -104,7 +103,7 @@ class LocalText(object): newnode.appendChild(newtext) node.appendChild(newnode) - def format(self): + def format(self, errs): return '' class autoxml(type): @@ -223,22 +222,22 @@ class autoxml(type): cls.__init__ = initialize cls.decoders = decoders - def decode(self, node): + def decode(self, node, errs): for decode_member in self.__class__.decoders: - decode_member(self, node) + decode_member(self, node, errs) cls.decode = decode cls.encoders = encoders - def encode(self, xml, node): + def encode(self, xml, node, errs): for encode_member in self.__class__.encoders: - encode_member(self, xml, node) + encode_member(self, xml, node, errs) cls.encode = encode cls.formatters = formatters - def format(self): + def format(self, errs): string = '' for formatter in self.__class__.formatters: - string += formatter(self) + string += formatter(self, errs) return string cls.format = format if not dict.has_key('__str__'): @@ -299,29 +298,22 @@ class autoxml(type): """initialize component""" setattr(self, name, init_a()) - def decode(self, node): + def decode(self, node, errs): """decode component from DOM node""" - setattr(self, name, decode_a(node)) + setattr(self, name, decode_a(node, errs)) - def encode(self, xml, node): + def encode(self, xml, node, errs): """encode self inside, possibly new, DOM node using xml""" if hasattr(self, name): value = getattr(self, name) else: value = None - encode_a(xml, node, value) - #newnode = - #if newnode: - # mergetext(node, newnode) - #else: - # if req == mandatory: - # raise Error('Mandatory variable %s not available' % name) - + encode_a(xml, node, value, errs) - def format(self): + def format(self, errs): if hasattr(self, name): value = getattr(self,name) - return '%s: %s\n' % (token, format_a(value)) + return '%s: %s\n' % (token, format_a(value, errs)) else: if req == mandatory: raise Error('Mandatory variable %s not available' % name) @@ -370,7 +362,7 @@ class autoxml(type): """default value for all basic types is None""" return None - def decode(node): + def decode(node, errs): """decode from DOM node, the value, watching the spec""" text = readtext(node, token) #print 'read text ', text @@ -378,24 +370,23 @@ class autoxml(type): try: value = autoxml.basic_cons_map[token_type](text) except Error: - raise Error('Type mismatch: read text cannot be decoded') + value = None + errs.append('Type mismatch: read text cannot be decoded') return value else: if req == mandatory: - raise Error('Mandatory token %s not available' % token) - else: - return None + errs.append('Mandatory token %s not available' % token) + return None - def encode(xml, node, value): + def encode(xml, node, value, errs): """encode given value inside DOM node""" if value: writetext(xml, node, token, str(value)) - return node else: if req == mandatory: - raise Error('Mandatory argument not available') + errs.append('Mandatory argument not available') - def format(value): + def format(value, errs): """format value for pretty printing""" return str(value) @@ -413,44 +404,43 @@ class autoxml(type): def init(): return make_object() - def decode(node): + def decode(node, errs): node = getNode(node, tag) if node: try: obj = make_object() - obj.decode(node) + obj.decode(node, errs) return obj except Error: - raise Error('Type mismatch: DOM cannot be decoded') + errs.append('Type mismatch: DOM cannot be decoded') else: if req == mandatory: - raise Error('Mandatory argument not available') - else: - return None - - def encode(xml, node, obj): + errs.append('Mandatory argument not available') + return None + + def encode(xml, node, obj, errs): if node and obj: try: #FIXME: this doesn't look pretty classnode = node.ownerDocument.createElement(tag) - obj.encode(xml, classnode) + obj.encode(xml, classnode, errs) node.appendChild(classnode) except Error: if req == mandatory: # note: we can receive an error if obj has no content - raise Error('Object cannot be encoded') + errs.append('Object cannot be encoded') else: if req == mandatory: - raise Error('Mandatory argument not available') + errs.append('Mandatory argument not available') - def format(obj): + def format(obj, errs): try: - return obj.format() + return obj.format(errs) except Error: if req == mandatory: - raise Error('Mandatory argument not available') + errs.append('Mandatory argument not available') else: - return "" + return '' return (init, decode, encode, format) def gen_list_tag(cls, tag, spec): @@ -467,33 +457,33 @@ class autoxml(type): def init(): return [] - def decode(node): + def decode(node, errs): l = [] nodes = getAllNodes(node, tag + '/' + comp_tag) #print node, tag + '/' + comp_tag, nodes if len(nodes) is 0 and req is mandatory: - raise Error('Mandatory list empty') + errs.append('Mandatory list empty') for node in nodes: dummy = node.ownerDocument.createElement("Dummy") dummy.appendChild(node) - l.append(decode_item(dummy)) + l.append(decode_item(dummy, errs)) return l - def encode(xml, node, l): + def encode(xml, node, l, errs): if l and len(l) > 0: listnode = xml.newNode(tag) for item in l: - encode_item(xml, listnode, item) + encode_item(xml, listnode, item, errs) node.appendChild(listnode) else: if req is mandatory: - raise Error('Mandatory list empty') + errs.append('Mandatory list empty') - def format(l): + def format(l, errs): #print 'format:', name s = '' for ix in range(len(l)): - s += str(ix+1) + ': ' + format_item(l[ix]) + s += str(ix+1) + ': ' + format_item(l[ix], errs) if ix != len(l)-1: s += ', ' return s @@ -516,41 +506,40 @@ class autoxml(type): def init(): return make_object() - def decode(node): + def decode(node, errs): if node: try: obj = make_object() - obj.decode(node) + obj.decode(node, errs) return obj except Error: - raise Error('Type mismatch: DOM cannot be decoded') + errs.append('Type mismatch: DOM cannot be decoded') else: if req == mandatory: - raise Error('Mandatory argument not available') - else: - return None + errs.append('Mandatory argument not available') + return None - def encode(xml, node, obj): + def encode(xml, node, obj, errs): if node and obj: try: #FIXME: this doesn't look pretty - obj.encode(xml, node) + obj.encode(xml, node, errs) except Error: if req == mandatory: # note: we can receive an error if obj has no content - raise Error('Object cannot be encoded') + errs.append('Object cannot be encoded') else: if req == mandatory: - raise Error('Mandatory argument not available') + errs.append('Mandatory argument not available') - def format(obj): + def format(obj, errs): try: - return obj.format() + return obj.format(errs) except Error: if req == mandatory: - raise Error('Mandatory argument not available') + errs.append('Mandatory argument not available') else: - return "" + return '' return (init, decode, encode, format) basic_cons_map = { diff --git a/tests/xmlfiletests.py b/tests/xmlfiletests.py index 2a7636fe..1af3e57f 100644 --- a/tests/xmlfiletests.py +++ b/tests/xmlfiletests.py @@ -49,16 +49,20 @@ class XmlFileTestCase(unittest.TestCase): dom = mdom.parse('tests/a.xml') node = getNode(dom, 'A') self.assert_(len(A.decoders)>0) - a.decode(node) + errs = [] + print 'errs', errs + a.decode(node, errs) self.assert_(a.href.startswith('http')) self.assertEqual(a.number, 868) self.assertEqual(a.name, 'Eray Ozkural') - string = a.format() + string = a.format(errs) print '*', string #self.assert_(string.startswith('Name')) xml = xmlfile.XmlFile('A') xml.newDOM() - a.encode(xml, xml.rootNode()) + errs2 = [] + a.encode(xml, xml.rootNode(), errs2) + print 'errs2', errs2 xml.writexml('/tmp/a.xml') print '/tmp/a.xml written' xml = xmlfile.XmlFile('A') @@ -67,8 +71,10 @@ class XmlFileTestCase(unittest.TestCase): a2.email = "baris@uludag.org.tr" a2.href = 'http://cekirdek.uludag.org.tr/~baris' a2.projects = [ 'pisi', 'tasma', 'plasma' ] - a2.encode(xml, xml.rootNode()) + errs3 = [] + a2.encode(xml, xml.rootNode(), errs3) + print 'errs3', errs3 xml.writexml('/tmp/a2.xml') - string = a2.format() + string = a2.format(errs3) suite = unittest.makeSuite(XmlFileTestCase)