]> SALOME platform Git repositories - tools/yacsgen.git/blob - module_generator/astcompo.py
Salome HOME
Remove file config.txt and remove compatibility with older ASTER versions.
[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
38 class ASTERComponent(Component):
39   """
40    A :class:`ASTERComponent` instance represents an ASTER SALOME component (special component for Code_Aster that is a mix of
41    Fortran and Python code) with services given as a list of :class:`Service` instances with the parameter *services*.
42
43    :param name: gives the name of the component.
44    :type name: str
45    :param services: the list of services (:class:`Service`) of the component.
46    :param kind: If it is given and has the value "exe", the component will be built as a standalone
47       component (executable or shell script). The default is to build the component as a dynamic library.
48    :param libs: gives all the libraries options to add when linking the generated component (-L...).
49    :param rlibs: gives all the runtime libraries options to add when linking the generated component (-R...).
50    :param exe_path: is only used when kind is "exe" and gives the path to the standalone component.
51    :param aster_dir: gives the Code_Aster installation directory.
52    :param python_path: If it is given (as a list of paths), all the paths are added to the python path (sys.path).
53    :param argv: is a list of strings that gives the command line parameters for Code_Aster. This parameter is only useful when
54       kind is "lib".
55
56    For example, the following call defines a Code_Aster component named "mycompo" with one service s1 (it must have been defined before).
57    This standalone component takes some command line arguments::
58
59       >>> c1 = module_generator.ASTERComponent('mycompo', services=[s1,], kind="exe",
60                                                           exe_path="launch.sh",
61                                                           argv=["-memjeveux","4"])
62   """
63   def __init__(self, name, services=None, libs="", rlibs="", aster_dir="", 
64                      python_path=None, argv=None, kind="lib", exe_path=None, aster_version_type="stable"):
65     """initialise component attributes"""
66     self.aster_dir = aster_dir
67     self.python_path = python_path or []
68     self.argv = argv or []
69     self.exe_path = exe_path
70     self.aster_version_type = aster_version_type
71     Component.__init__(self, name, services, impl="ASTER", libs=libs, 
72                              rlibs=rlibs, kind=kind)
73
74   def validate(self):
75     """validate the component definition"""
76     Component.validate(self)
77     if not self.aster_dir:
78       raise Invalid("aster_dir must be defined for component %s" % self.name)
79
80     kinds = ("lib", "cexe", "exe")
81     if self.kind not in kinds:
82       raise Invalid("kind must be one of %s for component %s" % (kinds,self.name))
83     if self.kind == "lib" and not self.python_path:
84       raise Invalid("python_path must be defined for component %s" % self.name)
85     if self.kind == "cexe" :
86       if not self.exe_path:
87         raise Invalid("exe_path must be defined for component %s" % self.name)
88     if self.kind == "exe" :
89       if not self.exe_path:
90         raise Invalid("exe_path must be defined for component %s" % self.name)
91
92     #Si un port de nom jdc n'est pas defini dans la liste des inports du service,
93     #on en ajoute un de type string en premiere position
94     for serv in self.services:
95       found=False
96       for port_name,port_type in serv.inport:
97         if port_name == "jdc":
98           found=True
99           break
100       if not found:
101         serv.inport.insert(0, ("jdc", "string"))
102
103   def getAsterPythonPath(self):
104     """Directory of aster python modules
105     """
106     python_version_dir = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
107     aster_python_path = os.path.join(self.aster_dir, "lib", python_version_dir, "site-packages")
108
109     if not os.path.exists(aster_python_path) :
110       aster_python_path = os.path.join(self.aster_dir, "bibpyt")
111       
112     return aster_python_path
113
114 #  def getConfig(self, gen):
115 #    """Content of the config.txt file
116 #    """
117 #    path_compo=os.path.join(os.path.abspath(gen.module.prefix),'lib',
118 #                      'python%s.%s' % (sys.version_info[0], sys.version_info[1]),
119 #                      'site-packages','salome','%s_component.py'%self.name)
120 #    conf="""ENV_SH         | env     | -     | $ASTER_VERSION_DIR/share/aster/profile.sh
121 #BINELE         | bin     | -     | $ASTER_VERSION_DIR/share/aster/elements
122 #SRCPY          | src     | -     | %s
123 #ARGPYT         | exec    | -     | %s
124 #""" % (self.getAsterPythonPath(), path_compo)
125 #    
126 #    return conf
127
128   def makeCompo(self, gen):
129     """drive the generation of SALOME module files and code files
130        depending on the choosen component kind
131     """
132     filename = "%s.py" % self.name
133     #on suppose que les composants ASTER sont homogenes (utilisent meme install)
134     gen.aster = self.aster_dir
135
136     #get ASTER version
137 #    f = os.path.join(self.aster_dir, self.getAsterPythonPath(), 'Accas', 'properties.py')
138 #    self.version=(0,0,0)
139 #    if os.path.isfile(f):
140 #      mydict = {}
141 #      execfile(f, mydict)
142 #      v,r,p = mydict['version'].split('.')
143 #      self.version=(int(v),int(r),int(p))
144
145     if self.kind == "lib":
146       return {"Makefile.am":gen.makeMakefile(self.getMakefileItems(gen)),
147               filename:self.makeaster(gen)}
148     elif self.kind == "cexe":
149       fdict=self.makecexepath(gen)
150       d= {"Makefile.am":gen.makeMakefile(self.getMakefileItems(gen)),
151            self.name+".exe":cexe.substitute(compoexe=self.exe_path),
152            filename:self.makecexeaster(gen)
153          }
154       d.update(fdict)
155       return d
156     elif self.kind == "exe":
157       fdict=self.makeexepath(gen)
158       d= {"Makefile.am":gen.makeMakefile(self.getMakefileItems(gen)),
159            self.name+".exe":exeaster.substitute(compoexe=self.exe_path),
160            self.name+"_module.py":self.makeexeaster(gen)
161          }
162       d.update(fdict)
163       return d
164
165   def getMakefileItems(self,gen):
166     makefileItems={"header":"include $(top_srcdir)/adm_local/make_common_starter.am"}
167     if self.kind == "lib":
168       makefileItems["salomepython_PYTHON"]=[self.name+".py"]
169     elif self.kind == "exe":
170       makefileItems["salomepython_PYTHON"]=[self.name+"_module.py",self.name+"_component.py"]
171 #      if self.version < (10,1,2):
172 #        makefileItems["salomepython_PYTHON"].append("E_SUPERV.py")
173       makefileItems["dist_salomescript_SCRIPTS"]=[self.name+".exe"]
174 #      makefileItems["salomeres_DATA"]=[self.name+"_config.txt"]
175     elif self.kind == "cexe":
176       makefileItems["salomepython_PYTHON"]=[self.name+".py",self.name+"_container.py"]
177 #      if self.version < (10,1,2):
178 #        makefileItems["salomepython_PYTHON"].append("E_SUPERV.py")
179       makefileItems["dist_salomescript_SCRIPTS"]=[self.name+".exe"]
180 #      makefileItems["salomeres_DATA"]=[self.name+"_config.txt"]
181     return makefileItems
182
183
184   def makeexepath(self, gen):
185     """standalone component: generate files for calculation code"""
186
187     fdict={}
188
189 #    if self.version < (10,1,2):
190       #patch to E_SUPERV.py
191 #      fil = open(os.path.join(self.aster_dir, "bibpyt", "Execution", "E_SUPERV.py"))
192 #      esuperv = fil.read()
193 #      fil.close()
194 #      esuperv = re.sub("def Execute\(self\)", "def Execute(self, params)", esuperv)
195 #      esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv)
196 #      esuperv = re.sub("\*\*args", "context_ini=params, **args", esuperv)
197 #      esuperv = re.sub("def main\(self\)", "def main(self,params={})", esuperv)
198 #      esuperv = re.sub("return self.Execute\(\)", "return self.Execute(params)", esuperv)
199 #      fdict["E_SUPERV.py"]=esuperv
200
201     #use a specific main program (modification of config.txt file)
202 #    config = ""
203 #    path_config = os.path.join(self.aster_dir, "config.txt")
204 #    if os.path.exists(path_config) :
205       # old aster version - old mechanism kept for compatibility
206 #      fil = open(path_config)
207 #      config = fil.read()
208 #      fil.close()
209 #      config = re.sub(" profile.sh", os.path.join(self.aster_dir, "profile.sh"), config)
210 #      path=os.path.join(os.path.abspath(gen.module.prefix),'lib',
211 #                      'python%s.%s' % (sys.version_info[0], sys.version_info[1]),
212 #                      'site-packages','salome','%s_component.py'%self.name)
213 #      config = re.sub("Execution\/E_SUPERV.py", path, config)
214 #    else :
215       # getConfig doesn't work with older versions of aster
216 #      config = self.getConfig(gen)
217
218 #    fdict["%s_config.txt" % self.name] = config
219     fdict["%s_component.py" % self.name] = component.substitute(component=self.name)
220
221     return fdict
222
223   def makecexepath(self, gen):
224     """specific container: generate files"""
225
226     fdict={}
227
228 #    if self.version < (10,1,2):
229       #patch to E_SUPERV.py
230 #      fil = open(os.path.join(self.aster_dir, "bibpyt", "Execution", "E_SUPERV.py"))
231 #      esuperv = fil.read()
232 #      fil.close()
233 #      esuperv = re.sub("def Execute\(self\)", "def Execute(self, params)", esuperv)
234 #      esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv)
235 #      esuperv = re.sub("\*\*args", "context_ini=params, **args", esuperv)
236 #      esuperv = re.sub("def main\(self\)", "def main(self,params={})", esuperv)
237 #      esuperv = re.sub("return self.Execute\(\)", "return self.Execute(params)", esuperv)
238 #      fdict["E_SUPERV.py"]=esuperv
239
240     #use a specific main program
241 #    config = ""
242 #    path_config = os.path.join(self.aster_dir, "config.txt")
243 #    if os.path.exists(path_config) :
244       # old aster version - old mechanism kept for compatibility
245 #      fil = open(path_config)
246 #      config = fil.read()
247 #      fil.close()
248 #      config = re.sub(" profile.sh", os.path.join(self.aster_dir, "profile.sh"), config)
249 #      path=os.path.join(os.path.abspath(gen.module.prefix),'lib',
250 #                      'python%s.%s' % (sys.version_info[0], sys.version_info[1]),
251 #                      'site-packages','salome','%s_container.py' % self.name)
252 #      config = re.sub("Execution\/E_SUPERV.py", path, config)
253 #    else :
254       # getConfig doesn't work with older versions of aster
255 #      config = self.getConfig(gen)
256
257     fdict["%s_container.py" % self.name] = container
258 #    fdict["%s_config.txt" % self.name] = config
259
260     return fdict
261
262   def getImportESuperv(self):
263     importesuperv="""
264 VERS="%s"
265 import os.path as osp
266 from asrun.run import AsRunFactory
267 from asrun.config import AsterConfig
268
269 run = AsRunFactory()
270 path = run.get_version_path(VERS)
271 cfg = AsterConfig(osp.join(path, 'config.txt'))
272 pypath = cfg['REPPY'][0]
273
274 sys.path.insert(0, pypath)
275 from Execution.E_SUPERV import SUPERV
276 """ % self.aster_version_type
277     return importesuperv
278
279
280   def makeexeaster(self, gen):
281     """standalone component: generate SALOME component source"""
282     services = []
283     inits = []
284     defs = []
285     for serv in self.services:
286       defs.append(serv.defs)
287       params = []
288       datas = []
289       for name, typ in serv.inport:
290         if typ=="file":continue #files are not passed through service interface
291         params.append(name)
292         if typ == "pyobj":
293           datas.append('"%s":cPickle.loads(%s)' % (name, name))
294         else:
295           datas.append('"%s":%s' % (name, name))
296       #ajout de l'adresse du composant
297       datas.append('"component":self.proxy.ptr()')
298       dvars = "{"+','.join(datas)+"}"
299       inparams = ",".join(params)
300
301       params = []
302       datas = []
303       for name, typ in serv.outport:
304         if typ=="file":continue #files are not passed through service interface
305         params.append(name)
306         if typ == "pyobj":
307           datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
308         else:
309           datas.append('j.g_context["%s"]'%name)
310       outparams = ",".join(params)
311       rvars = ",".join(datas)
312
313       service = asterEXEService.substitute(component=self.name,
314                                            service=serv.name,
315                                            inparams=inparams,
316                                            outparams=outparams,
317                                            body=serv.body,
318                                            dvars=dvars, rvars=rvars)
319       streams = []
320       for name, typ, dep in serv.instream:
321         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
322       instream = "\n".join(streams)
323       streams = []
324       for name, typ, dep in serv.outstream:
325         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
326       outstream = "\n".join(streams)
327
328       init = pyinitEXEService.substitute(component=self.name, service=serv.name,
329                                          instream=instream, outstream=outstream)
330       services.append(service)
331       inits.append(init)
332
333     importesuperv = self.getImportESuperv()
334
335     return asterEXECompo.substitute(component=self.name, module=gen.module.name,
336                                     servicesdef="\n".join(defs),
337                                     servicesimpl="\n".join(services),
338                                     initservice='\n'.join(inits),
339                                     aster_dir=self.aster_dir,
340                                     importesuperv=importesuperv,
341                                     )
342
343   def makecexeaster(self, gen):
344     """specific container: generate SALOME component source"""
345     services = []
346     inits = []
347     defs = []
348     for serv in self.services:
349       defs.append(serv.defs)
350       params = []
351       datas = []
352       for name, typ in serv.inport:
353         if typ=="file":continue #files are not passed through service interface
354         params.append(name)
355         if typ == "pyobj":
356           datas.append('"%s":cPickle.loads(%s)' % (name, name))
357         else:
358           datas.append('"%s":%s' % (name, name))
359       #ajout de l'adresse du composant
360       datas.append('"component":self.proxy.ptr()')
361       dvars = "{"+','.join(datas)+"}"
362       inparams = ",".join(params)
363
364       params = []
365       datas = []
366       for name, typ in serv.outport:
367         params.append(name)
368         if typ == "pyobj":
369           datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
370         else:
371           datas.append('j.g_context["%s"]'%name)
372       outparams = ",".join(params)
373       rvars = ",".join(datas)
374
375       service = asterCEXEService.substitute(component=self.name,
376                                             service=serv.name,
377                                             inparams=inparams,
378                                             outparams=outparams,
379                                             body=serv.body,
380                                             dvars=dvars, rvars=rvars)
381       streams = []
382       for name, typ, dep in serv.instream:
383         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
384       instream = "\n".join(streams)
385       streams = []
386       for name, typ, dep in serv.outstream:
387         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
388       outstream = "\n".join(streams)
389
390       init = pyinitCEXEService.substitute(component=self.name, 
391                                           service=serv.name,
392                                           instream=instream, 
393                                           outstream=outstream)
394       services.append(service)
395       inits.append(init)
396
397     importesuperv = self.getImportESuperv()
398
399     return asterCEXECompo.substitute(component=self.name, 
400                                      module=gen.module.name,
401                                      servicesdef="\n".join(defs), 
402                                      servicesimpl="\n".join(services), 
403                                      initservice='\n'.join(inits),
404                                      aster_dir=self.aster_dir,
405                                      importesuperv=importesuperv,
406                                      )
407
408   def getImpl(self):
409     if self.kind == "cexe":
410       return "CEXE", self.name+".exe"
411     else:
412       return "SO", ""
413
414   def makeaster(self, gen):
415     """library component: generate SALOME component source"""
416     services = []
417     inits = []
418     defs = []
419     for serv in self.services:
420       defs.append(serv.defs)
421       params = []
422       datas = []
423       for name, typ in serv.inport:
424         if typ=="file":continue #files are not passed through service interface
425         params.append(name)
426         if typ == "pyobj":
427           datas.append('"%s":cPickle.loads(%s)' % (name, name))
428         else:
429           datas.append('"%s":%s' % (name, name))
430       #ajout de l'adresse du composant
431       datas.append('"component":self.proxy.ptr()')
432       dvars = "{"+','.join(datas)+"}"
433       inparams = ",".join(params)
434
435       params = []
436       datas = []
437       for name, typ in serv.outport:
438         params.append(name)
439         if typ == "pyobj":
440           datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name)
441         else:
442           datas.append('j.g_context["%s"]'%name)
443       outparams = ",".join(params)
444       rvars = ",".join(datas)
445
446       service = asterService.substitute(component=self.name, service=serv.name, 
447                                         inparams=inparams, outparams=outparams, 
448                                         body=serv.body, 
449                                         dvars=dvars, rvars=rvars)
450       streams = []
451       for name, typ, dep in serv.instream:
452         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","IN","%s")'% (name, typ, dep))
453       instream = "\n".join(streams)
454       streams = []
455       for name, typ, dep in serv.outstream:
456         streams.append('       calcium.create_calcium_port(self.proxy,"%s","%s","OUT","%s")'% (name, typ, dep))
457       outstream = "\n".join(streams)
458
459       init = pyinitService.substitute(component=self.name, service=serv.name,
460                                       instream=instream, outstream=outstream)
461       services.append(service)
462       inits.append(init)
463
464     python_path = ",".join([repr(p) for p in self.python_path])
465     argv = ",".join([repr(p) for p in self.argv])
466     return asterCompo.substitute(component=self.name, module=gen.module.name,
467                                  servicesdef="\n".join(defs), 
468                                  servicesimpl="\n".join(services), 
469                                  initservice='\n'.join(inits),
470                                  aster_dir=self.aster_dir, 
471                                  python_path=python_path, argv=argv)
472