X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=module_generator%2Fastcompo.py;h=f0c6f257c50ce8322deb9191589065820c478a69;hb=8b4424caa9bc6abdcd519333a0acc9533e3d2a63;hp=181f3dbb864f2ce02b4ed5a4f6ca55c96aa0bfd2;hpb=b46d71e4c7d6a459cb2a62b6796fe45ccca630df;p=tools%2Fyacsgen.git diff --git a/module_generator/astcompo.py b/module_generator/astcompo.py index 181f3db..f0c6f25 100644 --- a/module_generator/astcompo.py +++ b/module_generator/astcompo.py @@ -1,129 +1,214 @@ -import re, os +# Copyright (C) 2009-2021 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# -from gener import Component, Invalid, makedirs +""" + This module defines the ASTERComponent class for ASTER component generation + An ASTER component comes in 3 flavors : + - implemented as a dynamic library (kind='lib') + - implemented as a standalone component (kind='exe') + - implemented as a specific container (kind='cexe') +""" +import re, os, sys -from pyth_tmpl import pyinitEXEService, pyinitCEXEService, pyinitService -from aster_tmpl import asterCEXEService, asterEXEService -from aster_tmpl import asterService, asterEXECompo, asterCEXECompo, asterCompo -from aster_tmpl import asterexeMakefile, astercexeMakefile, astercompoMakefile -from aster_tmpl import comm, make_etude, cexe, exeaster -from aster_tmpl import container, component +from module_generator.gener import Component, Invalid, makedirs + +from module_generator.pyth_tmpl import pyinitEXEService, pyinitCEXEService, pyinitService +from module_generator import aster_tmpl +from module_generator.aster_tmpl import asterCEXEService, asterEXEService +from module_generator.aster_tmpl import asterService, asterEXECompo, asterCEXECompo, asterCompo +from module_generator.aster_tmpl import comm, make_etude, cexe, exeaster +from module_generator.aster_tmpl import container, component +from module_generator.aster_tmpl import cmake_src_compo_aster, cmake_src_compo_aster_lib class ASTERComponent(Component): - def __init__(self, name, services=None, libs="", rlibs="", aster_dir="", - python_path=None, argv=None, kind="lib", exe_path=None, - asrun=None, export_extras=""): + """ + A :class:`ASTERComponent` instance represents an ASTER SALOME component (special component for Code_Aster that is a mix of + Fortran and Python code) with services given as a list of :class:`Service` instances with the parameter *services*. + + :param name: gives the name of the component. + :type name: str + :param services: the list of services (:class:`Service`) of the component. + :param kind: If it is given and has the value "exe", the component will be built as a standalone + component (executable or shell script). The default is to build the component as a dynamic library. + :param libs: gives all the libraries options to add when linking the generated component (-L...). + :param rlibs: gives all the runtime libraries options to add when linking the generated component (-R...). + :param exe_path: is only used when kind is "exe" and gives the path to the standalone component. + :param aster_dir: gives the Code_Aster installation directory. + :param python_path: If it is given (as a list of paths), all the paths are added to the python path (sys.path). + :param argv: is a list of strings that gives the command line parameters for Code_Aster. This parameter is only useful when + kind is "lib". + + For example, the following call defines a Code_Aster component named "mycompo" with one service s1 (it must have been defined before). + This standalone component takes some command line arguments:: + + >>> c1 = module_generator.ASTERComponent('mycompo', services=[s1,], kind="exe", + exe_path="launch.sh", + argv=["-memjeveux","4"]) + """ + def __init__(self, name, services=None, libs="", rlibs="", aster_dir="", + python_path=None, argv=None, kind="lib", exe_path=None, aster_version_type="stable"): + """initialise component attributes""" self.aster_dir = aster_dir self.python_path = python_path or [] self.argv = argv or [] self.exe_path = exe_path - self.asrun = asrun - self.export_extras = export_extras + self.aster_version_type = aster_version_type Component.__init__(self, name, services, impl="ASTER", libs=libs, rlibs=rlibs, kind=kind) def validate(self): + """validate the component definition""" Component.validate(self) if not self.aster_dir: raise Invalid("aster_dir must be defined for component %s" % self.name) kinds = ("lib", "cexe", "exe") if self.kind not in kinds: - raise Invalid("kind must be one of %s" % kinds) + raise Invalid("kind must be one of %s for component %s" % (kinds,self.name)) if self.kind == "lib" and not self.python_path: raise Invalid("python_path must be defined for component %s" % self.name) if self.kind == "cexe" : if not self.exe_path: raise Invalid("exe_path must be defined for component %s" % self.name) - if not self.asrun: - raise Invalid("asrun must be defined for component %s" % self.name) - if not os.path.exists(self.asrun): - raise Invalid("asrun does not exist for component %s" % self.name) if self.kind == "exe" : if not self.exe_path: raise Invalid("exe_path must be defined for component %s" % self.name) - if not self.asrun: - raise Invalid("asrun must be defined for component %s" % self.name) - if not os.path.exists(self.asrun): - raise Invalid("asrun does not exist for component %s" % self.name) + #Si un port de nom jdc n'est pas defini dans la liste des inports du service, + #on en ajoute un de type string en premiere position for serv in self.services: - #on ajoute un inport string de nom jdc en premier dans la liste des ports de chaque service - serv.inport.insert(0, ("jdc", "string")) + found=False + for port_name,port_type in serv.inport: + if port_name == "jdc": + found=True + break + if not found: + serv.inport.insert(0, ("jdc", "string")) + + def libraryName(self): + """ Name of the target library + No library for an aster component + """ + return "" + + def getAsterPythonPath(self): + """Directory of aster python modules + """ + python_version_dir = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) + aster_python_path = os.path.join(self.aster_dir, "lib", python_version_dir, "site-packages") + + if not os.path.exists(aster_python_path) : + aster_python_path = os.path.join(self.aster_dir, "bibpyt") + + return aster_python_path def makeCompo(self, gen): + """drive the generation of SALOME module files and code files + depending on the choosen component kind + """ filename = "%s.py" % self.name #on suppose que les composants ASTER sont homogenes (utilisent meme install) gen.aster = self.aster_dir + if self.kind == "lib": - return {"Makefile.am":astercompoMakefile.substitute(module=gen.module.name, - component=self.name), - filename:self.makeaster(gen)} + f = self.name+".py" + return {"CMakeLists.txt":cmake_src_compo_aster_lib.substitute(sources=f), + filename:self.makeaster(gen)} elif self.kind == "cexe": - #creation de l'installation aster dans exe_path - self.makecexepath(gen) - return {"Makefile.am":astercexeMakefile.substitute(module=gen.module.name, - component=self.name), - filename:self.makecexeaster(gen)} + fdict=self.makecexepath(gen) + sources = self.name + ".py\n " + self.name + "_container.py" + d= {"CMakeLists.txt":cmake_src_compo_aster.substitute( + sources=sources, + module=gen.module.name, + resources=self.name+"_config.txt", + scripts=self.name+".exe"), + self.name+".exe":cexe.substitute(compoexe=self.exe_path), + filename:self.makecexeaster(gen) + } + d.update(fdict) + return d elif self.kind == "exe": - #creation de l'installation aster dans exe_path - self.makeexepath(gen) - return {"Makefile.am":asterexeMakefile.substitute(module=gen.module.name, - component=self.name), - self.name+".exe":exeaster.substitute(export=os.path.join(self.exe_path, "make_etude.export"), asrun=self.asrun), - self.name+"_module.py":self.makeexeaster(gen)} + fdict=self.makeexepath(gen) + sources = self.name + "_module.py\n " + sources = sources + self.name + "_component.py" + d= {"CMakeLists.txt":cmake_src_compo_aster.substitute( + sources=sources, + module=gen.module.name, + resources=self.name+"_config.txt", + scripts=self.name+".exe"), + self.name+".exe":exeaster.substitute(compoexe=self.exe_path), + self.name+"_module.py":self.makeexeaster(gen) + } + d.update(fdict) + return d def makeexepath(self, gen): - makedirs(self.exe_path) - #patch to E_SUPERV.py - fil = open(os.path.join(self.aster_dir, "bibpyt", "Execution", "E_SUPERV.py")) - esuperv = fil.read() - esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv) - fil.close() - #utilisation d'un programme principal python different - fil = open(os.path.join(self.aster_dir, "config.txt")) - config = fil.read() - config = re.sub("Execution\/E_SUPERV.py", os.path.join(self.exe_path, "aster_component.py"), config) - fil.close() - - gen.makeFiles({ - "aster_component.py":component.substitute(component=self.name), - "make_etude.export":make_etude.substitute(config=os.path.join(self.exe_path, "config.txt"), - comm=os.path.join(self.exe_path, self.name+".comm"), - extras=self.export_extras), - self.name+".comm":comm, - "config.txt":config, - "profile.sh":os.path.join(self.aster_dir, "profile.sh"), - "E_SUPERV.py":esuperv, - }, self.exe_path) + """standalone component: generate files for calculation code""" + + fdict={} + #use a specific main program (modification of config.txt file) + config = "" + path_config = os.path.join(self.aster_dir, "config.txt") + if os.path.exists(path_config) : + fil = open(path_config) + config = fil.read() + fil.close() +# config = re.sub(" profile.sh", os.path.join(self.aster_dir, "profile.sh"), config) +# path=os.path.join(os.path.abspath(gen.module.prefix),'lib', +# 'python%s.%s' % (sys.version_info[0], sys.version_info[1]), +# 'site-packages','salome','%s_component.py'%self.name) +# config = re.sub("Execution\/E_SUPERV.py", path, config) + else : + config = "# a completer:%s n'existe pas" % path_config + + fdict["%s_config.txt" % self.name] = config + fdict["%s_component.py" % self.name] = component.substitute(component=self.name) + + return fdict def makecexepath(self, gen): - makedirs(self.exe_path) - #patch to E_SUPERV.py - fil = open(os.path.join(self.aster_dir, "bibpyt", "Execution", "E_SUPERV.py")) - esuperv = fil.read() - esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv) - fil.close() - #utilisation d'un programme principal python different - fil = open(os.path.join(self.aster_dir, "config.txt")) - config = fil.read() - config = re.sub("Execution\/E_SUPERV.py", os.path.join(self.exe_path, "aster_container.py"), config) - fil.close() - gen.makeFiles({self.name+".exe":cexe.substitute(export=os.path.join(self.exe_path, "make_etude.export"), - asrun=self.asrun), - "aster_container.py":container, - "make_etude.export":make_etude.substitute(config=os.path.join(self.exe_path, "config.txt"), - comm=os.path.join(self.exe_path, self.name+".comm"), - extras=self.export_extras), - self.name+".comm":comm, - "config.txt":config, - "profile.sh":os.path.join(self.aster_dir, "profile.sh"), - "E_SUPERV.py":esuperv, - }, self.exe_path) - #make exe executable - os.chmod(os.path.join(self.exe_path, self.name+".exe"), 0777) + """specific container: generate files""" + + fdict={} + fdict["%s_container.py" % self.name] = container + return fdict + + def getImportESuperv(self): + importesuperv=""" +VERS="%s" +import os.path as osp +from asrun.run import AsRunFactory +from asrun.config import AsterConfig + +run = AsRunFactory() +path = run.get_version_path(VERS) +cfg = AsterConfig(osp.join(path, 'config.txt')) +pypath = cfg['REPPY'][0] + +sys.path.insert(0, pypath) +from Execution.E_SUPERV import SUPERV +""" % self.aster_version_type + return importesuperv + def makeexeaster(self, gen): + """standalone component: generate SALOME component source""" services = [] inits = [] defs = [] @@ -132,9 +217,10 @@ class ASTERComponent(Component): params = [] datas = [] for name, typ in serv.inport: + if typ=="file":continue #files are not passed through service interface params.append(name) if typ == "pyobj": - datas.append('"%s":cPickle.loads(%s)' % (name, name)) + datas.append('"%s":pickle.loads(%s)' % (name, name)) else: datas.append('"%s":%s' % (name, name)) #ajout de l'adresse du composant @@ -145,19 +231,20 @@ class ASTERComponent(Component): params = [] datas = [] for name, typ in serv.outport: + if typ=="file":continue #files are not passed through service interface params.append(name) if typ == "pyobj": - datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name) + datas.append('pickle.dumps(j.g_context["%s"],-1)'%name) else: datas.append('j.g_context["%s"]'%name) outparams = ",".join(params) rvars = ",".join(datas) - service = asterEXEService.substitute(component=self.name, - service=serv.name, + service = asterEXEService.substitute(component=self.name, + service=serv.name, inparams=inparams, - outparams=outparams, - body=serv.body, + outparams=outparams, + body=serv.body, dvars=dvars, rvars=rvars) streams = [] for name, typ, dep in serv.instream: @@ -172,13 +259,19 @@ class ASTERComponent(Component): instream=instream, outstream=outstream) services.append(service) inits.append(init) + + importesuperv = self.getImportESuperv() + return asterEXECompo.substitute(component=self.name, module=gen.module.name, - servicesdef="\n".join(defs), - servicesimpl="\n".join(services), + servicesdef="\n".join(defs), + servicesimpl="\n".join(services), initservice='\n'.join(inits), - aster_dir=self.aster_dir) + aster_dir=self.aster_dir, + importesuperv=importesuperv, + ) def makecexeaster(self, gen): + """specific container: generate SALOME component source""" services = [] inits = [] defs = [] @@ -187,9 +280,10 @@ class ASTERComponent(Component): params = [] datas = [] for name, typ in serv.inport: + if typ=="file":continue #files are not passed through service interface params.append(name) if typ == "pyobj": - datas.append('"%s":cPickle.loads(%s)' % (name, name)) + datas.append('"%s":pickle.loads(%s)' % (name, name)) else: datas.append('"%s":%s' % (name, name)) #ajout de l'adresse du composant @@ -202,17 +296,17 @@ class ASTERComponent(Component): for name, typ in serv.outport: params.append(name) if typ == "pyobj": - datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name) + datas.append('pickle.dumps(j.g_context["%s"],-1)'%name) else: datas.append('j.g_context["%s"]'%name) outparams = ",".join(params) rvars = ",".join(datas) - service = asterCEXEService.substitute(component=self.name, - service=serv.name, + service = asterCEXEService.substitute(component=self.name, + service=serv.name, inparams=inparams, - outparams=outparams, - body=serv.body, + outparams=outparams, + body=serv.body, dvars=dvars, rvars=rvars) streams = [] for name, typ, dep in serv.instream: @@ -229,19 +323,26 @@ class ASTERComponent(Component): outstream=outstream) services.append(service) inits.append(init) + + importesuperv = self.getImportESuperv() + return asterCEXECompo.substitute(component=self.name, module=gen.module.name, servicesdef="\n".join(defs), servicesimpl="\n".join(services), initservice='\n'.join(inits), - aster_dir=self.aster_dir) + aster_dir=self.aster_dir, + importesuperv=importesuperv, + ) + def getImpl(self): if self.kind == "cexe": - return "CEXE", os.path.join(self.exe_path, self.name+".exe") + return "CEXE", self.name+".exe" else: return "SO", "" def makeaster(self, gen): + """library component: generate SALOME component source""" services = [] inits = [] defs = [] @@ -250,9 +351,10 @@ class ASTERComponent(Component): params = [] datas = [] for name, typ in serv.inport: + if typ=="file":continue #files are not passed through service interface params.append(name) if typ == "pyobj": - datas.append('"%s":cPickle.loads(%s)' % (name, name)) + datas.append('"%s":pickle.loads(%s)' % (name, name)) else: datas.append('"%s":%s' % (name, name)) #ajout de l'adresse du composant @@ -265,7 +367,7 @@ class ASTERComponent(Component): for name, typ in serv.outport: params.append(name) if typ == "pyobj": - datas.append('cPickle.dumps(j.g_context["%s"],-1)'%name) + datas.append('pickle.dumps(j.g_context["%s"],-1)'%name) else: datas.append('j.g_context["%s"]'%name) outparams = ",".join(params)