Salome HOME
merge from branch DEV tag mergeto_trunk_04apr08
[modules/yacs.git] / src / runtime / PythonNode.cxx
1
2 #include "RuntimeSALOME.hxx"
3 #include "PythonNode.hxx"
4 #include "PythonPorts.hxx"
5
6 #include "PyStdout.hxx"
7 #include <iostream>
8 #include <sstream>
9
10 //#define _DEVDEBUG_
11 #include "YacsTrace.hxx"
12
13 using namespace YACS::ENGINE;
14 using namespace std;
15
16 const char PythonNode::IMPL_NAME[]="Python";
17 const char PythonNode::KIND[]="Python";
18
19 PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father)
20 {
21   _implementation=IMPL_NAME;
22   PyGILState_STATE gstate=PyGILState_Ensure();
23   _context=PyDict_New();
24   PyGILState_Release(gstate);
25 }
26
27 PythonNode::PythonNode(const std::string& name):InlineNode(name)
28 {
29   _implementation=IMPL_NAME;
30   PyGILState_STATE gstate = PyGILState_Ensure();
31   _context=PyDict_New();
32   PyGILState_Release(gstate);
33 }
34
35 PythonNode::~PythonNode()
36 {
37   PyGILState_STATE gstate = PyGILState_Ensure();
38   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
39   Py_DECREF(_context);
40   PyGILState_Release(gstate);
41 }
42
43 void PythonNode::load()
44 {
45 }
46
47 void PythonNode::execute()
48 {
49   DEBTRACE( "++++++++++++++ PyNode::execute: " << getName() << " ++++++++++++++++++++" );
50   PyGILState_STATE gstate = PyGILState_Ensure();
51   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
52     {
53       stringstream msg;
54       msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
55       PyGILState_Release(gstate);
56       _errorDetails=msg.str();
57       throw Exception(msg.str());
58     }
59
60   DEBTRACE( "---------------PyNode::inputs---------------" );
61   list<InputPort *>::iterator iter2;
62   for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
63     {
64       InputPyPort *p=(InputPyPort *)*iter2;
65       DEBTRACE( "port name: " << p->getName() );
66       DEBTRACE( "port kind: " << p->edGetType()->kind() );
67       PyObject* ob=p->getPyObj();
68       DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
69 #ifdef _DEVDEBUG_
70       PyObject_Print(ob,stderr,Py_PRINT_RAW);
71       cerr << endl;
72 #endif
73       int ier=PyDict_SetItemString(_context,p->getName().c_str(),ob);
74       DEBTRACE( "after PyDict_SetItemString:ob refcnt: " << ob->ob_refcnt );
75     }
76   
77   DEBTRACE( "---------------End PyNode::inputs---------------" );
78   
79   //calculation
80   DEBTRACE( "----------------PyNode::calculation---------------" );
81   DEBTRACE(  _script );
82   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
83   PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context);
84   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
85   fflush(stdout);
86   fflush(stderr);
87   if(res == NULL)
88     {
89       _errorDetails="";
90       PyObject* new_stderr = newPyStdOut(_errorDetails);
91       PySys_SetObject("stderr", new_stderr);
92       PyErr_Print();
93       PySys_SetObject("stderr", PySys_GetObject("__stderr__"));
94       Py_DECREF(new_stderr);
95
96       PyGILState_Release(gstate);
97       throw Exception("Error during execution");
98     }
99   Py_DECREF(res);
100   
101   DEBTRACE( "-----------------PyNode::outputs-----------------" );
102   list<OutputPort *>::iterator iter;
103   try
104     {
105       for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
106         {
107           OutputPyPort *p=(OutputPyPort *)*iter;
108           DEBTRACE( "port name: " << p->getName() );
109           DEBTRACE( "port kind: " << p->edGetType()->kind() );
110           PyObject *ob=PyDict_GetItemString(_context,p->getName().c_str());
111           if(ob==NULL){
112              PyGILState_Release(gstate);
113              std::string msg="Error during execution: there is no variable ";
114              msg=msg+p->getName()+" in node context";
115              _errorDetails=msg;
116              throw Exception(msg);
117           }
118           DEBTRACE( "PyNode::outputs::ob refcnt: " << ob->ob_refcnt );
119 #ifdef _DEVDEBUG_
120           PyObject_Print(ob,stderr,Py_PRINT_RAW);
121           cerr << endl;
122 #endif
123           p->put(ob);
124         }
125     }
126   catch(ConversionException& ex)
127     {
128       PyGILState_Release(gstate);
129       _errorDetails=ex.what();
130       throw;
131     }
132
133   DEBTRACE( "-----------------End PyNode::outputs-----------------" );
134   PyGILState_Release(gstate);
135   DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" );
136 }
137
138 Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
139 {
140   return new PythonNode(*this,father);
141 }
142
143 //! Create a new node of same type with a given name
144 PythonNode* PythonNode::cloneNode(const std::string& name)
145 {
146   PythonNode* n=new PythonNode(name);
147   n->setScript(_script);
148   list<InputPort *>::iterator iter;
149   for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
150     {
151       InputPyPort *p=(InputPyPort *)*iter;
152       DEBTRACE( "port name: " << p->getName() );
153       DEBTRACE( "port kind: " << p->edGetType()->kind() );
154       n->edAddInputPort(p->getName(),p->edGetType());
155     }
156   list<OutputPort *>::iterator iter2;
157   for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
158     {
159       OutputPyPort *p=(OutputPyPort *)*iter2;
160       DEBTRACE( "port name: " << p->getName() );
161       DEBTRACE( "port kind: " << p->edGetType()->kind() );
162       n->edAddOutputPort(p->getName(),p->edGetType());
163     }
164   return n;
165 }
166
167 PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFuncNode(other,father),_pyfunc(0)
168 {
169   _implementation = PythonNode::IMPL_NAME;
170   PyGILState_STATE gstate = PyGILState_Ensure();
171   _context=PyDict_New();
172   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
173   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
174     {
175       stringstream msg;
176       msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
177       _errorDetails=msg.str();
178       PyGILState_Release(gstate);
179       throw Exception(msg.str());
180     }
181   PyGILState_Release(gstate);
182 }
183
184 PyFuncNode::PyFuncNode(const std::string& name): InlineFuncNode(name),_pyfunc(0)
185 {
186
187   _implementation = PythonNode::IMPL_NAME;
188   DEBTRACE( "PyFuncNode::PyFuncNode " << name );
189   PyGILState_STATE gstate = PyGILState_Ensure();
190   _context=PyDict_New();
191   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
192   if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
193     {
194       stringstream msg;
195       msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
196       _errorDetails=msg.str();
197       PyGILState_Release(gstate);
198       throw Exception(msg.str());
199     }
200   PyGILState_Release(gstate);
201 }
202
203 PyFuncNode::~PyFuncNode()
204 {
205   DEBTRACE( getName() );
206   PyGILState_STATE gstate = PyGILState_Ensure();
207   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
208   if(_pyfunc)DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
209   Py_DECREF(_context);
210   PyGILState_Release(gstate);
211 }
212
213 void PyFuncNode::load()
214 {
215   DEBTRACE( "---------------PyFuncNode::load function " << getName() << " ---------------" );
216   DEBTRACE(  _script );
217 #ifdef _DEVDEBUG_
218   list<OutputPort *>::iterator iter;
219   for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
220     {
221       OutputPyPort *p=(OutputPyPort *)*iter;
222       DEBTRACE( "port name: " << p->getName() );
223       DEBTRACE( "port kind: " << p->edGetType()->kind() );
224     }
225 #endif
226   PyGILState_STATE gstate = PyGILState_Ensure();
227   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
228   PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context);
229   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
230   if(res == NULL)
231     {
232       _errorDetails="";
233       PyObject* new_stderr = newPyStdOut(_errorDetails);
234       PySys_SetObject("stderr", new_stderr);
235       PyErr_Print();
236       PySys_SetObject("stderr", PySys_GetObject("__stderr__"));
237       Py_DECREF(new_stderr);
238
239       PyGILState_Release(gstate);
240       throw Exception("Error during execution");
241       return;
242     }
243   Py_DECREF(res);
244   _pyfunc=PyDict_GetItemString(_context,_fname.c_str());
245   DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
246   if(_pyfunc == NULL)
247     {
248       _errorDetails="";
249       PyObject* new_stderr = newPyStdOut(_errorDetails);
250       PySys_SetObject("stderr", new_stderr);
251       PyErr_Print();
252       PySys_SetObject("stderr", PySys_GetObject("__stderr__"));
253       Py_DECREF(new_stderr);
254
255       PyGILState_Release(gstate);
256       throw Exception("Error during execution");
257     }
258   DEBTRACE( "---------------End PyFuncNode::load function---------------" );
259   PyGILState_Release(gstate);
260 }
261
262 void PyFuncNode::execute()
263 {
264   DEBTRACE( "++++++++++++++ PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
265   int pos=0;
266   PyObject* ob;
267   if(!_pyfunc)throw Exception("PyFuncNode badly loaded");
268   PyGILState_STATE gstate = PyGILState_Ensure();
269
270   DEBTRACE( "---------------PyFuncNode::inputs---------------" );
271   PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
272   list<InputPort *>::iterator iter2;
273   for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
274     {
275       InputPyPort *p=(InputPyPort *)*iter2;
276       DEBTRACE( "port name: " << p->getName() );
277       DEBTRACE( "port kind: " << p->edGetType()->kind() );
278       ob=p->getPyObj();
279 #ifdef _DEVDEBUG_
280       PyObject_Print(ob,stderr,Py_PRINT_RAW);
281       cerr << endl;
282 #endif
283       DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
284       Py_INCREF(ob);
285       PyTuple_SetItem(args,pos,ob);
286       DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
287       pos++;
288     }
289   DEBTRACE( "---------------End PyFuncNode::inputs---------------" );
290
291   DEBTRACE( "----------------PyFuncNode::calculation---------------" );
292 #ifdef _DEVDEBUG_
293   PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
294   cerr << endl;
295   PyObject_Print(args,stderr,Py_PRINT_RAW);
296   cerr << endl;
297 #endif
298   DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
299   PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
300   DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
301   Py_DECREF(args);
302   fflush(stdout);
303   fflush(stderr);
304   if(result == NULL)
305     {
306       _errorDetails="";
307       PyObject* new_stderr = newPyStdOut(_errorDetails);
308       PySys_SetObject("stderr", new_stderr);
309       PyErr_Print();
310       PySys_SetObject("stderr", PySys_GetObject("__stderr__"));
311       Py_DECREF(new_stderr);
312
313       PyGILState_Release(gstate);
314       throw Exception("Error during execution");
315     }
316   DEBTRACE( "----------------End PyFuncNode::calculation---------------" );
317
318   DEBTRACE( "-----------------PyFuncNode::outputs-----------------" );
319   int nres=1;
320   if(result == Py_None)
321     nres=0;
322   else if(PyTuple_Check(result))
323     nres=PyTuple_Size(result);
324
325   if(getNumberOfOutputPorts() != nres)
326     {
327       std::string msg="Number of output arguments : Mismatch between definition and execution";
328       Py_DECREF(result);
329       PyGILState_Release(gstate);
330       _errorDetails=msg;
331       throw Exception(msg);
332     }
333
334   pos=0;
335 #ifdef _DEVDEBUG_
336   PyObject_Print(result,stderr,Py_PRINT_RAW);
337   cerr << endl;
338 #endif
339   list<OutputPort *>::iterator iter;
340   try
341     {
342       for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
343         {
344           OutputPyPort *p=(OutputPyPort *)*iter;
345           DEBTRACE( "port name: " << p->getName() );
346           DEBTRACE( "port kind: " << p->edGetType()->kind() );
347           DEBTRACE( "port pos : " << pos );
348           if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
349           else ob=result;
350           DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
351 #ifdef _DEVDEBUG_
352           PyObject_Print(ob,stderr,Py_PRINT_RAW);
353           cerr << endl;
354 #endif
355           p->put(ob);
356           pos++;
357         }
358     }
359   catch(ConversionException& ex)
360     {
361       Py_DECREF(result);
362       PyGILState_Release(gstate);
363       _errorDetails=ex.what();
364       throw;
365     }
366   DEBTRACE( "-----------------End PyFuncNode::outputs-----------------" );
367
368   Py_DECREF(result);
369   PyGILState_Release(gstate);
370   DEBTRACE( "++++++++++++++ End PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
371 }
372
373 Node *PyFuncNode::simpleClone(ComposedNode *father, bool editionOnly) const
374 {
375   return new PyFuncNode(*this,father);
376 }
377
378 //! Create a new node of same type with a given name
379 PyFuncNode* PyFuncNode::cloneNode(const std::string& name)
380 {
381   PyFuncNode* n=new PyFuncNode(name);
382   n->setScript(_script);
383   n->setFname(_fname);
384   list<InputPort *>::iterator iter;
385   for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
386     {
387       InputPyPort *p=(InputPyPort *)*iter;
388       n->edAddInputPort(p->getName(),p->edGetType());
389     }
390   list<OutputPort *>::iterator iter2;
391   for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
392     {
393       OutputPyPort *p=(OutputPyPort *)*iter2;
394       n->edAddOutputPort(p->getName(),p->edGetType());
395     }
396   return n;
397 }