]> SALOME platform Git repositories - tools/yacsgen.git/commitdiff
Salome HOME
CCAR: add data type file
authorcaremoli <caremoli>
Mon, 23 Nov 2009 17:18:55 +0000 (17:18 +0000)
committercaremoli <caremoli>
Mon, 23 Nov 2009 17:18:55 +0000 (17:18 +0000)
      automatic indent for python body
      change standalone component and specific container for component ASTER to be less intrusive
      fix some small bugs

module_generator/astcompo.py
module_generator/aster_tmpl.py
module_generator/cppcompo.py
module_generator/fcompo.py
module_generator/gener.py
module_generator/pacocompo.py
module_generator/pycompo.py

index 181f3dbb864f2ce02b4ed5a4f6ca55c96aa0bfd2..466b83e373bcc4c3aa6dac3a8a4fe4caba3c5ead 100644 (file)
@@ -1,4 +1,11 @@
-import re, os
+"""
+  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 gener import Component, Invalid, makedirs
 
@@ -13,6 +20,7 @@ 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=""):
+    """initialise component attributes"""
     self.aster_dir = aster_dir
     self.python_path = python_path or []
     self.argv = argv or []
@@ -23,107 +31,126 @@ class ASTERComponent(Component):
                              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 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, 
+      return {"Makefile.am":astercompoMakefile.substitute(module=gen.module.name,
                                                           component=self.name),
              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)
+      d= {"Makefile.am":astercexeMakefile.substitute(module=gen.module.name,
+                                                     component=self.name),
+           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, 
+      fdict=self.makeexepath(gen)
+      d= {"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)}
+           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)
+    """standalone component: generate files for calculation code"""
     #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
+    esuperv = re.sub("def Execute\(self\)", "def Execute(self, params)", esuperv)
+    esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv)
+    esuperv = re.sub("\*\*args", "context_ini=params, **args", esuperv)
+    esuperv = re.sub("def main\(self\)", "def main(self,params={})", esuperv)
+    esuperv = re.sub("return self.Execute\(\)", "return self.Execute(params)", esuperv)
+    #use a specific main program (modification of config.txt file)
     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()
+    config = re.sub("profile.sh", os.path.join(self.aster_dir, "profile.sh"), config)
 
-    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)
+    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)
+
+    fdict= {
+             "%s_component.py"%self.name:component.substitute(component=self.name),
+             "%s_config.txt" % self.name:config,
+             "E_SUPERV.py":esuperv,
+           }
+    return fdict
 
   def makecexepath(self, gen):
-    makedirs(self.exe_path)
+    """specific container: generate files"""
     #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
+    esuperv = re.sub("def Execute\(self\)", "def Execute(self, params)", esuperv)
+    esuperv = re.sub("j=self.JdC", "self.jdc=j=self.JdC", esuperv)
+    esuperv = re.sub("\*\*args", "context_ini=params, **args", esuperv)
+    esuperv = re.sub("def main\(self\)", "def main(self,params={})", esuperv)
+    esuperv = re.sub("return self.Execute\(\)", "return self.Execute(params)", esuperv)
+
+    #use a specific main program
     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)
+    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_container.py' % self.name)
+    config = re.sub("Execution\/E_SUPERV.py", path, config)
+
+    fdict= {
+             "%s_container.py" % self.name:container,
+             "%s_config.txt" % self.name:config,
+             "E_SUPERV.py":esuperv,
+           }
+    return fdict
 
   def makeexeaster(self, gen):
+    """standalone component: generate SALOME component source"""
     services = []
     inits = []
     defs = []
@@ -132,6 +159,7 @@ 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))
@@ -145,6 +173,7 @@ 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)
@@ -179,6 +208,7 @@ class ASTERComponent(Component):
                                     aster_dir=self.aster_dir)
 
   def makecexeaster(self, gen):
+    """specific container: generate SALOME component source"""
     services = []
     inits = []
     defs = []
@@ -187,6 +217,7 @@ 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))
@@ -237,11 +268,12 @@ class ASTERComponent(Component):
                                      aster_dir=self.aster_dir)
   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,6 +282,7 @@ 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))
index 1c493ccf3e8087448a3627f8487347058332beb0..c427a60bb8766010d41b5a1397d6b01a6048d776 100644 (file)
@@ -9,12 +9,20 @@ salomepython_PYTHON = ${component}.py
 
 """
 astercompoMakefile=Template(astercompoMakefile)
