Salome HOME
[EDF27816] : fix all non regression tests
[modules/yacs.git] / src / runtime / SalomePythonNode.cxx
1 // Copyright (C) 2006-2022  CEA/DEN, 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 #include "RuntimeSALOME.hxx"
21 #include "SalomePythonComponent.hxx"
22 #include "SalomePythonNode.hxx"
23 #include "PythonNode.hxx"
24 #include "PythonPorts.hxx"
25 #include "CORBANode.hxx"
26 #include "TypeCode.hxx"
27
28 #include <iostream>
29 #include <sstream>
30
31 using namespace YACS::ENGINE;
32 using namespace std;
33
34 const char SalomePythonNode::PLACEMENT_VAR_NAME_IN_INTERP[]="__container__from__YACS__";
35
36 SalomePythonNode::SalomePythonNode(const SalomePythonNode& other, ComposedNode *father):ServiceInlineNode(other,father),_pyfunc(0),_context(0)
37 {
38   //Not a bug : just because port point of view this is like PythonNode.
39   _implementation = PythonNode::IMPL_NAME;
40   PyGILState_STATE gstate = PyGILState_Ensure();
41   _context=PyDict_New();
42   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
43     {
44       stringstream msg;
45       msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
46       PyGILState_Release(gstate);
47       throw Exception(msg.str());
48     }
49   PyGILState_Release(gstate);
50 }
51
52 SalomePythonNode::SalomePythonNode(const std::string& name): ServiceInlineNode(name),_pyfunc(0)
53 {
54
55   //Not a bug : just because port point of view this is like PythonNode.
56   _implementation = PythonNode::IMPL_NAME;
57   PyGILState_STATE gstate = PyGILState_Ensure();
58   _context=PyDict_New();
59   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
60     {
61       stringstream msg;
62       msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
63       PyGILState_Release(gstate);
64       throw Exception(msg.str());
65     }
66   PyGILState_Release(gstate);
67 }
68
69 void SalomePythonNode::load()
70 {
71   ServiceInlineNode::load();
72   cerr << "---------------SalomePythonNode::load function---------------" << endl;
73   list<OutputPort *>::iterator iter;
74   string value2Export=((SalomePythonComponent*)_component)->getStringValueToExportInInterp(this);
75   PyObject* ob=PyBytes_FromString(value2Export.c_str());
76   PyDict_SetItemString(_context,PLACEMENT_VAR_NAME_IN_INTERP,ob);
77   for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
78     {
79       OutputPyPort *p=(OutputPyPort *)*iter;
80       cerr << "port name: " << p->getName() << endl;
81       cerr << "port kind: " << p->edGetType()->kind() << endl;
82     }
83   cerr <<  _script << endl;
84   PyGILState_STATE gstate = PyGILState_Ensure();
85   PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context);
86   if(res == NULL)
87     {
88       PyErr_Print();
89       PyGILState_Release(gstate);
90       throw Exception("Error during execution");
91       return;
92     }
93   Py_DECREF(res);
94   _pyfunc=PyDict_GetItemString(_context,_method.c_str());
95   if(_pyfunc == NULL)
96     {
97       PyErr_Print();
98       PyGILState_Release(gstate);
99       throw Exception("Error during execution");
100     }
101   cerr << "---------------End SalomePythonNode::load function---------------" << endl;
102   PyGILState_Release(gstate);
103 }
104
105 void SalomePythonNode::execute()
106 {
107   cerr << "++++++++++++++ SalomePythonNode::execute: " << getName() << " ++++++++++++++++++++" << endl;
108   int pos=0;
109   PyObject* ob;
110   if(!_pyfunc)throw Exception("SalomePythonNode badly loaded");
111   PyGILState_STATE gstate = PyGILState_Ensure();
112   
113   cerr << "---------------SalomePythonNode::inputs---------------" << endl;
114   PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
115   list<InputPort *>::iterator iter2;
116   for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
117     {
118       InputPyPort *p=(InputPyPort *)*iter2;
119       cerr << "port name: " << p->getName() << endl;
120       cerr << "port kind: " << p->edGetType()->kind() << endl;
121       ob=p->getPyObj();
122       PyObject_Print(ob,stderr,Py_PRINT_RAW);
123       cerr << endl;
124       cerr << "ob refcnt: " << ob->ob_refcnt << endl;
125       Py_INCREF(ob);
126       PyTuple_SetItem(args,pos,ob);
127       cerr << "ob refcnt: " << ob->ob_refcnt << endl;
128       pos++;
129     }
130   cerr << "---------------End SalomePythonNode::inputs---------------" << endl;
131
132   cerr << "----------------SalomePythonNode::calculation---------------" << endl;
133   PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
134   cerr << endl;
135   PyObject_Print(args,stderr,Py_PRINT_RAW);
136   cerr << endl;
137   PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
138   Py_DECREF(args);
139   if(result == NULL)
140     {
141       PyErr_Print();
142       PyGILState_Release(gstate);
143       throw Exception("Error during execution");
144     }
145   cerr << "----------------End SalomePythonNode::calculation---------------" << endl;
146
147   cerr << "-----------------SalomePythonNode::outputs-----------------" << endl;
148   int nres=1;
149   if(result == Py_None)
150     nres=0;
151   else if(PyTuple_Check(result))
152     nres=PyTuple_Size(result);
153
154   if(getNumberOfOutputPorts() != nres)
155     {
156       Py_DECREF(result);
157       PyGILState_Release(gstate);
158       throw Exception("Number of output arguments : Mismatch between definition and execution");
159     }
160
161   pos=0;
162   PyObject_Print(result,stderr,Py_PRINT_RAW);
163   cerr << endl;
164   list<OutputPort *>::iterator iter;
165   try
166     {
167       for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
168         {
169           OutputPyPort *p=(OutputPyPort *)*iter;
170           cerr << "port name: " << p->getName() << endl;
171           cerr << "port kind: " << p->edGetType()->kind() << endl;
172           cerr << "port pos : " << pos << endl;
173           if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
174           else ob=result;
175           cerr << "ob refcnt: " << ob->ob_refcnt << endl;
176           PyObject_Print(ob,stderr,Py_PRINT_RAW);
177           cerr << endl;
178           p->put(ob);
179           pos++;
180         }
181     }
182   catch(ConversionException)
183     {
184       Py_DECREF(result);
185       PyGILState_Release(gstate);
186       throw;
187     }
188   cerr << "-----------------End SalomePythonNode::outputs-----------------" << endl;
189
190   Py_DECREF(result);
191   PyGILState_Release(gstate);
192   cerr << "++++++++++++++ End SalomePythonNode::execute: " << getName() << " ++++++++++++++++++++" << endl;
193 }
194
195 std::string SalomePythonNode::getKind() const
196 {
197   static const char LOC_KIND[]="";
198   return LOC_KIND;
199 }
200
201 Node *SalomePythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
202 {
203   return new SalomePythonNode(*this,father);
204 }
205
206 ServiceNode *SalomePythonNode::createNode(const std::string &name)
207 {
208   ServiceNode* node=new SalomePythonNode(name);
209   node->setComponent(_component);
210   return node;
211 }
212
213 //! Create a new node of same type with a given name
214 SalomePythonNode* SalomePythonNode::cloneNode(const std::string& name)
215 {
216   SalomePythonNode* n=new SalomePythonNode(name);
217   n->setScript(_script);
218   n->setMethod(_method);
219   list<InputPort *>::iterator iter;
220   for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
221     {
222       InputPyPort *p=(InputPyPort *)*iter;
223       n->edAddInputPort(p->getName(),p->edGetType());
224     }
225   list<OutputPort *>::iterator iter2;
226   for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
227     {
228       OutputPyPort *p=(OutputPyPort *)*iter2;
229       n->edAddOutputPort(p->getName(),p->edGetType());
230     }
231   return n;
232 }