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