]> SALOME platform Git repositories - tools/yacsgen.git/blob - module_generator/astcompo.py
Salome HOME
Generate an empty config.txt file.
[tools/yacsgen.git] / module_generator / astcompo.py
1 # Copyright (C) 2009-2014  EDF R&D
2 #
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.
7 #
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.
12 #
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
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 """
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')
26 """
27 import re, os, sys
28
29 from gener import Component, Invalid, makedirs
30
31 from pyth_tmpl import pyinitEXEService, pyinitCEXEService, pyinitService
32 import aster_tmpl
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
38
39 class ASTERComponent(Component):
40   """
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*.
43
44    :param name: gives the name of the component.
45    :type name: str
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
55       kind is "lib".
56
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::
59
60       >>> c1 = module_generator.ASTERComponent('mycompo', services=[s1,], kind="exe",
61                                                           exe_path="launch.sh",
62                                                           argv=["-memjeveux","4"])
63   """
64   def __init__(self, name, services=None, libs="", rlibs="", aster_dir="",
65                      python_path=None, argv=None, kind="lib", exe_path=None, aster_version_type="stable"):
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)
74
75   def validate(self):
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)
80
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" :
87       if not self.exe_path:
88         raise Invalid("exe_path must be defined for component %s" % self.name)
89     if self.kind == "exe" :
90       if not self.exe_path:
91         raise Invalid("exe_path must be defined for component %s" % self.name)
92
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:
96       found=False
97       for port_name,port_type in serv.inport:
98         if port_name == "jdc":
99           found=True
100           break
101       if not found:
102         serv.inport.insert(0, ("jdc", "string"))
103
104   def libraryName(self):
105     """ Name of the target library
106         No library for an aster component
107     """
108     return ""
109     
110   def getAsterPythonPath(self):
111     """Directory of aster python modules
112     """
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")
115
116     if not os.path.exists(aster_python_path) :
117       aster_python_path = os.path.join(self.aster_dir, "bibpyt")
118       
119     return aster_python_path
120
121   def makeCompo(self, gen):
122     """drive the generation of SALOME module files and code files
123        depending on the choosen component kind
124     """
125     filename = "%s.py" % self.name
126     #on suppose que les composants ASTER sont homogenes (utilisent meme install)
127     gen.aster = self.aster_dir
128
129     if self.kind == "lib":
130       f = self.name+".py"
131       return {"CMakeLists.txt":cmake_src_compo_aster_lib.substitute(sources=f),
132               filename:self.makeaster(gen)}
133     elif self.kind == "cexe":
134       fdict=self.makecexepath(gen)
135       sources = self.name + ".py\n  " + self.name + "_container.py"
136       d= {"CMakeLists.txt":cmake_src_compo_aster.substitute(
137                                             sources=sources,
138                                             module=gen.module.name,
139                                             resources=self.name+"_config.txt",
140                                             scripts=self.name+".exe"),
141            self.name+".exe":cexe.substitute(compoexe=self.exe_path),
142            filename:self.makecexeaster(gen)
143          }
144       d.update(fdict)
145       return d
146     elif self.kind == "exe":
147       fdict=self.makeexepath(gen)
148       sources =  self.name + "_module.py\n  "
149       sources =  sources + self.name + "_component.py"
150       d= {"CMakeLists.txt":cmake_src_compo_aster.substitute(
151                                             sources=sources,
152                                             module=gen.module.name,
153                                             resources=self.name+"_config.txt",
154                                             scripts=self.name+".exe"),
155            self.name+".exe":exeaster.substitute(compoexe=self.exe_path),
156            self.name+"_module.py":self.makeexeaster(gen)
157          }
158       d.update(fdict)
159       return d
160
161   def makeexepath(self, gen):
162     """standalone component: generate files for calculation code"""
163
164     fdict={}
165     fdict["%s_config.txt" % self.name] = "# a completer"
166     fdict["%s_component.py" % self.name] = component.substitute(component=self.name)
167
168     return fdict
169
170   def makecexepath(self, gen):
171     """specific container: generate files"""
172
173     fdict={}
174     fdict["%s_container.py" % self.name] = container
175     return fdict
176
177   def getImportESuperv(self):
178     importesuperv="""
179 VERS="%s"
180 import os.path as osp
181 from asrun.run import AsRunFactory
182 from asrun.config import AsterConfig
183
184 run = AsRunFactory()
185 path = run.get_version_path(VERS)
186 cfg = AsterConfig(osp.join(path, 'config.txt'))
187 pypath = cfg['REPPY'][0]
188
189 sys.path.insert(0, pypath)
190 from Execution.E_SUPERV import SUPERV
191 """ % self.aster_version_type
192     return importesuperv
193
194
195   def makeexeaster(self, gen):
196     """standalone component: generate SALOME component source"""
197     services = []
198     inits = []
199     defs = []
200     for serv in self.services:
201       defs.append(serv.defs)
202       params = []
203       datas = []
204       for name, typ in serv.inport:
205         if typ=="file":continue #files are not passed through service interface
206         params.append(name)
207         if typ == "pyobj":
208           datas.append('"%s":cPickle.loads(%s)' % (name, name))
209         else:
210           datas.append('"%s":%s' % (name, name))
211       #ajout de l'adresse du composant
212       datas.append('"component":self.proxy.ptr()')
213       dvars = "{"+','.join(datas)+"}"
214       inparams = ",".join(params)
215
216       params = []
217       datas = []
218       for name, typ in serv.outport:
219         if typ=="file":continue #files are not passed through service interface
220         params.append(name)
221         if typ == "pyobj":
222           datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
223         else:
224           datas.append('j.g_context["%s"]'%name)
225       outparams = ",".join(params)
226       rvars = ",".join(datas)
227
228       service = asterEXEService.substitute(component=self.name,
229                                            service=serv.name,
230                                            inparams=inparams,
231                                            outparams=outparams,
232                                            body=serv.body,
233                                            dvars=dvars, rvars=rvars)
234       streams = []
235       for name, typ, dep in serv.instream:
236         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
237       instream = "\n".join(streams)
238       streams = []
239       for name, typ, dep in serv.outstream:
240         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
241       outstream = "\n".join(streams)
242
243       init = pyinitEXEService.substitute(component=self.name, service=serv.name,
244                                          instream=instream, outstream=outstream)
245       services.append(service)
246       inits.append(init)
247
248     importesuperv = self.getImportESuperv()
249
250     return asterEXECompo.substitute(component=self.name, module=gen.module.name,
251                                     servicesdef="\n".join(defs),
252                                     servicesimpl="\n".join(services),
253                                     initservice='\n'.join(inits),
254                                     aster_dir=self.aster_dir,
255                                     importesuperv=importesuperv,
256                                     )
257
258   def makecexeaster(self, gen):
259     """specific container: generate SALOME component source"""
260     services = []
261     inits = []
262     defs = []
263     for serv in self.services:
264       defs.append(serv.defs)
265       params = []
266       datas = []
267       for name, typ in serv.inport:
268         if typ=="file":continue #files are not passed through service interface
269         params.append(name)
270         if typ == "pyobj":
271           datas.append('"%s":cPickle.loads(%s)' % (name, name))
272         else:
273           datas.append('"%s":%s' % (name, name))
274       #ajout de l'adresse du composant
275       datas.append('"component":self.proxy.ptr()')
276       dvars = "{"+','.join(datas)+"}"
277       inparams = ",".join(params)
278
279       params = []
280       datas = []
281       for name, typ in serv.outport:
282         params.append(name)
283         if typ == "pyobj":
284           datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
285         else:
286           datas.append('j.g_context["%s"]'%name)
287       outparams = ",".join(params)
288       rvars = ",".join(datas)
289
290       service = asterCEXEService.substitute(component=self.name,
291                                             service=serv.name,
292                                             inparams=inparams,
293                                             outparams=outparams,
294                                             body=serv.body,
295                                             dvars=dvars, rvars=rvars)
296       streams = []
297       for name, typ, dep in serv.instream:
298         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
299       instream = "\n".join(streams)
300       streams = []
301       for name, typ, dep in serv.outstream:
302         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
303       outstream = "\n".join(streams)
304
305       init = pyinitCEXEService.substitute(component=self.name, 
306                                           service=serv.name,
307                                           instream=instream, 
308                                           outstream=outstream)
309       services.append(service)
310       inits.append(init)
311
312     importesuperv = self.getImportESuperv()
313
314     return asterCEXECompo.substitute(component=self.name, 
315                                      module=gen.module.name,
316                                      servicesdef="\n".join(defs), 
317                                      servicesimpl="\n".join(services), 
318                                      initservice='\n'.join(inits),
319                                      aster_dir=self.aster_dir,
320                                      importesuperv=importesuperv,
321                                      )
322
323   def getImpl(self):
324     if self.kind == "cexe":
325       return "CEXE", self.name+".exe"
326     else:
327       return "SO", ""
328
329   def makeaster(self, gen):
330     """library component: generate SALOME component source"""
331     services = []
332     inits = []
333     defs = []
334     for serv in self.services:
335       defs.append(serv.defs)
336       params = []
337       datas = []
338       for name, typ in serv.inport:
339         if typ=="file":continue #files are not passed through service interface
340         params.append(name)
341         if typ == "pyobj":
342           datas.append('"%s":cPickle.loads(%s)' % (name, name))
343         else:
344           datas.append('"%s":%s' % (name, name))
345       #ajout de l'adresse du composant
346       datas.append('"component":self.proxy.ptr()')
347       dvars = "{"+','.join(datas)+"}"
348       inparams = ",".join(params)
349
350       params = []
351       datas = []
352       for name, typ in serv.outport:
353         params.append(name)
354         if typ == "pyobj":
355           datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
356         else:
357           datas.append('j.g_context["%s"]'%name)
358       outparams = ",".join(params)
359       rvars = ",".join(datas)
360
361       service = asterService.substitute(component=self.name, service=serv.name, 
362                                         inparams=inparams, outparams=outparams, 
363                                         body=serv.body, 
364                                         dvars=dvars, rvars=rvars)
365       streams = []
366       for name, typ, dep in serv.instream:
367         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
368       instream = "\n".join(streams)
369       streams = []
370       for name, typ, dep in serv.outstream:
371         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
372       outstream = "\n".join(streams)
373
374       init = pyinitService.substitute(component=self.name, service=serv.name,
375                                       instream=instream, outstream=outstream)
376       services.append(service)
377       inits.append(init)
378
379     python_path = ",".join([repr(p) for p in self.python_path])
380     argv = ",".join([repr(p) for p in self.argv])
381     return asterCompo.substitute(component=self.name, module=gen.module.name,
382                                  servicesdef="\n".join(defs), 
383                                  servicesimpl="\n".join(services), 
384                                  initservice='\n'.join(inits),
385                                  aster_dir=self.aster_dir, 
386                                  python_path=python_path, argv=argv)
387