-astercexeMakefile=astercompoMakefile
+
+astercexeMakefile="""include $$(top_srcdir)/adm_local/make_common_starter.am
+salomepython_PYTHON = ${component}.py ${component}_container.py E_SUPERV.py
+# These files are executable scripts
+dist_salomescript_SCRIPTS= ${component}.exe
+salomeres_DATA = ${component}_config.txt
+"""
+astercexeMakefile=Template(astercexeMakefile)
 
 asterexeMakefile="""include $$(top_srcdir)/adm_local/make_common_starter.am
-salomepython_PYTHON = ${component}_module.py
+salomepython_PYTHON = ${component}_module.py ${component}_component.py E_SUPERV.py
 # These files are executable scripts
 dist_salomescript_SCRIPTS= ${component}.exe
+salomeres_DATA = ${component}_config.txt
 """
 asterexeMakefile=Template(asterexeMakefile)
 
@@ -90,6 +98,9 @@ except:
 ${servicesdef}
 #ENDDEF
 
+class ExecutionError(Exception):
+  '''General exception during execution'''
+
 class ${component}(${module}__POA.${component},dsccalcium.PyDSCComponent,SUPERV):
   '''
      To be identified as a SALOME component this Python class
@@ -105,6 +116,19 @@ class ${component}(${module}__POA.${component},dsccalcium.PyDSCComponent,SUPERV)
 ${initservice}
     return False
 
+  def interpstring(self,text,args):
+    try:
+      self.jdc.g_context.update(args)
+      CONTEXT.set_current_step(self.jdc)
+      linecache.cache['<string>']=0,None,string.split(text,'\\n'),'<string>'
+      exec text in self.jdc.const_context,self.jdc.g_context
+      CONTEXT.unset_current_step()
+    except EOFError:
+      CONTEXT.unset_current_step()
+    except:
+      CONTEXT.unset_current_step()
+      raise
+
 ${servicesimpl}
 """
 
@@ -228,27 +252,34 @@ asterService=Template(asterService)
 asterCEXEService="""
   def ${service}(self,${inparams}):
     self.beginService("${component}.${service}")
-    if not self.init:
-      self.init=1
-      ier=self.main()
-    j=self.jdc
-    self.jdc.g_context.update(${dvars})
     try:
-      CONTEXT.set_current_step(self.jdc)
-      linecache.cache['<string>']=0,0,string.split(jdc,'\\n'),'<string>'
-      exec jdc in self.jdc.g_context
-      CONTEXT.unset_current_step()
-      self.endService("${component}.${service}")
-    except EOFError:
+      args=${dvars}
+      if not args.has_key("jdc"):
+        fcomm=open("jdc",'r')
+        jdc=fcomm.read()
+        fcomm.close()
+        #args["jdc"]=jdc
+      if not self.init:
+        self.init=1
+        fcomm=open("fort.1",'w')
+        fcomm.write(jdc)
+        fcomm.close()
+        ier=self.main(args)
+        if ier != 0:
+          raise ExecutionError("Error in initial execution")
+      else:
+        self.interpstring(jdc,args)
+
       self.endService("${component}.${service}")
+      j=self.jdc
+      return ${rvars}
     except:
-      sys.stdout.flush()
       exc_typ,exc_val,exc_fr=sys.exc_info()
       l=traceback.format_exception(exc_typ,exc_val,exc_fr)
       self.endService("${component}.${service}")
-      CONTEXT.unset_current_step()
+      sys.stdout.flush()
+      sys.stderr.flush()
       raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.BAD_PARAM,"".join(l),"${component}.py",0))
-    return ${rvars}
 """
 asterCEXEService=Template(asterCEXEService)
 asterEXEService=asterCEXEService
@@ -333,14 +364,7 @@ cexe="""#!/bin/sh
 
 export SALOME_CONTAINERNAME=$$1
 
-cp ${export} temp.export
-cat >> temp.export << END
-F mess $$PWD/messages R 6
-F resu $$PWD/resu R 8
-F erre $$PWD/erre R 9
-END
-
-${asrun} temp.export
+${compoexe}
 """
 cexe=Template(cexe)
 
@@ -350,14 +374,7 @@ export SALOME_CONTAINER=$$1
 export SALOME_CONTAINERNAME=$$2
 export SALOME_INSTANCE=$$3
 
-cp ${export} temp.export
-cat >> temp.export << END
-F mess $$PWD/messages R 6
-F resu $$PWD/resu R 8
-F erre $$PWD/erre R 9
-END
-
-${asrun} temp.export
+${compoexe}
 """
 exeaster=Template(exeaster)
 
index a0b36d592607d234de020023243f3b68b942a777..195e2b43eadacb3abd4b31f9e4a6a7ba0c5aeb9f 100644 (file)
@@ -20,7 +20,7 @@ class CPPComponent(Component):
     Component.validate(self)
     kinds = ("lib", "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 == "exe" :
       if not self.exe_path:
index 02b8d1153f28268691d4a835c4fc36745322eb1d..bb484ebb89492266a30cfa8643a329084bc3eb66 100644 (file)
@@ -18,17 +18,20 @@ class F77Component(CPPComponent):
     self.impl = "F77"
 
   def makebody(self):
+    """generate definitions (defs attribute of services) et bodys (body attribute of services)"""
     for serv in self.services:
       #defs generation
       params = ["void *compo"]
       strparams = []
       for name, typ in serv.inport:
+        if typ == "file":continue #files are not passed through service interface
         if typ == "string":
           params.append("const STR_PSTR(%s)"%name)
           strparams.append("STR_PLEN(%s)"%name)
         else:
           params.append("%s %s" % (f77Types[typ], name))
       for name, typ in serv.outport:
+        if typ == "file":continue #files are not passed through service interface
         if typ == "string":
           params.append("const STR_PSTR(%s)"%name)
           strparams.append("STR_PLEN(%s)"%name)
@@ -44,12 +47,14 @@ class F77Component(CPPComponent):
       #length allocated for out string
       lstr = 20
       for name, typ in serv.inport:
+        if typ == "file":continue #files are not passed through service interface
         if typ == "string":
           params.append("STR_CPTR(%s)" % name)
           strparams.append("STR_CLEN(%s)"%name)
         else:
           params.append("&%s" % name)
       for name, typ in serv.outport:
+        if typ == "file":continue #files are not passed through service interface
         if typ == "string":
           params.append("STR_CPTR(%s.ptr())" % name)
           strparams.append("STR_CLEN(%s.ptr())"%name)
@@ -61,5 +66,9 @@ class F77Component(CPPComponent):
       serv.body = serv.body+"\n   F_CALL(%s,%s)(%s);" % (serv.name.lower(), serv.name.upper(), args)
 
   def makeCompo(self, gen):
+    """build a dictionary that defines component files
+       dictionary key = file name
+       dictionary value = file content or dictionary defining subdirectory content
+    """
     self.makebody()
     return CPPComponent.makeCompo(self, gen)
index aae9af4c9986a0b166ea8dcee2cc36be852d4b7f..59640f425ae23c35cd5eef33c515dfda3a202f47 100644 (file)
@@ -1,4 +1,5 @@
 import os, shutil, glob, socket
+import traceback
 
 try:
   from string import Template
@@ -8,6 +9,8 @@ except:
 class Invalid(Exception):
   pass
 
+debug=0
+
 from mod_tmpl import resMakefile, makecommon, configure, paco_configure
 from mod_tmpl import mainMakefile, autogen, application
 from cata_tmpl import catalog, interface, idl, idlMakefile, parallel_interface
@@ -23,13 +26,13 @@ from aster_tmpl import check_aster
 corbaTypes = {"double":"CORBA::Double", "long":"CORBA::Long",
               "string":"const char*", "dblevec":"const %s::dblevec&",
               "stringvec":"const %s::stringvec&", "intvec":"const %s::intvec&",
-              "dataref":"const Engines::dataref&",
+              "dataref":"const Engines::dataref&","file":None
              }
 
 corbaOutTypes = {"double":"CORBA::Double&", "long":"CORBA::Long&",
                  "string":"CORBA::String_out", "dblevec":"%s::dblevec_out",
                  "stringvec":"%s::stringvec_out", "intvec":"%s::intvec_out",
-                 "dataref":"Engines::dataref_out",
+                 "dataref":"Engines::dataref_out","file":None
                 }
 
 def corba_in_type(typ, module):
@@ -76,7 +79,13 @@ class Module(object):
     self.name = name
     self.components = components or []
     self.prefix = prefix or "%s_INSTALL" % name
-    self.validate()
+    try:
+      self.validate()
+    except Invalid,e:
+      if debug:
+        traceback.print_exc()
+      print "Error in module %s: %s" % (name,e)
+      raise SystemExit
 
   def validate(self):
     lcompo = set()
@@ -221,6 +230,7 @@ class Generator(object):
     self.aster = ""
 
   def generate(self):
+    """generate SALOME module as described by module attribute"""
     module = self.module
     namedir = module.name+"_SRC"
     force = self.context.get("force")
@@ -306,14 +316,18 @@ class Generator(object):
     return
 
   def makeArgs(self, service):
+    """generate source service for arguments"""
     params = []
     for name, typ in service.inport:
+      if typ=="file":continue #files are not passed through service interface
       params.append("%s %s" % (corba_in_type(typ, self.module.name), name))
     for name, typ in service.outport:
+      if typ=="file":continue #files are not passed through service interface
       params.append("%s %s" % (corba_out_type(typ, self.module.name), name))
     return ",".join(params)
 
   def makeCatalog(self):
+    """generate SALOME components catalog source"""
     components = []
     for compo in self.module.components:
       services = []
@@ -344,6 +358,7 @@ class Generator(object):
     return catalog.substitute(components='\n'.join(components))
 
   def makeidl(self):
+    """generate module IDL file source (CORBA interface)"""
     from pacocompo import PACOComponent
     interfaces = []
     for compo in self.module.components:
@@ -352,22 +367,26 @@ class Generator(object):
         for serv in compo.services:
           params = []
           for name, typ in serv.inport:
+            if typ == "file":continue #files are not passed through IDL interface
             params.append("in %s %s" % (typ, name))
           for name, typ in serv.outport:
+            if typ == "file":continue #files are not passed through IDL interface
             params.append("out %s %s" % (typ, name))
           service = "    void %s(" % serv.name
           service = service+",".join(params)+");"
           services.append(service)
         interfaces.append(parallel_interface.substitute(component=compo.name, services="\n".join(services)))
-      else: 
+      else:
         services = []
         for serv in compo.services:
           params = []
           for name, typ in serv.inport:
+            if typ == "file":continue #files are not passed through IDL interface
             if compo.impl in ("PY", "ASTER") and typ == "pyobj":
               typ = "Engines::fileBlock"
             params.append("in %s %s" % (typ, name))
           for name, typ in serv.outport:
+            if typ == "file":continue #files are not passed through IDL interface
             if compo.impl in ("PY", "ASTER") and typ == "pyobj":
               typ = "Engines::fileBlock"
             params.append("out %s %s" % (typ, name))
@@ -392,6 +411,10 @@ class Generator(object):
     return xml.substitute(module=self.module.name, interfaces='\n'.join(interfaces))
 
   def makeFiles(self, dic, basedir):
+    """create files and directories defined in dictionary dic in basedir directory
+       dic key = file name to create
+       dic value = file content or dictionary defining the content of a sub directory
+    """
     for name, content in dic.items():
       filename = os.path.join(basedir, name)
       if isinstance(content, str):
@@ -404,11 +427,13 @@ class Generator(object):
         self.makeFiles(content, filename)
 
   def bootstrap(self):
+    """execute module autogen.sh script: execution of libtool, autoconf, automake"""
     ier = os.system("cd %s_SRC;sh autogen.sh" % self.module.name)
     if ier != 0:
       raise Invalid("bootstrap has ended in error")
 
   def configure(self):
+    """execute module configure script with installation prefix (prefix attribute of module)"""
     prefix = self.module.prefix
     paco = self.context.get("paco")
     mpi = self.context.get("mpi")
@@ -439,6 +464,7 @@ class Generator(object):
       raise Invalid("configure has ended in error")
 
   def make(self):
+    """execute module Makefile : make"""
     make_command = "make "
     if self.makeflags:
       make_command += self.makeflags
@@ -447,11 +473,13 @@ class Generator(object):
       raise Invalid("make has ended in error")
 
   def install(self):
+    """install module: make install """
     ier = os.system("cd %s_SRC;make install" % self.module.name)
     if ier != 0:
       raise Invalid("install has ended in error")
 
   def make_appli(self, appliname, restrict=None, altmodules=None):
+    """generate SALOME application"""
     makedirs(appliname)
 
     rootdir, kerdir = os.path.split(self.kernel)
index 3435f08a4f0bdc8c776b90b2e7a748ec34c8102a..f455bf7bf9dd00a517a229892aed4252be7e47bc 100644 (file)
@@ -44,7 +44,7 @@ class PACOComponent(Component):
     Component.validate(self)
     kinds = ("lib")
     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))
     parallel_libs = ("dummy", "mpi")
     if self.parallel_lib not in parallel_libs:
       raise Invalid("parallel_lib must be one of %s" % parallel_libs)
index f542e619a0713df04328a400cae4d4a4dc41306f..0abf5d4df5caf504639080239b3c9ac7eb579074 100644 (file)
@@ -5,21 +5,36 @@ import os
 from gener import Component, Invalid
 from pyth_tmpl import pyinitService, pyService, pyCompoEXE, pyCompo
 from pyth_tmpl import pycompoEXEMakefile, pycompoMakefile
+import textwrap
+from string import split,rstrip,join
+
+def indent(text, prefix='    '):
+  """Indent text by prepending a given prefix to each line."""
+  if not text: return ''
+  lines = split(text, '\n')
+  lines = map(lambda line, prefix=prefix: prefix + line, lines)
+  if lines: lines[-1] = rstrip(lines[-1])
+  return join(lines, '\n')
 
 class PYComponent(Component):
   def __init__(self, name, services=None, python_path=None, kind="lib",
                      sources=None):
+    """initialise component attributes"""
     self.python_path = python_path or []
     Component.__init__(self, name, services, impl="PY", kind=kind,
                              sources=sources)
 
   def validate(self):
+    """validate component attributes"""
     Component.validate(self)
     kinds = ("lib","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))
 
   def makeCompo(self, gen):
+    """generate component sources as a dictionary containing 
+       file names (key) and file content (values)
+    """
     pyfile = "%s.py" % self.name
     sources = " ".join(map(os.path.basename,self.sources))
     if self.kind == "lib":
@@ -36,6 +51,7 @@ class PYComponent(Component):
              }
 
   def makepy(self, gen):
+    """generate standard SALOME component source (python module)"""
     services = []
     inits = []
     defs = []
@@ -44,6 +60,7 @@ class PYComponent(Component):
       params = []
       pyparams = []
       for name, typ in serv.inport:
+        if typ=="file":continue #files are not passed through service interface
         params.append(name)
         if typ == "pyobj":
           pyparams.append("      %s=cPickle.loads(%s)" %(name, name))
@@ -53,13 +70,18 @@ class PYComponent(Component):
       params = []
       pyparams = []
       for name, typ in serv.outport:
+        if typ=="file":continue #files are not passed through service interface
         params.append(name)
         if typ == "pyobj":
           pyparams.append("      %s=cPickle.dumps(%s,-1)" %(name, name))
       outparams = ",".join(params)
       convertoutparams = '\n'.join(pyparams)
+      #dedent and indent the body
+      body=textwrap.dedent(serv.body)
+      body=indent(body,' '*6)
+
       service = pyService.substitute(component=self.name, service=serv.name, inparams=inparams,
-                                     outparams=outparams, body=serv.body, 
+                                     outparams=outparams, body= body,
                                      convertinparams=convertinparams,
                                      convertoutparams=convertoutparams)
       streams = []
@@ -83,6 +105,7 @@ class PYComponent(Component):
                               python_path=python_path)
 
   def makepyexe(self, gen):
+    """generate standalone component source (python executable)"""
     services = []
     inits = []
     defs = []
@@ -91,6 +114,7 @@ class PYComponent(Component):
       params = []
       pyparams = []
       for name, typ in serv.inport:
+        if typ=="file":continue #files are not passed through service interface
         params.append(name)
         if typ == "pyobj":
           pyparams.append("      %s=cPickle.loads(%s)" %(name, name))
@@ -100,14 +124,18 @@ class PYComponent(Component):
       params = []
       pyparams = []
       for name, typ in serv.outport:
+        if typ=="file":continue #files are not passed through service interface
         params.append(name)
         if typ == "pyobj":
           pyparams.append("      %s=cPickle.dumps(%s,-1)" %(name, name))
       outparams = ",".join(params)
       convertoutparams = '\n'.join(pyparams)
-      service = pyService.substitute(component=self.name, service=serv.name, 
-                                     inparams=inparams, outparams=outparams, 
-                                     body=serv.body, 
+      #dedent and indent the body
+      body=textwrap.dedent(serv.body)
+      body=indent(body,' '*6)
+      service = pyService.substitute(component=self.name, service=serv.name,
+                                     inparams=inparams, outparams=outparams,
+                                     body=body,
                                      convertinparams=convertinparams,
                                      convertoutparams=convertoutparams,
                                     )