I am trying to use a Python function defined in my template in a py:for directive, and am encountering errors. The areainfolist function processes a deep dictionary object in DATA and returns a list of dictionary objects found in the dictionary in DATA, and I cannot change the format of the DATA consumed by the template.
import genshi.template
TEMPLATE = """<?xml version="1.0"?>
<?python
def areainfolist(areas_cfg):
results = []
opt_props = ['isphased', 'keepupcount', 'standbycount', 'iseditkeepup', 'playspindowntimer', 'editspindowntimer', 'depopspindowntimer']
for k, v in areas_cfg:
area = {
"name": k,
"id": v["id"],
"popfloor": v["popfloor"],
"popsoftcap": v["popsoftcap"],
"popfull": v["popfull"]
}
for opt_prop in opt_props:
if opt_prop in v:
area[opt_prop] = v[opt_prop]
results.append(area)
return results
?>
<area py:for="area in areainfolist(config.shard.areas)" py:attrs="area"></area>
</areainfolist>"""
DATA = {
"shard": {
"areas": {
"ald_main": {
"id": "4611686023868513034",
"isphased": "0",
"keepupcount": "1",
"planned-load": "120",
"planned-memory": "3000000000",
"popfloor": "70",
"popsoftcap": "150",
"popfull": "175"
},
"dro_knight": {
"id": "4611686087038969857",
"isphased": "0",
"keepupcount": "0",
"planned-load": "5",
"planned-memory": "2000000000",
"popfloor": "12",
"popsoftcap": "30",
"popfull": "50"
}
}
}
}
template_filename = "template.xml"
with open(template_filename, "w") as outfile:
outfile.write(TEMPLATE)
template_loader = genshi.template.TemplateLoader([os.getcwd()])
template = template_loader.load("template.xml")
generated = template.generate(config=DATA)
rendered = generated.render()
print rendered
Traceback (most recent call last):
File "genshitest.py", line 62, in <module>
rendered = generated.render()
File "/usr/lib64/python2.6/site-packages/genshi/core.py", line 179, in render
return encode(generator, method=method, encoding=encoding, out=out)
File "/usr/lib64/python2.6/site-packages/genshi/output.py", line 60, in encode
return _encode(u''.join(list(iterator)))
File "/usr/lib64/python2.6/site-packages/genshi/output.py", line 210, in __call__
for kind, data, pos in stream:
File "/usr/lib64/python2.6/site-packages/genshi/output.py", line 592, in __call__
for kind, data, pos in stream:
File "/usr/lib64/python2.6/site-packages/genshi/output.py", line 698, in __call__
for kind, data, pos in chain(stream, [(None, None, None)]):
File "/usr/lib64/python2.6/site-packages/genshi/output.py", line 532, in __call__
for ev in stream:
File "/usr/lib64/python2.6/site-packages/genshi/core.py", line 283, in _ensure
for event in stream:
File "/usr/lib64/python2.6/site-packages/genshi/template/base.py", line 569, in _include
for event in stream:
File "/usr/lib64/python2.6/site-packages/genshi/template/markup.py", line 245, in _match
for event in stream:
File "/usr/lib64/python2.6/site-packages/genshi/template/base.py", line 543, in _exec
for event in stream:
File "/usr/lib64/python2.6/site-packages/genshi/template/base.py", line 496, in _eval
for kind, data, pos in stream:
File "/usr/lib64/python2.6/site-packages/genshi/template/base.py", line 558, in _flatten
for event in self._flatten(substream, ctxt, **vars):
File "/usr/lib64/python2.6/site-packages/genshi/template/base.py", line 551, in _flatten
for event in stream:
File "/usr/lib64/python2.6/site-packages/genshi/template/directives.py", line 370, in __call__
iterable = _eval_expr(self.expr, ctxt, **vars)
File "/usr/lib64/python2.6/site-packages/genshi/template/base.py", line 286, in _eval_expr
retval = expr.evaluate(ctxt)
File "/usr/lib64/python2.6/site-packages/genshi/template/eval.py", line 180, in evaluate
return eval(self.code, _globals, {'__data__': data})
File "/home/agooch/.workspace/genshitest/src/template.xml", line 21, in <Expression u'iter(areainfolist(config.shard.areas))'>
<area py:for="area in areainfolist(config.shard.areas)" py:attrs="area"></area>
File "<string>", line 4, in areainfolist
ValueError: too many values to unpack
Is what I'm trying to do possible with Genshi? I'm stumped as to how this might be done, but I really need to preserve the structure of the original DATA yet process it as a list built at render time by the function defined in my original TEMPLATE.