1 # Copyright (C) 2009-2014 EDF R&D
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 This module defines the ASTERComponent class for ASTER component generation
22 An ASTER component comes in 3 flavors :
23 - implemented as a dynamic library (kind='lib')
24 - implemented as a standalone component (kind='exe')
25 - implemented as a specific container (kind='cexe')
29 from gener import Component, Invalid, makedirs
31 from pyth_tmpl import pyinitEXEService, pyinitCEXEService, pyinitService
33 from aster_tmpl import asterCEXEService, asterEXEService
34 from aster_tmpl import asterService, asterEXECompo, asterCEXECompo, asterCompo
35 from aster_tmpl import comm, make_etude, cexe, exeaster
36 from aster_tmpl import container, component
37 from aster_tmpl import cmake_src_compo_aster, cmake_src_compo_aster_lib
39 class ASTERComponent(Component):
41 A :class:`ASTERComponent` instance represents an ASTER SALOME component (special component for Code_Aster that is a mix of
42 Fortran and Python code) with services given as a list of :class:`Service` instances with the parameter *services*.
44 :param name: gives the name of the component.
46 :param services: the list of services (:class:`Service`) of the component.
47 :param kind: If it is given and has the value "exe", the component will be built as a standalone
48 component (executable or shell script). The default is to build the component as a dynamic library.
49 :param libs: gives all the libraries options to add when linking the generated component (-L...).
50 :param rlibs: gives all the runtime libraries options to add when linking the generated component (-R...).
51 :param exe_path: is only used when kind is "exe" and gives the path to the standalone component.
52 :param aster_dir: gives the Code_Aster installation directory.
53 :param python_path: If it is given (as a list of paths), all the paths are added to the python path (sys.path).
54 :param argv: is a list of strings that gives the command line parameters for Code_Aster. This parameter is only useful when
57 For example, the following call defines a Code_Aster component named "mycompo" with one service s1 (it must have been defined before).
58 This standalone component takes some command line arguments::
60 >>> c1 = module_generator.ASTERComponent('mycompo', services=[s1,], kind="exe",
62 argv=["-memjeveux","4"])
64 def __init__(self, name, services=None, libs=[], rlibs="", aster_dir="",
65 python_path=None, argv=None, kind="lib", exe_path=None):
66 """initialise component attributes"""
67 self.aster_dir = aster_dir
68 self.python_path = python_path or []
69 self.argv = argv or []
70 self.exe_path = exe_path
71 self.aster_version_type = aster_version_type
72 Component.__init__(self, name, services, impl="ASTER", libs=libs,
73 rlibs=rlibs, kind=kind)
76 """validate the component definition"""
77 Component.validate(self)
78 if not self.aster_dir:
79 raise Invalid("aster_dir must be defined for component %s" % self.name)
81 kinds = ("lib", "cexe", "exe")
82 if self.kind not in kinds:
83 raise Invalid("kind must be one of %s for component %s" % (kinds,self.name))
84 if self.kind == "lib" and not self.python_path:
85 raise Invalid("python_path must be defined for component %s" % self.name)
86 if self.kind == "cexe" :
88 raise Invalid("exe_path must be defined for component %s" % self.name)
89 if self.kind == "exe" :
91 raise Invalid("exe_path must be defined for component %s" % self.name)
93 #Si un port de nom jdc n'est pas defini dans la liste des inports du service,
94 #on en ajoute un de type string en premiere position
95 for serv in self.services:
97 for port_name,port_type in serv.inport:
98 if port_name == "jdc":
102 serv.inport.insert(0, ("jdc", "string"))
104 def libraryName(self):
105 """ Name of the target library
106 No library for an aster component
110 def getAsterPythonPath(self):
111 """Directory of aster python modules
113 python_version_dir = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
114 aster_python_path = os.path.join(self.aster_dir, "lib", python_version_dir, "site-packages")
116 if not os.path.exists(aster_python_path) :
117 aster_python_path = os.path.join(self.aster_dir, "bibpyt")
119 return aster_python_path
121 # def getConfig(self, gen):
122 # """Content of the config.txt file
124 # path_compo=os.path.join(os.path.abspath(gen.module.prefix),'lib',
125 # 'python%s.%s' % (sys.version_info[0], sys.version_info[1]),
126 # 'site-packages','salome','%s_component.py'%self.name)
127 # conf="""ENV_SH | env | - | $ASTER_VERSION_DIR/share/aster/profile.sh
128 #BINELE | bin | - | $ASTER_VERSION_DIR/share/aster/elements
129 #SRCPY | src | - | %s
130 #ARGPYT | exec | - | %s
131 #""" % (self.getAsterPythonPath(), path_compo)
135 def makeCompo(self, gen):
136 """drive the generation of SALOME module files and code files
137 depending on the choosen component kind
139 filename = "%s.py" % self.name
140 #on suppose que les composants ASTER sont homogenes (utilisent meme install)
141 gen.aster = self.aster_dir
144 # f = os.path.join(self.aster_dir, self.getAsterPythonPath(), 'Accas', 'properties.py')
145 # self.version=(0,0,0)
146 # if os.path.isfile(f):
148 # execfile(f, mydict)
149 # v,r,p = mydict['version'].split('.')
150 # self.version=(int(v),int(r),int(p))
152 if self.kind == "lib":
154 return {"CMakeLists.txt":cmake_src_compo_aster_lib.substitute(sources=f),
155 filename:self.makeaster(gen)}
156 elif self.kind == "cexe":
157 fdict=self.makecexepath(gen)
158 sources = self.name + ".py\n " + self.name + "_container.py"
159 if self.version < (10,1,2):
160 sources = sources + "\n E_SUPERV.py"
161 d= {"CMakeLists.txt":cmake_src_compo_aster.substitute(
163 module=gen.module.name,
164 resources=self.name+"_config.txt",
165 scripts=self.name+".exe"),
166 self.name+".exe":cexe.substitute(compoexe=self.exe_path),
167 filename:self.makecexeaster(gen)
171 elif self.kind == "exe":
172 fdict=self.makeexepath(gen)
173 sources = self.name + "_module.py\n "
174 sources = sources + self.name + "_component.py"
175 if self.version < (10,1,2):
176 sources = sources + "\n E_SUPERV.py"
177 d= {"CMakeLists.txt":cmake_src_compo_aster.substitute(
179 module=gen.module.name,
180 resources=self.name+"_config.txt",
181 scripts=self.name+".exe"),
182 self.name+".exe":exeaster.substitute(compoexe=self.exe_path),
183 self.name+"_module.py":self.makeexeaster(gen)
188 def makeexepath(self, gen):
189 """standalone component: generate files for calculation code"""
193 # if self.version < (10,1,2):
194 #patch to E_SUPERV.py
195 # fil = open(os.path.join(self.aster_dir, "bibpyt", "Execution", "E_SUPERV.py"))
196 # esuperv = fil.read()
198 # esuperv = re.sub("def Execute\(self\)", "def Execute(self, params)", esuperv)
199 # esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv)
200 # esuperv = re.sub("\*\*args", "context_ini=params, **args", esuperv)
201 # esuperv = re.sub("def main\(self\)", "def main(self,params={})", esuperv)
202 # esuperv = re.sub("return self.Execute\(\)", "return self.Execute(params)", esuperv)
203 # fdict["E_SUPERV.py"]=esuperv
205 #use a specific main program (modification of config.txt file)
207 # path_config = os.path.join(self.aster_dir, "config.txt")
208 # if os.path.exists(path_config) :
209 # old aster version - old mechanism kept for compatibility
210 # fil = open(path_config)
211 # config = fil.read()
213 # config = re.sub(" profile.sh", os.path.join(self.aster_dir, "profile.sh"), config)
214 # path=os.path.join(os.path.abspath(gen.module.prefix),'lib',
215 # 'python%s.%s' % (sys.version_info[0], sys.version_info[1]),
216 # 'site-packages','salome','%s_component.py'%self.name)
217 # config = re.sub("Execution\/E_SUPERV.py", path, config)
219 # getConfig doesn't work with older versions of aster
220 # config = self.getConfig(gen)
222 # fdict["%s_config.txt" % self.name] = config
223 fdict["%s_component.py" % self.name] = component.substitute(component=self.name)
227 def makecexepath(self, gen):
228 """specific container: generate files"""
232 # if self.version < (10,1,2):
233 #patch to E_SUPERV.py
234 # fil = open(os.path.join(self.aster_dir, "bibpyt", "Execution", "E_SUPERV.py"))
235 # esuperv = fil.read()
237 # esuperv = re.sub("def Execute\(self\)", "def Execute(self, params)", esuperv)
238 # esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv)
239 # esuperv = re.sub("\*\*args", "context_ini=params, **args", esuperv)
240 # esuperv = re.sub("def main\(self\)", "def main(self,params={})", esuperv)
241 # esuperv = re.sub("return self.Execute\(\)", "return self.Execute(params)", esuperv)
242 # fdict["E_SUPERV.py"]=esuperv
244 #use a specific main program
246 # path_config = os.path.join(self.aster_dir, "config.txt")
247 # if os.path.exists(path_config) :
248 # old aster version - old mechanism kept for compatibility
249 # fil = open(path_config)
250 # config = fil.read()
252 # config = re.sub(" profile.sh", os.path.join(self.aster_dir, "profile.sh"), config)
253 # path=os.path.join(os.path.abspath(gen.module.prefix),'lib',
254 # 'python%s.%s' % (sys.version_info[0], sys.version_info[1]),
255 # 'site-packages','salome','%s_container.py' % self.name)
256 # config = re.sub("Execution\/E_SUPERV.py", path, config)
258 # getConfig doesn't work with older versions of aster
259 # config = self.getConfig(gen)
261 fdict["%s_container.py" % self.name] = container
262 # fdict["%s_config.txt" % self.name] = config
266 def getImportESuperv(self):
269 import os.path as osp
270 from asrun.run import AsRunFactory
271 from asrun.config import AsterConfig
274 path = run.get_version_path(VERS)
275 cfg = AsterConfig(osp.join(path, 'config.txt'))
276 pypath = cfg['REPPY'][0]
278 sys.path.insert(0, pypath)
279 from Execution.E_SUPERV import SUPERV
280 """ % self.aster_version_type
284 def makeexeaster(self, gen):
285 """standalone component: generate SALOME component source"""
289 for serv in self.services:
290 defs.append(serv.defs)
293 for name, typ in serv.inport:
294 if typ=="file":continue #files are not passed through service interface
297 datas.append('"%s":cPickle.loads(%s)' % (name, name))
299 datas.append('"%s":%s' % (name, name))
300 #ajout de l'adresse du composant
301 datas.append('"component":self.proxy.ptr()')
302 dvars = "{"+','.join(datas)+"}"
303 inparams = ",".join(params)
307 for name, typ in serv.outport:
308 if typ=="file":continue #files are not passed through service interface
311 datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
313 datas.append('j.g_context["%s"]'%name)
314 outparams = ",".join(params)
315 rvars = ",".join(datas)
317 service = asterEXEService.substitute(component=self.name,
322 dvars=dvars, rvars=rvars)
324 for name, typ, dep in serv.instream:
325 streams.append(' calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
326 instream = "\n".join(streams)
328 for name, typ, dep in serv.outstream:
329 streams.append(' calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
330 outstream = "\n".join(streams)
332 init = pyinitEXEService.substitute(component=self.name, service=serv.name,
333 instream=instream, outstream=outstream)
334 services.append(service)
337 importesuperv = self.getImportESuperv()
339 return asterEXECompo.substitute(component=self.name, module=gen.module.name,
340 servicesdef="\n".join(defs),
341 servicesimpl="\n".join(services),
342 initservice='\n'.join(inits),
343 aster_dir=self.aster_dir,
344 importesuperv=importesuperv,
347 def makecexeaster(self, gen):
348 """specific container: generate SALOME component source"""
352 for serv in self.services:
353 defs.append(serv.defs)
356 for name, typ in serv.inport:
357 if typ=="file":continue #files are not passed through service interface
360 datas.append('"%s":cPickle.loads(%s)' % (name, name))
362 datas.append('"%s":%s' % (name, name))
363 #ajout de l'adresse du composant
364 datas.append('"component":self.proxy.ptr()')
365 dvars = "{"+','.join(datas)+"}"
366 inparams = ",".join(params)
370 for name, typ in serv.outport:
373 datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
375 datas.append('j.g_context["%s"]'%name)
376 outparams = ",".join(params)
377 rvars = ",".join(datas)
379 service = asterCEXEService.substitute(component=self.name,
384 dvars=dvars, rvars=rvars)
386 for name, typ, dep in serv.instream:
387 streams.append(' calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
388 instream = "\n".join(streams)
390 for name, typ, dep in serv.outstream:
391 streams.append(' calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
392 outstream = "\n".join(streams)
394 init = pyinitCEXEService.substitute(component=self.name,
398 services.append(service)
401 importesuperv = self.getImportESuperv()
403 return asterCEXECompo.substitute(component=self.name,
404 module=gen.module.name,
405 servicesdef="\n".join(defs),
406 servicesimpl="\n".join(services),
407 initservice='\n'.join(inits),
408 aster_dir=self.aster_dir,
409 importesuperv=importesuperv,
413 if self.kind == "cexe":
414 return "CEXE", self.name+".exe"
418 def makeaster(self, gen):
419 """library component: generate SALOME component source"""
423 for serv in self.services:
424 defs.append(serv.defs)
427 for name, typ in serv.inport:
428 if typ=="file":continue #files are not passed through service interface
431 datas.append('"%s":cPickle.loads(%s)' % (name, name))
433 datas.append('"%s":%s' % (name, name))
434 #ajout de l'adresse du composant
435 datas.append('"component":self.proxy.ptr()')
436 dvars = "{"+','.join(datas)+"}"
437 inparams = ",".join(params)
441 for name, typ in serv.outport:
444 datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
446 datas.append('j.g_context["%s"]'%name)
447 outparams = ",".join(params)
448 rvars = ",".join(datas)
450 service = asterService.substitute(component=self.name, service=serv.name,
451 inparams=inparams, outparams=outparams,
453 dvars=dvars, rvars=rvars)
455 for name, typ, dep in serv.instream:
456 streams.append(' calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
457 instream = "\n".join(streams)
459 for name, typ, dep in serv.outstream:
460 streams.append(' calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
461 outstream = "\n".join(streams)
463 init = pyinitService.substitute(component=self.name, service=serv.name,
464 instream=instream, outstream=outstream)
465 services.append(service)
468 python_path = ",".join([repr(p) for p in self.python_path])
469 argv = ",".join([repr(p) for p in self.argv])
470 return asterCompo.substitute(component=self.name, module=gen.module.name,
471 servicesdef="\n".join(defs),
472 servicesimpl="\n".join(services),
473 initservice='\n'.join(inits),
474 aster_dir=self.aster_dir,
475 python_path=python_path, argv=argv)