to execute remote Python code.
Example from python interpreter:
import salome_pynode
code="""def f(x):
return 2*x
"""
node=container.createPyNode("mynode",code)
y=node.execute("f",10)
nstest.idl \
DSC_Engines.idl \
SALOME_Ports.idl \
+ SALOME_PyNode.idl \
Palm_Ports.idl \
SALOME_PACOExtension.idl \
SALOME_ParamPorts.idl
nstestSK.cc \
DSC_EnginesSK.cc \
SALOME_PortsSK.cc \
+ SALOME_PyNodeSK.cc \
Calcium_PortsSK.cc \
Palm_PortsSK.cc \
SALOME_PACOExtensionSK.cc \
SALOMEDSDynSK.cc SALOME_SessionDynSK.cc SALOME_RessourcesCatalogDynSK.cc \
DSC_EnginesDynSK.cc SALOME_ComponentDynSK.cc SALOME_GenericObjDynSK.cc \
Palm_PortsDynSK.cc SALOME_ExceptionDynSK.cc SALOMEDS_AttributesDynSK.cc \
- LoggerDynSK.cc SALOME_PACOExtensionDynSK.cc SALOME_ParamPortsDynSK.cc
+ LoggerDynSK.cc SALOME_PACOExtensionDynSK.cc SALOME_ParamPortsDynSK.cc SALOME_PyNodeDynSK.cc
MPIIDL_SOURCES = \
SALOME_MPIObjectSK.cc \
#include "SALOMEDS.idl"
#include "SALOME_Exception.idl"
+#include "SALOME_PyNode.idl"
/*! \file SALOME_Component.idl \brief interfaces for Component and Container
*/
\param localFile the local file to create by copy
*/
void copyFile(in Container contai, in string remoteFile, in string localFile);
+
+ //! Create a PyNode in the container
+ /*!
+ \param nodeName the name of the PyNode
+ \param code python code as text to load in the node
+ */
+ PyNode createPyNode(in string nodeName, in string code) raises(SALOME::SALOME_Exception);
};
/*! \brief Interface of the %component.
--- /dev/null
+// Copyright (C) 2007-2008 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
+//
+// 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.
+//
+// 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
+//
+// File : SALOME_PyNode.idl
+// Author : Christian CAREMOLI, EDF
+// $Header:
+//
+#ifndef _SALOME_PYNODE_IDL_
+#define _SALOME_PYNODE_IDL_
+
+#include "SALOME_GenericObj.idl"
+#include "SALOME_Exception.idl"
+
+/*! \file SALOME_PyNode.idl \brief interface for remote python execution
+*/
+
+/*! \brief
+This is a package of interfaces used for executing Python code on remote container
+*/
+module Engines
+{
+ typedef sequence<octet> pickledArgs;
+
+ interface PyNode : SALOME::GenericObj
+ {
+
+ /*! \brief execute a python function defined in the node
+
+ \param functionName the python function defined in the node to execute
+ \param inargs input argument values provided as a python pickle
+ \return output argument values as a python pickle
+ */
+ pickledArgs execute(in string functionName,in pickledArgs inargs) raises (SALOME::SALOME_Exception);
+
+ } ;
+
+};
+
+#endif
}
}
+/*! \brief create a PyNode object to execute remote python code
+ * \param nodeName the name of the node
+ * \param code the python code to load
+ * \return the PyNode
+ */
+Engines::PyNode_ptr Engines_Container_i::createPyNode(const char* nodeName, const char* code)
+{
+ Engines::PyNode_var node= Engines::PyNode::_nil();
+
+ PyGILState_STATE gstate = PyGILState_Ensure();
+ PyObject *res = PyObject_CallMethod(_pyCont,
+ (char*)"create_pynode",
+ (char*)"ss",
+ nodeName,
+ code);
+ if(res==NULL)
+ {
+ //internal error
+ PyErr_Print();
+ PyGILState_Release(gstate);
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = "can not create a python node";
+ throw SALOME::SALOME_Exception(es);
+ }
+ long ierr=PyInt_AsLong(PyTuple_GetItem(res,0));
+ PyObject* result=PyTuple_GetItem(res,1);
+ std::string astr=PyString_AsString(result);
+ Py_DECREF(res);
+ PyGILState_Release(gstate);
+
+ if(ierr==0)
+ {
+ CORBA::Object_var obj = _orb->string_to_object(astr.c_str());
+ node = Engines::PyNode::_narrow(obj);
+ return node._retn();
+ }
+ else
+ {
+ SALOME::ExceptionStruct es;
+ es.type = SALOME::INTERNAL_ERROR;
+ es.text = astr.c_str();
+ throw SALOME::SALOME_Exception(es);
+ }
+
+}
# Scripts to be installed
dist_salomescript_PYTHON =\
SALOME_ComponentPy.py \
+ SALOME_PyNode.py \
SALOME_Container.py
# These files are executable scripts
import os
import sys
import string
+import traceback
from omniORB import CORBA, PortableServer
import SALOMEDS
import Engines, Engines__POA
from SALOME_NamingServicePy import *
from SALOME_ComponentPy import *
+import SALOME_PyNode
from SALOME_utilities import *
from Utils_Identity import getShortHostName
return comp_iors
+ def create_pynode(self,nodeName,code):
+ try:
+ node=SALOME_PyNode.PyNode_i(nodeName,code,self._poa)
+ id_o = self._poa.activate_object(node)
+ comp_o = self._poa.id_to_reference(id_o)
+ comp_iors = self._orb.object_to_string(comp_o)
+ return 0,comp_iors
+ except:
+ exc_typ,exc_val,exc_fr=sys.exc_info()
+ l=traceback.format_exception(exc_typ,exc_val,exc_fr)
+ return 1,"".join(l)
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SALOME_Component)
+#include CORBA_SERVER_HEADER(SALOME_PyNode)
#include <iostream>
#include <signal.h>
virtual Engines::Salome_file_ptr createSalome_file(const char* origFileName);
void copyFile(Engines::Container_ptr container, const char* remoteFile, const char* localFile);
+ Engines::PyNode_ptr createPyNode(const char* nodeName, const char* code);
// --- local C++ methods
Engines::Component_ptr
--- /dev/null
+# Copyright (C) 2007-2008 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
+#
+# 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.
+#
+# 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
+#
+# File : SALOME_PyNode.py
+# Author : Christian CAREMOLI, EDF
+# Module : SALOME
+# $Header$
+#
+
+import sys,traceback,string
+import linecache
+import cPickle
+import Engines__POA
+import SALOME__POA
+import SALOME
+
+class Generic(SALOME__POA.GenericObj):
+ """A Python implementation of the GenericObj CORBA IDL"""
+ def __init__(self,poa):
+ self.poa=poa
+ self.cnt=1
+
+ def Register(self):
+ self.cnt+=1
+
+ def Destroy(self):
+ self.cnt-=1
+ if self.cnt <= 0:
+ oid=self.poa.servant_to_id(self)
+ self.poa.deactivate_object(oid)
+
+class PyNode_i (Engines__POA.PyNode,Generic):
+ """The implementation of the PyNode CORBA IDL"""
+ def __init__(self, nodeName,code,poa):
+ """Initialize the node : compilation in the local context"""
+ Generic.__init__(self,poa)
+ self.nodeName=nodeName
+ self.code=code
+ linecache.cache[nodeName]=0,None,string.split(code,'\n'),nodeName
+ ccode=compile(code,nodeName,'exec')
+ self.context={}
+ exec ccode in self.context
+
+ def execute(self,funcName,argsin):
+ """Execute the function funcName found in local context with pickled args (argsin)"""
+ try:
+ argsin,kws=cPickle.loads(argsin)
+ func=self.context[funcName]
+ argsout=func(*argsin,**kws)
+ argsout=cPickle.dumps(argsout,-1)
+ return argsout
+ except:
+ exc_typ,exc_val,exc_fr=sys.exc_info()
+ l=traceback.format_exception(exc_typ,exc_val,exc_fr)
+ raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.BAD_PARAM,"".join(l),"PyNode: %s, function: %s" % (self.nodeName,funcName),0))
+
iparameters.py \
salome_version.py \
salome_notebook.py \
+ salome_pynode.py \
salome_genericobj.py
endif
--- /dev/null
+# Copyright (C) 2007-2008 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
+#
+# 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.
+#
+# 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
+#
+# File : salome_pynode.py
+# Author : Christian CAREMOLI, EDF
+# Module : SALOME
+# $Header$
+#
+
+"""
+ When imported this module adds to CORBA proxy (from PyNode type) automatic pickle and unpickle
+ of arguments and results when calling execute method. It also converts the SALOME exception into a standard python
+ exception
+"""
+import omniORB
+import cPickle
+import SALOME
+import Engines
+
+class SmartPyNode(Engines._objref_PyNode):
+ def __init__(self):
+ Engines._objref_PyNode.__init__(self)
+
+ def execute(self,functionName,*args,**kws):
+ try:
+ args=cPickle.dumps((args,kws),-1)
+ results=Engines._objref_PyNode.execute(self,functionName,args)
+ x=cPickle.loads(results)
+ return x
+ except SALOME.SALOME_Exception, e:
+ raise ValueError(e.details.text)
+
+ def __getattr__(self,name):
+ """ a trick to be able to call directly a remote method by its name : no need to use execute"""
+ if name[0]== '_':
+ raise AttributeError, name
+ def afunc(*args,**kws):
+ return self.execute(name,*args,**kws)
+ return afunc
+
+#Register the new proxy for PyNode
+omniORB.registerObjref(Engines._objref_PyNode._NP_RepositoryId, SmartPyNode)
+