* birtakim duzeltmeler (saka canim)
* autoxml'de muhtelif duzeltmeler * toplam code size'ini azaltip, list type'ini encode disinda implement et. sira class type'inda * run.py'de pisi.api'i init et, ne bileyim iste. * code'u yazan biziz calistiran da biz olacagiz
This commit is contained in:
+136
-106
@@ -143,7 +143,7 @@ class autoxml(type):
|
|||||||
|
|
||||||
class Company:
|
class Company:
|
||||||
__metaclass__ = autoxml
|
__metaclass__ = autoxml
|
||||||
t_Employees = [ Employee, xmlfile.mandatory]
|
t_Employees = [ [Employee], xmlfile.mandatory]
|
||||||
|
|
||||||
Logically, inside the Company tag, we will have several Employee
|
Logically, inside the Company tag, we will have several Employee
|
||||||
tags, which are inserted to the Employees instance variable of
|
tags, which are inserted to the Employees instance variable of
|
||||||
@@ -154,7 +154,7 @@ class autoxml(type):
|
|||||||
It is also possible to change the XML path we expect the tag in,
|
It is also possible to change the XML path we expect the tag in,
|
||||||
just like with any other tag.
|
just like with any other tag.
|
||||||
|
|
||||||
t_Employees = [ Employee, xmlfile.mandatory, 'Employees/Employee']
|
t_Employees = [ [Employee], xmlfile.mandatory, 'Employees/Employee']
|
||||||
|
|
||||||
|
|
||||||
You see, it works like magic, when it works of course. All of it
|
You see, it works like magic, when it works of course. All of it
|
||||||
@@ -175,12 +175,11 @@ class autoxml(type):
|
|||||||
#TODO: initialize class attribute __xml_tags
|
#TODO: initialize class attribute __xml_tags
|
||||||
#setattr(cls, 'xml_variables', [])
|
#setattr(cls, 'xml_variables', [])
|
||||||
|
|
||||||
if not dict.has_key('tag'):
|
# default class tag is class name
|
||||||
setattr(cls, 'tag', name)
|
if not dict.has_key('tag'):
|
||||||
|
cls.tag = name
|
||||||
|
|
||||||
root_tag = cls.tag
|
# generate helper routines, for each XML component
|
||||||
|
|
||||||
# generate helper routines
|
|
||||||
inits = []
|
inits = []
|
||||||
decoders = []
|
decoders = []
|
||||||
encoders = []
|
encoders = []
|
||||||
@@ -188,177 +187,208 @@ class autoxml(type):
|
|||||||
for var in dict:
|
for var in dict:
|
||||||
if var.startswith('t_') or var.startswith('a_'):
|
if var.startswith('t_') or var.startswith('a_'):
|
||||||
name = var[2:]
|
name = var[2:]
|
||||||
#print 'name', name
|
print 'generating member', name
|
||||||
if var.startswith('t_'):
|
if var.startswith('a_'):
|
||||||
x = autoxml.gen_tag(cls, name)
|
x = autoxml.gen_attr_member(cls, name)
|
||||||
elif var.startswith('a_'):
|
elif var.startswith('t_'):
|
||||||
x = autoxml.gen_attr(cls, name)
|
x = autoxml.gen_tag_member(cls, name)
|
||||||
ctx.ui.debug(x)
|
|
||||||
(init, decoder, encoder, formatter) = x
|
(init, decoder, encoder, formatter) = x
|
||||||
inits.append(init)
|
inits.append(init)
|
||||||
decoders.append(decoder)
|
decoders.append(decoder)
|
||||||
encoders.append(encoder)
|
encoders.append(encoder)
|
||||||
formatters.append(formatter)
|
formatters.append(formatter)
|
||||||
|
|
||||||
varname = cls.mixed_case(name)
|
# generate top-level helper functions
|
||||||
|
cls.initializers = inits
|
||||||
setattr(cls, 'initializers', inits)
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
for init in self.__class__.initializers:
|
for init in self.__class__.initializers:
|
||||||
init(self)
|
init(self)
|
||||||
setattr(cls, '__init__', initialize)
|
cls.__init__ = initialize
|
||||||
|
|
||||||
setattr(cls, 'decoders', decoders)
|
cls.decoders = decoders
|
||||||
def decode(self, node):
|
def decode(self, node):
|
||||||
for decoder in self.__class__.decoders:
|
for decoder in self.__class__.decoders:
|
||||||
setattr(self, varname, decoder(self, node))
|
decoder(self, node)
|
||||||
setattr(cls, 'decode', decode)
|
cls.decode = decode
|
||||||
|
|
||||||
setattr(cls, 'encoders', encoders)
|
cls.encoders = encoders
|
||||||
def encode(self, xml):
|
def encode(self, xml):
|
||||||
for encoder in self.__class__.encoders:
|
for encoder in self.__class__.encoders:
|
||||||
encoder(self, xml, getattr(self, varname))
|
encoder(self, xml)
|
||||||
setattr(cls, 'encode', encode)
|
cls.encode = encode
|
||||||
|
|
||||||
setattr(cls, 'formatters', formatters)
|
cls.formatters = formatters
|
||||||
def format(self):
|
def format(self):
|
||||||
string = ''
|
string = ''
|
||||||
for formatter in self.__class__.formatters:
|
for formatter in self.__class__.formatters:
|
||||||
string = string + formatter(self)
|
string += formatter(self)
|
||||||
return string
|
return string
|
||||||
setattr(cls, 'format', format)
|
cls.format = format
|
||||||
if not dict.has_key('__str__'):
|
if not dict.has_key('__str__'):
|
||||||
def string(self):
|
cls.__str__ = format
|
||||||
return self.format()
|
|
||||||
setattr(cls, '__str__', string)
|
|
||||||
|
|
||||||
def gen_tag(cls, tag):
|
def gen_attr_member(cls, attr):
|
||||||
# generate readers and writers for the tag
|
"""generate readers and writers for an attribute member"""
|
||||||
val = getattr(cls, 't_' + tag)
|
print 'attr:', attr
|
||||||
tag_type = val[0]
|
spec = getattr(cls, 'a_' + attr)
|
||||||
return autoxml.gen_tag_aux(cls, tag, tag_type, val)
|
tag_type = spec[0]
|
||||||
|
|
||||||
def gen_tag_aux(cls, tag, tag_type, val):
|
|
||||||
if type(tag_type) == types.TypeType:
|
|
||||||
# basic types
|
|
||||||
return autoxml.gen_basic_tag(cls, tag, val)
|
|
||||||
elif type(tag_type) == types.ClassType:
|
|
||||||
return autoxml.gen_class_tag(cls, tag, val)
|
|
||||||
elif type(tag_type) == types.ListType:
|
|
||||||
return autoxml.gen_list_tag(cls, tag, val)
|
|
||||||
|
|
||||||
def gen_attr(cls, tag):
|
|
||||||
"generate readers and writers for an attribute"
|
|
||||||
#print 'attr:', tag
|
|
||||||
val = getattr(cls, 'a_' + tag)
|
|
||||||
tag_type = val[0]
|
|
||||||
assert type(tag_type) == type(type)
|
assert type(tag_type) == type(type)
|
||||||
return autoxml.gen_basic_attr(cls, tag, val)
|
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 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 gen_named_comp(cls, token, spec, anonfuns):
|
||||||
|
"""generate a named component tag/attr. a decoration of
|
||||||
|
anonymous functions that do not bind to variable names"""
|
||||||
|
name = cls.mixed_case(token)
|
||||||
|
token_type = spec[0]
|
||||||
|
req = spec[1]
|
||||||
|
(init_a, decode_a, encode_a, format_a) = anonfuns
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
setattr(self, name, init_a())
|
||||||
|
|
||||||
|
def decode(self, node):
|
||||||
|
setattr(self, name, decode_a(node))
|
||||||
|
|
||||||
|
def encode(self, xml):
|
||||||
|
if hasattr(self, name):
|
||||||
|
value = getattr(self, name)
|
||||||
|
else:
|
||||||
|
value = None
|
||||||
|
encode_a(xml, value)
|
||||||
|
|
||||||
|
def format(self):
|
||||||
|
if hasattr(self, name):
|
||||||
|
value = getattr(self,name)
|
||||||
|
return '%s: %s\n' % (token, format_a(value))
|
||||||
|
else:
|
||||||
|
if req == mandatory:
|
||||||
|
raise Error('Mandatory variable %s not available' % name)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
return (init, decode, encode, format)
|
||||||
|
|
||||||
|
def gen_tag(cls, tag, spec, readtext, writetext):
|
||||||
|
"""generate readers and writers for the tag"""
|
||||||
|
tag_type = spec[0]
|
||||||
|
if type(tag_type) == types.TypeType:
|
||||||
|
return cls.gen_anon_basic(tag, spec, readtext, writetext)
|
||||||
|
elif type(tag_type) == types.ListType:
|
||||||
|
return cls.gen_list_tag(tag, spec, readtext, writetext)
|
||||||
|
elif type(tag_type) == types.ClassType:
|
||||||
|
return cls.gen_class_tag(tag, spec, readtext, writetext)
|
||||||
|
|
||||||
def mixed_case(cls, identifier):
|
def mixed_case(cls, identifier):
|
||||||
|
"""helper function to turn token name into mixed case"""
|
||||||
identifier_p = identifier[0].lower() + identifier[1:]
|
identifier_p = identifier[0].lower() + identifier[1:]
|
||||||
return identifier_p
|
return identifier_p
|
||||||
|
|
||||||
def gen_basic(cls, token, val, readtext, writetext):
|
def gen_anon_basic(cls, token, spec, readtext, writetext):
|
||||||
"""Generate a basic tag or attribute. This has got
|
"""Generate a tag or attribute with one of the basic
|
||||||
to be pretty generic so we can invoke it from the complex
|
types like integer. This has got to be pretty generic
|
||||||
types such as Class and List"""
|
so 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."""
|
||||||
|
|
||||||
name = cls.mixed_case(token)
|
name = cls.mixed_case(token)
|
||||||
token_type = val[0]
|
token_type = spec[0]
|
||||||
req = val[1]
|
req = spec[1]
|
||||||
|
|
||||||
def initialize(self):
|
def initialize():
|
||||||
#print 'init:', name
|
"""default value for all basic types is None"""
|
||||||
setattr(self, name, None)
|
return None
|
||||||
|
|
||||||
def decode(self, node):
|
def decode(node):
|
||||||
|
"""decode from DOM node, the value, watching the spec"""
|
||||||
text = readtext(node, token)
|
text = readtext(node, token)
|
||||||
|
print 'read text ', text
|
||||||
if text:
|
if text:
|
||||||
try:
|
try:
|
||||||
value = autoxml.basic_cons_map[token_type](text)
|
value = autoxml.basic_cons_map[token_type](text)
|
||||||
except Error:
|
except Error:
|
||||||
raise Error('Type mismatch')
|
raise Error('Type mismatch: read text cannot be decoded')
|
||||||
setattr(self, name, value)
|
return value
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
raise Error('Mandatory argument not available')
|
raise Error('Mandatory argument not available')
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def encode(self, xml, value):
|
def encode(xml, value):
|
||||||
|
"""encode given value into xml file"""
|
||||||
node = xml.newNode(cls.tag)
|
node = xml.newNode(cls.tag)
|
||||||
if hasattr(self, name):
|
if value:
|
||||||
writetext(xml, node, token, str(value))
|
writetext(xml, node, token, str(value))
|
||||||
else:
|
else:
|
||||||
if req == mandatory:
|
if req == mandatory:
|
||||||
raise Error('Mandatory argument not available')
|
raise Error('Mandatory argument not available')
|
||||||
|
|
||||||
def format(self):
|
def format(value):
|
||||||
if hasattr(self, name):
|
return str(value)
|
||||||
return '%s: %s\n' % (token, str(getattr(self, name)))
|
|
||||||
else:
|
|
||||||
if req == mandatory:
|
|
||||||
raise Error('Mandatory variable %s not available' % name)
|
|
||||||
return ""
|
|
||||||
|
|
||||||
return initialize, decode, encode, format
|
return initialize, decode, encode, format
|
||||||
|
|
||||||
def gen_basic_attr(cls, attr, spec):
|
def gen_class_tag(cls, tag, spec, readtext, writetext):
|
||||||
"""generate an attribute with a basic datatype"""
|
|
||||||
def readtext(node, attr):
|
|
||||||
return getNodeAttribute(node, attr)
|
|
||||||
def writetext(xml, node, attr, value):
|
|
||||||
node.setAttribute(attr, value)
|
|
||||||
return autoxml.gen_basic(cls, attr, spec, readtext, writetext)
|
|
||||||
|
|
||||||
def gen_basic_tag(cls, tag, spec):
|
|
||||||
"""generate a tag with a basic datatype"""
|
|
||||||
def readtext(node, tag):
|
|
||||||
return getNodeText(getNode(node, tag))
|
|
||||||
def writetext(xml, node, tag, value):
|
|
||||||
xml.addTextNodeUnder(node, tag, value)
|
|
||||||
return autoxml.gen_basic(cls, tag, spec, readtext, writetext)
|
|
||||||
|
|
||||||
def gen_class_tag(cls, tag, val):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def gen_list_tag(cls, tag, val):
|
def gen_list_tag(cls, tag, spec, readtext, writetext):
|
||||||
|
""" generate a list member of a class. we do not support
|
||||||
|
list members that are embedded in lists. """
|
||||||
name = cls.mixed_case(tag)
|
name = cls.mixed_case(tag)
|
||||||
tag_type = val[0]
|
tag_type = spec[0]
|
||||||
req = val[1]
|
req = spec[1]
|
||||||
|
|
||||||
if len(val)>=3:
|
if len(spec)>=3:
|
||||||
path = val[2] # an alternative path specified
|
path = spec[2] # an alternative path specified
|
||||||
else:
|
else:
|
||||||
path = tag # otherwise it's the same name as
|
path = tag # otherwise it's the same name as
|
||||||
# the tag
|
# the tag
|
||||||
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')
|
||||||
x = autoxml.gen_tag_aux(cls, tag, tag_type[0], val)
|
def readtext(node, tag):
|
||||||
|
return getNodeText(node)
|
||||||
|
def writetext(xml, node, tag, value):
|
||||||
|
xml.addTextNode(node, value)
|
||||||
|
x = cls.gen_tag(tag, [tag_type[0], mandatory], readtext, writetext)
|
||||||
(init_item, decode_item, encode_item, format_item) = x
|
(init_item, decode_item, encode_item, format_item) = x
|
||||||
|
|
||||||
def init(self):
|
def init():
|
||||||
setattr(self, name, [])
|
return []
|
||||||
|
|
||||||
def decode(self, node):
|
def decode(node):
|
||||||
l = []
|
l = []
|
||||||
self.nodes = getAllNodes(node, path)
|
nodes = getAllNodes(node, path)
|
||||||
print 'F U', self.nodes
|
print 'F U', nodes
|
||||||
if len(self.nodes) is 0 and req is mandatory:
|
if len(nodes) is 0 and req is mandatory:
|
||||||
raise Error('Mandatory list empty')
|
raise Error('Mandatory list empty')
|
||||||
for node in self.nodes:
|
for node in nodes:
|
||||||
l.append(decode_item(self, node))
|
l.append(decode_item(node))
|
||||||
return l
|
return l
|
||||||
|
|
||||||
def encode(self, xml, value):
|
def encode(xml, l):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def format(self):
|
def format(l):
|
||||||
#print 'format:', name
|
#print 'format:', name
|
||||||
s = ''
|
s = ''
|
||||||
l = getattr(self, name)
|
|
||||||
for ix in range(len(l)):
|
for ix in range(len(l)):
|
||||||
s += str(ix) + format_item(l[ix])
|
s += str(ix+1) + ': ' + format_item(l[ix])
|
||||||
|
if ix != len(l)-1:
|
||||||
|
s += ', '
|
||||||
return s
|
return s
|
||||||
|
|
||||||
return (init, decode, encode, format)
|
return (init, decode, encode, format)
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ 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():
|
||||||
@@ -59,6 +62,7 @@ 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:]
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class XmlFileTestCase(unittest.TestCase):
|
|||||||
t_Number = [types.IntType, xmlfile.optional]
|
t_Number = [types.IntType, xmlfile.optional]
|
||||||
t_Email = [types.StringType, xmlfile.optional]
|
t_Email = [types.StringType, xmlfile.optional]
|
||||||
a_href = [types.StringType, xmlfile.mandatory]
|
a_href = [types.StringType, xmlfile.mandatory]
|
||||||
#t_Projects = [ [types.StringType], xmlfile.mandatory]
|
t_Projects = [ [types.StringType], xmlfile.mandatory, 'Projects/Project']
|
||||||
a = A()
|
a = A()
|
||||||
self.assertEqual(a.href, None)
|
self.assertEqual(a.href, None)
|
||||||
dom = mdom.parse('tests/a.xml')
|
dom = mdom.parse('tests/a.xml')
|
||||||
@@ -43,13 +43,15 @@ class XmlFileTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(a.number, 868)
|
self.assertEqual(a.number, 868)
|
||||||
self.assertEqual(a.name, 'Eray Ozkural')
|
self.assertEqual(a.name, 'Eray Ozkural')
|
||||||
string = a.format()
|
string = a.format()
|
||||||
#print '*', string
|
print '*', string
|
||||||
#self.assert_(string.startswith('Name'))
|
#self.assert_(string.startswith('Name'))
|
||||||
outfn = '/tmp/a2.xml'
|
outfn = '/tmp/a2.xml'
|
||||||
xml = xmlfile.XmlFile('A')
|
xml = xmlfile.XmlFile('A')
|
||||||
a2 = A()
|
a2 = A()
|
||||||
a2.name = "Baris Metin"
|
a2.name = "Baris Metin"
|
||||||
a2.email = "baris@uludag.org.tr"
|
a2.email = "baris@uludag.org.tr"
|
||||||
|
a2.href = 'http://cekirdek.uludag.org.tr/~baris'
|
||||||
|
a2.projects = [ 'pisi', 'tasma', 'plasma' ]
|
||||||
elt = a2.encode(xml)
|
elt = a2.encode(xml)
|
||||||
string = a2.format()
|
string = a2.format()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user