Salome HOME
Copyright update 2021
[modules/yacs.git] / src / py2yacs / py2yacs.py
index f5f01ce3d384a764e6d293f661dc72f4a4efba86..8bf41d4a5df8a0a9e90f0d6f98d314c2ecc8babf 100644 (file)
@@ -1,9 +1,6 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 *-
-# Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
-#
-# Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+# Copyright (C) 2007-2021  CEA/DEN, 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
@@ -39,11 +36,9 @@ class FunctionProperties:
     result+= "  Imports:"+ str(self.imports) + "\n"
     return result
 
-class v(ast.NodeVisitor):
+class VisitAST(ast.NodeVisitor):
   def visit_Module(self, node):
-    #print(type(node).__name__, ":")
-    accepted_tokens = ["Import", "ImportFrom", "FunctionDef", "ClassDef"]
-    #print "module body:"
+    accepted_tokens = ["Import", "ImportFrom", "FunctionDef", "ClassDef", "If"]
     self.global_errors=[]
     for e in node.body:
       type_name = type(e).__name__
@@ -51,8 +46,6 @@ class v(ast.NodeVisitor):
         error="py2yacs error at line %s: not accepted statement '%s'." % (
                e.lineno, type_name)
         self.global_errors.append(error)
-      #print(type_name)
-    #print("------------------------------------------------------------------")
     self.functions=[]
     self.lastfn=""
     self.infunc=False
@@ -60,7 +53,6 @@ class v(ast.NodeVisitor):
     self.generic_visit(node)
     pass
   def visit_FunctionDef(self, node):
-    #print(type(node).__name__, ":", node.name)
     if not self.infunc:
       self.lastfn = FunctionProperties(node.name)
       self.functions.append(self.lastfn)
@@ -72,11 +64,9 @@ class v(ast.NodeVisitor):
       self.infunc=False
     pass
   def visit_arg(self, node):
-    #print(type(node).__name__, ":", node.arg)
     self.lastfn.inputs.append(node.arg)
     pass
   def visit_Return(self, node):
-    #print(type(node).__name__, ":", node.value)
     if self.lastfn.outputs is not None :
       error="py2yacs error at line %s: multiple returns." % node.lineno
       self.lastfn.errors.append(error)
@@ -119,36 +109,89 @@ class v(ast.NodeVisitor):
 
 class vtest(ast.NodeVisitor):
   def generic_visit(self, node):
-    #print type(node).__name__
     ast.NodeVisitor.generic_visit(self, node)
 
 def create_yacs_schema(text, fn_name, fn_args, fn_returns, file_name):
   import pilot
   import SALOMERuntime
-  #import loader
   SALOMERuntime.RuntimeSALOME_setRuntime()
   runtime = pilot.getRuntime()
   schema = runtime.createProc("schema")
-  node = runtime.createFuncNode("", "default_name")
+  node = runtime.createScriptNode("", "default_name")
   schema.edAddChild(node)
   fncall = "\n%s=%s(%s)\n"%(",".join(fn_returns),
                             fn_name,
                             ",".join(fn_args))
   node.setScript(text+fncall)
-  node.setFname(fn_name)
   td=schema.getTypeCode("double")
   for p in fn_args:
-    node.edAddInputPort(p, td)
+    newport = node.edAddInputPort(p, td)
+    newport.edInit(0.0)
   for p in fn_returns:
     node.edAddOutputPort(p, td)
+  myContainer=schema.createContainer("Py2YacsContainer")
+  node.setExecutionMode(pilot.InlineNode.REMOTE_STR)
+  node.setContainer(myContainer)
   schema.saveSchema(file_name)
 
 def get_properties(text_file):
-  bt=ast.parse(text_file)
-  w=v()
+  try:
+    bt=ast.parse(text_file)
+  except SyntaxError as err:
+    import traceback
+    return [], ["".join(traceback.format_exception_only(SyntaxError,err))]
+  w=VisitAST()
   w.visit(bt)
   return w.functions, w.global_errors
 
+def function_properties(python_path, fn_name):
+  """
+  python_path : path to a python file
+  fn_name : name of a function in the file
+  return : properties of the function. see class FunctionProperties
+  """
+  with open(python_path, 'r') as f:
+    text_file = f.read()
+  functions,errors = get_properties(text_file)
+  result = [fn for fn in functions if fn.name == fn_name]
+  if len(result) < 1:
+    raise Exception("Function not found: {}".format(fn_name))
+  result = result[0]
+  error_string = ""
+  if len(errors) > 0:
+    error_string += "Global errors in file {}\n".format(python_path)
+    error_string += '\n'.join(errors)
+    raise Exception(error_string)
+  if len(result.errors) > 0:
+    error_string += "Errors when parsing function {}\n".format(fn_name)
+    error_string += '\n'.join(result.errors)
+    raise Exception(error_string)
+  return result
+
+
+def main(python_path, yacs_path, function_name="_exec"):
+  with open(python_path, 'r') as f:
+    text_file = f.read()
+  fn_name = function_name
+  functions,errors = get_properties(text_file)
+  error_string = ""
+  if len(errors) > 0:
+    error_string += "global errors:\n"
+    error_string += '\n'.join(errors)
+    return error_string
+  fn_properties = next((f for f in functions if f.name == fn_name), None)
+  if fn_properties is not None :
+    if not fn_properties.errors :
+      create_yacs_schema(text_file, fn_name,
+                         fn_properties.inputs, fn_properties.outputs,
+                         yacs_path)
+    else:
+      error_string += '\n'.join(fn_properties.errors)
+  else:
+    error_string += "Function not found:"
+    error_string += fn_name
+  return error_string
+
 if __name__ == '__main__':
   import argparse
   parser = argparse.ArgumentParser(description="Generate a YACS schema from a python file containing a function to run.")
@@ -160,29 +203,10 @@ if __name__ == '__main__':
         help='Name of the function to call in the yacs node (_exec by default)',
         default='_exec')
   args = parser.parse_args()
-  with open(args.file, 'r') as f:
-    text_file = f.read()
-  #bt=ast.parse(text_file)
-  #w=vtest()
-  #w=v()
-  #w.visit(bt)
-  #print "global errors:", w.global_errors
-  #for f in w.functions:
-  #  print f
-  
-  fn_name = args.def_name
-  functions,errors = get_properties(text_file)
-  print("global errors:", errors)
-  for f in functions:
-    print(f)
-  
-  fn_properties = next((f for f in functions if f.name == fn_name), None)
-  if fn_properties is not None :
-    if not fn_properties.errors :
-      create_yacs_schema(text_file, fn_name,
-                       fn_properties.inputs, fn_properties.outputs,
-                       args.output)
-    else:
-      print("\n".join(fn_properties.errors))
+  erreurs = main(args.file, args.output, args.def_name)
+  import sys
+  if len(erreurs) > 0:
+    print(erreurs)
+    sys.exit(1)
   else:
-    print("Function not found:", fn_name)
+    sys.exit(0)