from pycropml.transpiler.generators.pythonGenerator import PythonGenerator, PythonCompo
import os
from pycropml.composition import model_parser
from path import Path
try:
from openalea.core import interface as inter
from openalea.core import package, CompositeNodeFactory, CompositeNode
from openalea.core import node
from pycropml.xml2wf import XmlToWf
from openalea.core.pkgmanager import PackageManager
except:
inter = None
package = None
node = None
has_openalea = False
[docs]
class OpenaleaGenerator(PythonGenerator):
""" This class contains the specific properties of
OpenAlea and use the NodeVisitor to generate a csharp
code source from a well formed syntax tree.
"""
def __init__(self, tree=None, model=None, name=None):
self.tree = tree
self.model=model
self.name = name
self.indent_with=' '*4
PythonGenerator.__init__(self, tree, model, name)
[docs]
def visit_module(self, node):
self.newline(extra=1)
self.newline(node)
self.write("# coding: utf8")
self.newline(node)
#self.write("from pycropml.units import u")
#self.newline(node)
self.write("from copy import copy\nfrom array import array\nfrom math import *\nfrom typing import *\nfrom datetime import datetime\n")
self.newline(node)
self.visit(node.body)
[docs]
def visit_local(self, node):
self.write(node.name)
[docs]
def visit_int(self, node):
self.write(node.value)
[docs]
def visit_float(self, node):
self.write(node.value)
[docs]
def visit_importfrom(self, node):
if self.imp:
self.newline(node)
if node.namespace not in ["math", "array", "typing", "datetime"]:
self.write('from %s import ' % (node.namespace))
for idx, item in enumerate(node.name):
if idx:
self.write(', ')
self.write(item)
[docs]
class OpenaleaCompo(PythonCompo):
def __init__(self, tree, model=None, name=None):
self.tree = tree
self.model = model
self.name = name
PythonCompo.__init__(self,tree, model, self.name)
self.generate_wralea(self.model)
[docs]
def generate_wralea(self, mc):
"""Generate wralea factories from the meta-information of the the model units."""
'''if not has_openalea:
return'''
# TODO
metainfo = {'version': '0.0.1',
'license': 'CECILL-C',
'authors': 'AMEI Consortium',
'institutes': '',
'description': 'CropML Model library.',
'url': 'http://crop2ml.org',
'icon': ''}
metainfo['alias']= [mc.name]
split_name = (mc.id).lower().split('.') # remove the name of the workflow
names = split_name[:-1] if len(split_name) >2 else split_name
names.insert(0, 'amei')
name = '.'.join(names).lower()
wra_path = mc.path.split(os.path.sep)[-1].replace('-', '_')
path = Path(os.path.join(mc.path,"src","openalea", wra_path))
_package = package.UserPackage(name, metainfo, path)
print(name, path)
for model in mc.model:
if not model.package_name or model.package_name=="unit":
_factory = self.generate_factory(model)
print(_factory.name)
_package.add_factory(_factory)
else:
pass
_package.write()
writer = XmlToWf(mc, path, name)
writer.run()
writer.pkg.name = name
writer.pkg.write()
[docs]
def generate_factory(self, model):
"""Create a Node Factory from CropML model unit."""
'''if not has_openalea:
return'''
inputs = []
for input in model.inputs:
name = input.name
dtype = input.datatype
interface = openalea_interface(input)
if dtype not in ('STRING', 'BOOLEAN' ,'DATE') and 'default' in dir(input):
#print(input.default)
value = eval(input.default) if input.default else 0
_in = dict(name=name, interface=interface, value=value)
elif 'default' in dir(input):
value=input.default.capitalize() if dtype=="BOOLEAN" else input.default
_in = dict(name=name, interface=interface, value=value)
elif 'default' not in dir(input):
_in = dict(name=name, interface=interface)
value = None
#value = eval(input.default) if dtype != 'string'else input.default
inputs.append(_in)
outputs = []
for output in model.outputs:
name = output.name
dtype = output.datatype
interface = openalea_interface(output)
_out = dict(name=name, interface=interface)
outputs.append(_out)
_factory = node.Factory(name=model.name,
description=model.description.ExtendedDescription,
nodemodule=signature(model),
nodeclass="model_%s"%(signature(model)),
inputs=inputs,
outputs=outputs,
)
return _factory
[docs]
def signature(model):
name = model.name
name = name.strip()
name = name.replace(' ', '_').lower()
return name
[docs]
def openalea_interface(inout):
if inter is None:
return None
dtype = inout.datatype.lower().strip()
interface = None
kwds = {}
if inout.min:
kwds['min'] = inout.min
if inout.max:
kwds['max'] = inout.max
if dtype in ('int', 'float', 'double') :
interface =inter.IInt if dtype == 'int' else inter.IFloat
if ('min' in kwds) and ('max' in kwds) and (eval(inout.min)!=None) and (eval(inout.max)!=None):
#print(inout)
interface = interface(min=eval(inout.min), max=eval(inout.max))
elif 'min' in kwds and (eval(inout.min)!=None):
interface = interface (min=eval(inout.min))
elif 'max' in kwds and (eval(inout.max)!=None):
interface = interface(max=eval(inout.max))
elif 'default' in dir(inout):
interface = interface(min=eval(inout.default), max=eval(inout.default))
elif dtype == 'string':
interface = inter.IStr
elif dtype == "boolean":
interface = inter.IBool
elif dtype == "date":
interface = inter.IDateTime
elif dtype in ("doublelist", "intlist", "stringlist","datelist", "doublearray", "intarray", "datearray"):
interface=inter.ISequence
return interface