Salome HOME
RAII protection + More information in case of throw
[modules/yacs.git] / src / runtime / PythonNode.cxx
1 // Copyright (C) 2006-2019  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 "PythonNode.hxx"
22 #include "PythonPorts.hxx"
23 #include "TypeCode.hxx"
24 #include "AutoGIL.hxx"
25 #include "Container.hxx"
26 #include "SalomeContainer.hxx"
27 #include "SalomeHPContainer.hxx"
28 #include "SalomeContainerTmpForHP.hxx"
29 #include "ConversionException.hxx"
30
31 #include "PyStdout.hxx"
32 #include <iostream>
33 #include <memory>
34 #include <sstream>
35 #include <fstream>
36
37 #ifdef WIN32
38 #include <process.h>
39 #define getpid _getpid
40 #endif
41
42 #if PY_VERSION_HEX < 0x02050000 
43 typedef int Py_ssize_t;
44 #endif
45
46 //#define _DEVDEBUG_
47 #include "YacsTrace.hxx"
48
49 using namespace YACS::ENGINE;
50 using namespace std;
51
52 const char PythonEntry::SCRIPT_FOR_SIMPLE_SERIALIZATION[]="import pickle\n"
53     "def pickleForVarSimplePyth2009(val):\n"
54     "  return pickle.dumps(val,-1)\n"
55     "\n";
56
57 const char PythonNode::IMPL_NAME[]="Python";
58 const char PythonNode::KIND[]="Python";
59
60 const char PythonNode::SCRIPT_FOR_SERIALIZATION[]="import pickle\n"
61     "def pickleForDistPyth2009(kws):\n"
62     "  return pickle.dumps(((),kws),-1)\n"
63     "\n"
64     "def unPickleForDistPyth2009(st):\n"
65     "  args=pickle.loads(st)\n"
66     "  return args\n";
67
68 const char PythonNode::REMOTE_NAME[]="remote";
69
70 const char PythonNode::DPL_INFO_NAME[]="my_dpl_localization";
71
72 const char PyFuncNode::SCRIPT_FOR_SERIALIZATION[]="import pickle\n"
73     "def pickleForDistPyth2009(*args,**kws):\n"
74     "  return pickle.dumps((args,kws),-1)\n"
75     "\n"
76     "def unPickleForDistPyth2009(st):\n"
77     "  args=pickle.loads(st)\n"
78     "  return args\n";
79
80
81 PythonEntry::PythonEntry():_context(0),_pyfuncSer(0),_pyfuncUnser(0),_pyfuncSimpleSer(0)
82 {
83 }
84
85 PythonEntry::~PythonEntry()
86 {
87   AutoGIL agil;
88   DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
89   // not Py_XDECREF of _pyfuncUnser because it is returned by PyDict_GetItem -> borrowed
90   // not Py_XDECREF of _pyfuncSer because it is returned by PyDict_GetItem -> borrowed
91   Py_XDECREF(_context);
92 }
93
94 void PythonEntry::commonRemoteLoadPart1(InlineNode *reqNode)
95 {
96   DEBTRACE( "---------------PythonEntry::CommonRemoteLoad function---------------" );
97   Container *container(reqNode->getContainer());
98   bool isContAlreadyStarted(false);
99   if(container)
100     {
101       isContAlreadyStarted=container->isAlreadyStarted(reqNode);
102       if(!isContAlreadyStarted)
103         {
104           try
105           {
106               container->start(reqNode);
107           }
108           catch(Exception& e)
109           {
110               reqNode->setErrorDetails(e.what());
111               throw e;
112           }
113         }
114     }
115   else
116     {
117       std::string what("PythonEntry::CommonRemoteLoad : a load operation requested on \"");
118       what+=reqNode->getName(); what+="\" with no container specified.";
119       reqNode->setErrorDetails(what);
120       throw Exception(what);
121     }
122 }
123
124 Engines::Container_var GetContainerObj(InlineNode *reqNode, bool& isStandardCont)
125 {
126   isStandardCont = false;
127   Container *container(reqNode->getContainer());
128   Engines::Container_var objContainer(Engines::Container::_nil());
129   if(!container)
130     throw YACS::Exception("No container specified !");
131   SalomeContainer *containerCast0(dynamic_cast<SalomeContainer *>(container));
132   SalomeHPContainerBase *containerCast1(dynamic_cast<SalomeHPContainerBase *>(container));
133   if(containerCast0)
134     {
135       isStandardCont = true;
136       objContainer=containerCast0->getContainerPtr(reqNode);
137     }
138   else if(containerCast1)
139     {
140       objContainer=containerCast1->getContainerPtr(reqNode);
141     }
142   else
143     throw YACS::Exception("Unrecognized type of container ! Salome one is expected for PythonNode/PyFuncNode !");
144   if(CORBA::is_nil(objContainer))
145     throw YACS::Exception("Container corba pointer is NULL for PythonNode !");
146   return objContainer;
147 }
148
149 Engines::Container_var PythonEntry::commonRemoteLoadPart2(InlineNode *reqNode, bool& isInitializeRequested)
150 {
151   bool isStandardCont(true);
152   Engines::Container_var objContainer(GetContainerObj(reqNode,isStandardCont));
153   isInitializeRequested=false;
154   try
155   {
156       if(isStandardCont)
157         {
158           createRemoteAdaptedPyInterpretor(objContainer);
159         }
160       else
161         {
162           Engines::PyNodeBase_var dftPyScript(retrieveDftRemotePyInterpretorIfAny(objContainer));
163           if(CORBA::is_nil(dftPyScript))
164             {
165               isInitializeRequested=true;
166               createRemoteAdaptedPyInterpretor(objContainer);
167             }
168           else
169             assignRemotePyInterpretor(dftPyScript);
170         }
171   }
172   catch( const SALOME::SALOME_Exception& ex )
173   {
174       std::string msg="Exception on remote python node creation ";
175       msg += '\n';
176       msg += ex.details.text.in();
177       reqNode->setErrorDetails(msg);
178       throw Exception(msg);
179   }
180   Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle());
181   if(CORBA::is_nil(pynode))
182     throw Exception("In PythonNode the ref in NULL ! ");
183   return objContainer;
184 }
185
186 void PythonEntry::commonRemoteLoadPart3(InlineNode *reqNode, Engines::Container_ptr objContainer, bool isInitializeRequested)
187 {
188   Container *container(reqNode->getContainer());
189   Engines::PyNodeBase_var pynode(getRemoteInterpreterHandle());
190   ///
191   {
192     AutoGIL agil;
193     const char *picklizeScript(getSerializationScript());
194     PyObject *res=PyRun_String(picklizeScript,Py_file_input,_context,_context);
195     PyObject *res2(PyRun_String(SCRIPT_FOR_SIMPLE_SERIALIZATION,Py_file_input,_context,_context));
196     if(res == NULL || res2==NULL)
197       {
198         std::string errorDetails;
199         PyObject* new_stderr = newPyStdOut(errorDetails);
200         reqNode->setErrorDetails(errorDetails);
201         PySys_SetObject((char*)"stderr", new_stderr);
202         PyErr_Print();
203         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
204         Py_DECREF(new_stderr);
205         throw Exception("Error during load");
206       }
207     Py_DECREF(res); Py_DECREF(res2);
208     _pyfuncSer=PyDict_GetItemString(_context,"pickleForDistPyth2009");
209     _pyfuncUnser=PyDict_GetItemString(_context,"unPickleForDistPyth2009");
210     _pyfuncSimpleSer=PyDict_GetItemString(_context,"pickleForVarSimplePyth2009");
211     if(_pyfuncSer == NULL)
212       {
213         std::string errorDetails;
214         PyObject *new_stderr(newPyStdOut(errorDetails));
215         reqNode->setErrorDetails(errorDetails);
216         PySys_SetObject((char*)"stderr", new_stderr);
217         PyErr_Print();
218         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
219         Py_DECREF(new_stderr);
220         throw Exception("Error during load");
221       }
222     if(_pyfuncUnser == NULL)
223       {
224         std::string errorDetails;
225         PyObject *new_stderr(newPyStdOut(errorDetails));
226         reqNode->setErrorDetails(errorDetails);
227         PySys_SetObject((char*)"stderr", new_stderr);
228         PyErr_Print();
229         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
230         Py_DECREF(new_stderr);
231         throw Exception("Error during load");
232       }
233     if(_pyfuncSimpleSer == NULL)
234       {
235         std::string errorDetails;
236         PyObject *new_stderr(newPyStdOut(errorDetails));
237         reqNode->setErrorDetails(errorDetails);
238         PySys_SetObject((char*)"stderr", new_stderr);
239         PyErr_Print();
240         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
241         Py_DECREF(new_stderr);
242         throw Exception("Error during load");
243       }
244   }
245   if(isInitializeRequested)
246     {//This one is called only once at initialization in the container if an init-script is specified.
247       try
248       {
249           std::string zeInitScriptKey(container->getProperty(HomogeneousPoolContainer::INITIALIZE_SCRIPT_KEY));
250           if(!zeInitScriptKey.empty())
251             pynode->executeAnotherPieceOfCode(zeInitScriptKey.c_str());
252       }
253       catch( const SALOME::SALOME_Exception& ex )
254       {
255           std::string msg="Exception on PythonNode::loadRemote python invocation of initializisation py script !";
256           msg += '\n';
257           msg += ex.details.text.in();
258           reqNode->setErrorDetails(msg);
259           throw Exception(msg);
260       }
261       DEBTRACE( "---------------End PyNode::loadRemote function---------------" );
262     }
263 }
264
265 std::string PythonEntry::GetContainerLog(const std::string& mode, Container *container, const Task *askingTask)
266 {
267   if(mode=="local")
268     return "";
269
270   std::string msg;
271   try
272   {
273       SalomeContainer *containerCast(dynamic_cast<SalomeContainer *>(container));
274       SalomeHPContainer *objContainer2(dynamic_cast<SalomeHPContainer *>(container));
275       if(containerCast)
276         {
277           Engines::Container_var objContainer(containerCast->getContainerPtr(askingTask));
278           CORBA::String_var logname = objContainer->logfilename();
279           DEBTRACE(logname);
280           msg=logname;
281           std::string::size_type pos = msg.find(":");
282           msg=msg.substr(pos+1);
283         }
284       else if(objContainer2)
285         {
286           msg="Remote PythonNode is on HP Container : no log because no info of the location by definition of HP Container !";
287         }
288       else
289         {
290           msg="Not implemented yet for container log for that type of container !";
291         }
292   }
293   catch(...)
294   {
295       msg = "Container no longer reachable";
296   }
297   return msg;
298 }
299
300 void PythonEntry::commonRemoteLoad(InlineNode *reqNode)
301 {
302   commonRemoteLoadPart1(reqNode);
303   bool isInitializeRequested;
304   Engines::Container_var objContainer(commonRemoteLoadPart2(reqNode,isInitializeRequested));
305   commonRemoteLoadPart3(reqNode,objContainer,isInitializeRequested);
306 }
307
308 PythonNode::PythonNode(const PythonNode& other, ComposedNode *father):InlineNode(other,father),_autoSqueeze(other._autoSqueeze)
309 {
310   _implementation=IMPL_NAME;
311   {
312     AutoGIL agil;
313     _context=PyDict_New();
314     if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
315       {
316         stringstream msg;
317         msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
318         _errorDetails=msg.str();
319         throw Exception(msg.str());
320       }
321   }
322 }
323
324 PythonNode::PythonNode(const std::string& name):InlineNode(name)
325 {
326   _implementation=IMPL_NAME;
327   {
328     AutoGIL agil;
329     _context=PyDict_New();
330     if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
331       {
332         stringstream msg;
333         msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__;
334         _errorDetails=msg.str();
335         throw Exception(msg.str());
336       }
337   }
338 }
339
340 PythonNode::~PythonNode()
341 {
342   if(!CORBA::is_nil(_pynode))
343     {
344       _pynode->UnRegister();
345     }
346 }
347
348 void PythonNode::checkBasicConsistency() const throw(YACS::Exception)
349 {
350   DEBTRACE("checkBasicConsistency");
351   InlineNode::checkBasicConsistency();
352   {
353     AutoGIL agil;
354     PyObject* res;
355     res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
356     if(res == NULL)
357       {
358         std::string error="";
359         PyObject* new_stderr = newPyStdOut(error);
360         PySys_SetObject((char*)"stderr", new_stderr);
361         PyErr_Print();
362         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
363         Py_DECREF(new_stderr);
364         throw Exception(error);
365       }
366     else
367       Py_XDECREF(res);
368   }
369 }
370
371 void PythonNode::load()
372 {
373   DEBTRACE( "---------------PyNode::load function---------------" );
374   if(_mode==PythonNode::REMOTE_NAME)
375     loadRemote();
376   else
377     loadLocal();
378 }
379
380 void PythonNode::loadLocal()
381 {
382   DEBTRACE( "---------------PyNode::loadLocal function---------------" );
383   // do nothing
384 }
385
386 void PythonNode::loadRemote()
387 {
388   commonRemoteLoad(this);
389 }
390
391 void PythonNode::execute()
392 {
393   if(_mode==PythonNode::REMOTE_NAME)
394     executeRemote();
395   else
396     executeLocal();
397 }
398
399 void PythonNode::executeRemote()
400 {
401   DEBTRACE( "++++++++++++++ PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
402   if(!_pyfuncSer)
403     throw Exception("DistributedPythonNode badly loaded");
404   //
405   if(dynamic_cast<HomogeneousPoolContainer *>(getContainer()))
406     {
407       bool dummy;
408       commonRemoteLoadPart2(this,dummy);
409       _pynode->assignNewCompiledCode(getScript().c_str());
410     }
411   //
412   std::unique_ptr<Engines::pickledArgs> serializationInputCorba(new Engines::pickledArgs);
413   AutoPyRef serializationInput;
414   {
415       AutoGIL agil;
416       PyObject *args(0),*ob(0);
417       //===========================================================================
418       // Get inputs in input ports, build a Python dict and pickle it
419       //===========================================================================
420       args = PyDict_New();
421       std::list<InputPort *>::iterator iter2;
422       int pos(0);
423       for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); ++iter2)
424         {
425           InputPyPort *p=(InputPyPort *)*iter2;
426           ob=p->getPyObj();
427           PyDict_SetItemString(args,p->getName().c_str(),ob);
428           pos++;
429         }
430 #ifdef _DEVDEBUG_
431       PyObject_Print(args,stderr,Py_PRINT_RAW);
432       std::cerr << endl;
433 #endif
434       serializationInput.set(PyObject_CallFunctionObjArgs(_pyfuncSer,args,nullptr));
435       Py_DECREF(args);
436       //The pickled string may contain NULL characters so use PyString_AsStringAndSize
437       char *serializationInputC(0);
438       Py_ssize_t len;
439       if (PyBytes_AsStringAndSize(serializationInput, &serializationInputC, &len))
440         throw Exception("DistributedPythonNode problem in python pickle");
441       // no copy here. The C byte array of Python is taken  as this into CORBA sequence to avoid copy
442       serializationInputCorba.reset(new Engines::pickledArgs(len,len,reinterpret_cast<CORBA::Octet *>(serializationInputC),0));
443   }
444
445   //get the list of output argument names
446   std::list<OutputPort *>::iterator iter;
447   Engines::listofstring myseq;
448   myseq.length(getNumberOfOutputPorts());
449   int pos=0;
450   for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
451     {
452       OutputPyPort *p=(OutputPyPort *)*iter;
453       myseq[pos]=p->getName().c_str();
454       DEBTRACE( "port name: " << p->getName() );
455       DEBTRACE( "port kind: " << p->edGetType()->kind() );
456       DEBTRACE( "port pos : " << pos );
457       pos++;
458     }
459   //===========================================================================
460   // Execute in remote Python node
461   //===========================================================================
462   DEBTRACE( "-----------------starting remote python invocation-----------------" );
463   std::unique_ptr<Engines::pickledArgs> resultCorba;
464   try
465     {
466       //pass outargsname and dict serialized
467       _pynode->executeFirst(*(serializationInputCorba.get()));
468       //serializationInput and serializationInputCorba are no more needed for server. Release it.
469       serializationInputCorba.reset(nullptr); serializationInput.set(nullptr);
470       resultCorba.reset(_pynode->executeSecond(myseq));
471     }
472   catch( const SALOME::SALOME_Exception& ex )
473     {
474       std::ostringstream msg; msg << "Exception on remote python invocation" << std::endl << ex.details.text.in() << std::endl;
475       msg << "PyScriptNode CORBA ref : ";
476       {
477         CORBA::ORB_ptr orb(getSALOMERuntime()->getOrb());
478         if(!CORBA::is_nil(orb))
479         {
480           CORBA::String_var IOR(orb->object_to_string(_pynode));
481           msg << IOR;
482         }
483       }
484       msg << std::endl;
485       _errorDetails=msg.str();
486       throw Exception(msg.str());
487     }
488   if(!CORBA::is_nil(_pynode))
489     {
490       _pynode->UnRegister();
491     }
492   _pynode = Engines::PyScriptNode::_nil();
493   //
494   bool dummy;
495   Engines::Container_var cont(GetContainerObj(this,dummy));
496   cont->removePyScriptNode(getName().c_str());
497   DEBTRACE( "-----------------end of remote python invocation-----------------" );
498   //===========================================================================
499   // Get results, unpickle and put them in output ports
500   //===========================================================================
501   auto length(resultCorba->length());
502   char *resultCorbaC(reinterpret_cast<char *>(resultCorba->get_buffer()));
503   {
504       AutoGIL agil;
505       PyObject *args(0),*ob(0);
506       PyObject* resultPython=PyMemoryView_FromMemory(resultCorbaC,length,PyBUF_READ);
507       args = PyTuple_New(1);
508       PyTuple_SetItem(args,0,resultPython);
509       PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
510       resultCorba.reset(nullptr);
511       Py_DECREF(args);
512
513       if (finalResult == NULL)
514         {
515           std::stringstream msg;
516           msg << "Conversion with pickle of output ports failed !";
517           msg << " : " << __FILE__ << ":" << __LINE__;
518           _errorDetails=msg.str();
519           throw YACS::ENGINE::ConversionException(msg.str());
520         }
521
522       DEBTRACE( "-----------------PythonNode::outputs-----------------" );
523       int nres=1;
524       if(finalResult == Py_None)
525         nres=0;
526       else if(PyTuple_Check(finalResult))
527         nres=PyTuple_Size(finalResult);
528
529       if(getNumberOfOutputPorts() != nres)
530         {
531           std::string msg="Number of output arguments : Mismatch between definition and execution";
532           Py_DECREF(finalResult);
533           _errorDetails=msg;
534           throw Exception(msg);
535         }
536
537       pos=0;
538       try
539       {
540           for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); ++iter)
541             {
542               OutputPyPort *p=(OutputPyPort *)*iter;
543               DEBTRACE( "port name: " << p->getName() );
544               DEBTRACE( "port kind: " << p->edGetType()->kind() );
545               DEBTRACE( "port pos : " << pos );
546               if(PyTuple_Check(finalResult))
547                 ob=PyTuple_GetItem(finalResult,pos) ;
548               else
549                 ob=finalResult;
550               DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
551               p->put(ob);
552               pos++;
553             }
554           Py_DECREF(finalResult);
555       }
556       catch(ConversionException& ex)
557       {
558           Py_DECREF(finalResult);
559           _errorDetails=ex.what();
560           throw;
561       }
562       if(_autoSqueeze)
563         squeezeMemoryRemote();
564   }
565   DEBTRACE( "++++++++++++++ ENDOF PyNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
566 }
567
568 void PythonNode::executeLocal()
569 {
570   DEBTRACE( "++++++++++++++ PyNode::executeLocal: " << getName() << " ++++++++++++++++++++" );
571   {
572     AutoGIL agil;
573
574     DEBTRACE( "---------------PyNode::inputs---------------" );
575     list<InputPort *>::iterator iter2;
576     for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
577       {
578         InputPyPort *p=(InputPyPort *)*iter2;
579         DEBTRACE( "port name: " << p->getName() );
580         DEBTRACE( "port kind: " << p->edGetType()->kind() );
581         PyObject* ob=p->getPyObj();
582         DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
583 #ifdef _DEVDEBUG_
584         PyObject_Print(ob,stderr,Py_PRINT_RAW);
585         cerr << endl;
586 #endif
587         int ier=PyDict_SetItemString(_context,p->getName().c_str(),ob);
588         DEBTRACE( "after PyDict_SetItemString:ob refcnt: " << ob->ob_refcnt );
589       }
590
591     DEBTRACE( "---------------End PyNode::inputs---------------" );
592
593     //calculation
594     DEBTRACE( "----------------PyNode::calculation---------------" );
595     DEBTRACE(  _script );
596     DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
597
598     std::ostringstream stream;
599     stream << "/tmp/PythonNode_";
600     stream << getpid();
601
602     PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
603     if(code == NULL)
604       {
605         _errorDetails=""; 
606         PyObject* new_stderr = newPyStdOut(_errorDetails);
607         PySys_SetObject((char*)"stderr", new_stderr);
608         PyErr_Print();
609         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
610         Py_DECREF(new_stderr);
611         throw Exception("Error during execution");
612       }
613     PyObject *res = PyEval_EvalCode(  code, _context, _context);
614
615     Py_DECREF(code);
616     Py_XDECREF(res);
617     DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
618     fflush(stdout);
619     fflush(stderr);
620     if(PyErr_Occurred ())
621       {
622         _errorDetails="";
623         PyObject* new_stderr = newPyStdOut(_errorDetails);
624         PySys_SetObject((char*)"stderr", new_stderr);
625         ofstream errorfile(stream.str().c_str());
626         if (errorfile.is_open())
627           {
628             errorfile << _script;
629             errorfile.close();
630           }
631         PyErr_Print();
632         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
633         Py_DECREF(new_stderr);
634         throw Exception("Error during execution");
635       }
636
637     DEBTRACE( "-----------------PyNode::outputs-----------------" );
638     list<OutputPort *>::iterator iter;
639     try
640     {
641         for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
642           {
643             OutputPyPort *p=(OutputPyPort *)*iter;
644             DEBTRACE( "port name: " << p->getName() );
645             DEBTRACE( "port kind: " << p->edGetType()->kind() );
646             PyObject *ob=PyDict_GetItemString(_context,p->getName().c_str());
647             if(ob==NULL)
648               {
649                 std::string msg="Error during execution: there is no variable ";
650                 msg=msg+p->getName()+" in node context";
651                 _errorDetails=msg;
652                 throw Exception(msg);
653               }
654             DEBTRACE( "PyNode::outputs::ob refcnt: " << ob->ob_refcnt );
655 #ifdef _DEVDEBUG_
656             PyObject_Print(ob,stderr,Py_PRINT_RAW);
657             cerr << endl;
658 #endif
659             p->put(ob);
660           }
661     }
662     catch(ConversionException& ex)
663     {
664         _errorDetails=ex.what();
665         throw;
666     }
667     if(_autoSqueeze)
668       squeezeMemory();
669     DEBTRACE( "-----------------End PyNode::outputs-----------------" );
670   }
671   DEBTRACE( "++++++++++++++ End PyNode::execute: " << getName() << " ++++++++++++++++++++" );
672 }
673
674 void PythonNode::squeezeMemorySafe()
675 {
676   AutoGIL agil;
677   if(_mode==PythonNode::REMOTE_NAME)
678     this->squeezeMemoryRemote();
679   else
680     this->squeezeMemory();
681 }
682   
683 void PythonNode::squeezeMemory()
684 {
685   for(auto p : _setOfInputPort)
686     {
687       PyDict_DelItemString(_context,p->getName().c_str());
688       InputPyPort *p2(static_cast<InputPyPort *>(p));
689       if(p2->canSafelySqueezeMemory())
690         p2->put(Py_None);
691     }
692   for(auto p : _setOfOutputPort)
693     {
694       PyDict_DelItemString(_context,p->getName().c_str());
695       OutputPyPort *p2(static_cast<OutputPyPort *>(p));
696       p2->putWithoutForward(Py_None);
697     }
698 }
699
700 void PythonNode::squeezeMemoryRemote()
701 {
702   for(auto p : _setOfInputPort)
703     {
704       InputPyPort *p2(static_cast<InputPyPort *>(p));
705       if(p2->canSafelySqueezeMemory())
706         p2->put(Py_None);
707     }
708   for(auto p : _setOfOutputPort)
709     {
710       OutputPyPort *p2(static_cast<OutputPyPort *>(p));
711       p2->putWithoutForward(Py_None);
712     }
713 }
714
715 std::string PythonNode::getContainerLog()
716 {
717   return PythonEntry::GetContainerLog(_mode,_container,this);
718 }
719
720 void PythonNode::shutdown(int level)
721 {
722   DEBTRACE("PythonNode::shutdown " << level);
723   if(_mode=="local")return;
724   if(_container)
725     {
726       if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
727       _pynode=Engines::PyScriptNode::_nil();
728       _container->shutdown(level);
729     }
730 }
731
732 Node *PythonNode::simpleClone(ComposedNode *father, bool editionOnly) const
733 {
734   return new PythonNode(*this,father);
735 }
736
737 void PythonNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
738 {
739   if(!CORBA::is_nil(_pynode))
740     _pynode->UnRegister();
741   _pynode=objContainer->createPyScriptNode(getName().c_str(),getScript().c_str());
742   _pynode->Register();
743 }
744
745 Engines::PyNodeBase_var PythonNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const
746 {
747   Engines::PyScriptNode_var ret(objContainer->getDefaultPyScriptNode(getName().c_str()));
748   if(!CORBA::is_nil(ret))
749     {
750       ret->Register();
751     }
752   return Engines::PyNodeBase::_narrow(ret);
753 }
754
755 void PythonNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
756 {
757   if(!CORBA::is_nil(_pynode))
758     {
759       Engines::PyScriptNode_var tmpp(Engines::PyScriptNode::_narrow(remoteInterp));
760       if(_pynode->_is_equivalent(tmpp))
761         {
762           _pynode->UnRegister();
763           return ;
764         }
765     }
766   if(!CORBA::is_nil(_pynode))
767     _pynode->UnRegister();
768   _pynode=Engines::PyScriptNode::_narrow(remoteInterp);
769 }
770
771 Engines::PyNodeBase_var PythonNode::getRemoteInterpreterHandle()
772 {
773   return Engines::PyNodeBase::_narrow(_pynode);
774 }
775
776 //! Create a new node of same type with a given name
777 PythonNode* PythonNode::cloneNode(const std::string& name)
778 {
779   PythonNode* n=new PythonNode(name);
780   n->setScript(_script);
781   list<InputPort *>::iterator iter;
782   for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
783     {
784       InputPyPort *p=(InputPyPort *)*iter;
785       DEBTRACE( "port name: " << p->getName() );
786       DEBTRACE( "port kind: " << p->edGetType()->kind() );
787       n->edAddInputPort(p->getName(),p->edGetType());
788     }
789   list<OutputPort *>::iterator iter2;
790   for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
791     {
792       OutputPyPort *p=(OutputPyPort *)*iter2;
793       DEBTRACE( "port name: " << p->getName() );
794       DEBTRACE( "port kind: " << p->edGetType()->kind() );
795       n->edAddOutputPort(p->getName(),p->edGetType());
796     }
797   return n;
798 }
799
800 void PythonNode::applyDPLScope(ComposedNode *gfn)
801 {
802   std::vector< std::pair<std::string,int> > ret(getDPLScopeInfo(gfn));
803   if(ret.empty())
804     return ;
805   //
806   PyObject *ob(0);
807   {
808     AutoGIL agil;
809     std::size_t sz(ret.size());
810     ob=PyList_New(sz);
811     for(std::size_t i=0;i<sz;i++)
812       {
813         const std::pair<std::string,int>& p(ret[i]);
814         PyObject *elt(PyTuple_New(2));
815         PyTuple_SetItem(elt,0,PyUnicode_FromString(p.first.c_str()));
816         PyTuple_SetItem(elt,1,PyLong_FromLong(p.second));
817         PyList_SetItem(ob,i,elt);
818       }
819   }
820   if(_mode==REMOTE_NAME)
821     {
822       Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);
823       {
824         AutoGIL agil;
825         PyObject *serializationInput(PyObject_CallFunctionObjArgs(_pyfuncSimpleSer,ob,NULL));
826         Py_XDECREF(ob);
827         char *serializationInputC(0);
828         Py_ssize_t len;
829         if (PyBytes_AsStringAndSize(serializationInput, &serializationInputC, &len))
830           throw Exception("DistributedPythonNode problem in python pickle");
831         serializationInputCorba->length(len);
832         for(int i=0; i < len ; i++)
833           serializationInputCorba[i]=serializationInputC[i];
834         Py_XDECREF(serializationInput);
835       }
836       _pynode->defineNewCustomVar(DPL_INFO_NAME,serializationInputCorba);
837     }
838   else
839     {
840       AutoGIL agil;
841       PyDict_SetItemString(_context,DPL_INFO_NAME,ob);
842       Py_XDECREF(ob);
843     }
844 }
845
846 PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFuncNode(other,father),_pyfunc(0)
847 {
848   _implementation = PythonNode::IMPL_NAME;
849   {
850     AutoGIL agil;
851     _context=PyDict_New();
852     DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
853     if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
854       {
855         stringstream msg;
856         msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
857         _errorDetails=msg.str();
858         throw Exception(msg.str());
859       }
860   }
861 }
862
863 PyFuncNode::PyFuncNode(const std::string& name): InlineFuncNode(name),_pyfunc(0)
864 {
865
866   _implementation = PythonNode::IMPL_NAME;
867   DEBTRACE( "PyFuncNode::PyFuncNode " << name );
868   {
869     AutoGIL agil;
870     _context=PyDict_New();
871     DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
872     if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() ))
873       {
874         stringstream msg;
875         msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__;
876         _errorDetails=msg.str();
877         throw Exception(msg.str());
878       }
879   }
880 }
881
882 PyFuncNode::~PyFuncNode()
883 {
884   if(!CORBA::is_nil(_pynode))
885     {
886       _pynode->UnRegister();
887     }
888 }
889
890 void PyFuncNode::init(bool start)
891 {
892   initCommonPartWithoutStateManagement(start);
893   if(_state == YACS::DISABLED)
894     {
895       exDisabledState(); // to refresh propagation of DISABLED state
896       return ;
897     }
898   if(start) //complete initialization
899     setState(YACS::READY);
900   else if(_state > YACS::LOADED)// WARNING FuncNode has internal vars (CEA usecase) ! Partial initialization (inside a loop). Exclusivity of funcNode.
901     setState(YACS::TORECONNECT);
902 }
903
904 void PyFuncNode::checkBasicConsistency() const throw(YACS::Exception)
905 {
906   DEBTRACE("checkBasicConsistency");
907   InlineFuncNode::checkBasicConsistency();
908   {
909     AutoGIL agil;
910     PyObject* res;
911     res=Py_CompileString(_script.c_str(),getName().c_str(),Py_file_input);
912     if(res == NULL)
913       {
914         std::string error="";
915         PyObject* new_stderr = newPyStdOut(error);
916         PySys_SetObject((char*)"stderr", new_stderr);
917         PyErr_Print();
918         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
919         Py_DECREF(new_stderr);
920         throw Exception(error);
921       }
922     else
923       Py_XDECREF(res);
924   }
925 }
926
927 void PyFuncNode::load()
928 {
929   DEBTRACE( "---------------PyfuncNode::load function---------------" );
930   if(_mode==PythonNode::REMOTE_NAME)
931     loadRemote();
932   else
933     loadLocal();
934 }
935
936 void PyFuncNode::loadRemote()
937 {
938   commonRemoteLoad(this);
939 }
940
941 void PyFuncNode::loadLocal()
942 {
943   DEBTRACE( "---------------PyFuncNode::load function " << getName() << " ---------------" );
944   DEBTRACE(  _script );
945
946 #ifdef _DEVDEBUG_
947   list<OutputPort *>::iterator iter;
948   for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
949     {
950       OutputPyPort *p=(OutputPyPort *)*iter;
951       DEBTRACE( "port name: " << p->getName() );
952       DEBTRACE( "port kind: " << p->edGetType()->kind() );
953     }
954 #endif
955
956   {
957     AutoGIL agil;
958     DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
959
960     std::ostringstream stream;
961     stream << "/tmp/PythonNode_";
962     stream << getpid();
963
964     PyObject* code=Py_CompileString(_script.c_str(), stream.str().c_str(), Py_file_input);
965     if(code == NULL)
966       {
967         _errorDetails="";
968         PyObject* new_stderr = newPyStdOut(_errorDetails);
969         PySys_SetObject((char*)"stderr", new_stderr);
970         PyErr_Print();
971         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
972         Py_DECREF(new_stderr);
973         throw Exception("Error during execution");
974       }
975     PyObject *res = PyEval_EvalCode( code, _context, _context);
976     Py_DECREF(code);
977     Py_XDECREF(res);
978
979     DEBTRACE( "_context refcnt: " << _context->ob_refcnt );
980     if(PyErr_Occurred ())
981       {
982         _errorDetails="";
983         PyObject* new_stderr = newPyStdOut(_errorDetails);
984         PySys_SetObject((char*)"stderr", new_stderr);
985         ofstream errorfile(stream.str().c_str());
986         if (errorfile.is_open())
987           {
988             errorfile << _script;
989             errorfile.close();
990           }
991         PyErr_Print();
992         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
993         Py_DECREF(new_stderr);
994         throw Exception("Error during execution");
995         return;
996       }
997     _pyfunc=PyDict_GetItemString(_context,_fname.c_str());
998     DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
999     if(_pyfunc == NULL)
1000       {
1001         _errorDetails="";
1002         PyObject* new_stderr = newPyStdOut(_errorDetails);
1003         PySys_SetObject((char*)"stderr", new_stderr);
1004         PyErr_Print();
1005         PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
1006         Py_DECREF(new_stderr);
1007         throw Exception("Error during execution");
1008       }
1009     DEBTRACE( "---------------End PyFuncNode::load function---------------" );
1010   }
1011 }
1012
1013 void PyFuncNode::execute()
1014 {
1015   if(_mode==PythonNode::REMOTE_NAME)
1016     executeRemote();
1017   else
1018     executeLocal();
1019 }
1020
1021 void PyFuncNode::executeRemote()
1022 {
1023   DEBTRACE( "++++++++++++++ PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
1024   if(!_pyfuncSer)
1025     throw Exception("DistributedPythonNode badly loaded");
1026   //
1027   if(dynamic_cast<HomogeneousPoolContainer *>(getContainer()))
1028     {
1029       bool dummy;
1030       commonRemoteLoadPart2(this,dummy);
1031       _pynode->executeAnotherPieceOfCode(getScript().c_str());
1032     }
1033   //
1034   Engines::pickledArgs_var serializationInputCorba(new Engines::pickledArgs);;
1035   {
1036       AutoGIL agil;
1037       PyObject *ob(0);
1038       //===========================================================================
1039       // Get inputs in input ports, build a Python tuple and pickle it
1040       //===========================================================================
1041       PyObject *args(PyTuple_New(getNumberOfInputPorts()));
1042       int pos(0);
1043       for(std::list<InputPort *>::iterator iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++,pos++)
1044         {
1045           InputPyPort *p=(InputPyPort *)*iter2;
1046           ob=p->getPyObj();
1047           Py_INCREF(ob);
1048           PyTuple_SetItem(args,pos,ob);
1049         }
1050 #ifdef _DEVDEBUG_
1051       PyObject_Print(args,stderr,Py_PRINT_RAW);
1052       std::cerr << endl;
1053 #endif
1054       PyObject *serializationInput=PyObject_CallObject(_pyfuncSer,args);
1055       Py_DECREF(args);
1056       //The pickled string may contain NULL characters so use PyString_AsStringAndSize
1057       char *serializationInputC(0);
1058       Py_ssize_t len;
1059       if (PyBytes_AsStringAndSize(serializationInput, &serializationInputC, &len))
1060         throw Exception("DistributedPythonNode problem in python pickle");
1061
1062       serializationInputCorba->length(len);
1063       for(int i=0; i < len ; i++)
1064         serializationInputCorba[i]=serializationInputC[i];
1065       Py_DECREF(serializationInput);
1066   }
1067
1068   //===========================================================================
1069   // Execute in remote Python node
1070   //===========================================================================
1071   DEBTRACE( "-----------------starting remote python invocation-----------------" );
1072   Engines::pickledArgs_var resultCorba;
1073   try
1074     {
1075       resultCorba=_pynode->execute(getFname().c_str(),serializationInputCorba);
1076     }
1077   catch( const SALOME::SALOME_Exception& ex )
1078     {
1079       std::string msg="Exception on remote python invocation";
1080       msg += '\n';
1081       msg += ex.details.text.in();
1082       _errorDetails=msg;
1083       throw Exception(msg);
1084     }
1085   DEBTRACE( "-----------------end of remote python invocation-----------------" );
1086   //===========================================================================
1087   // Get results, unpickle and put them in output ports
1088   //===========================================================================
1089   char *resultCorbaC=new char[resultCorba->length()+1];
1090   resultCorbaC[resultCorba->length()]='\0';
1091   for(int i=0;i<resultCorba->length();i++)
1092     resultCorbaC[i]=resultCorba[i];
1093
1094   {
1095       AutoGIL agil;
1096
1097       PyObject *resultPython(PyBytes_FromStringAndSize(resultCorbaC,resultCorba->length()));
1098       delete [] resultCorbaC;
1099       PyObject *args(PyTuple_New(1)),*ob(0);
1100       PyTuple_SetItem(args,0,resultPython);
1101       PyObject *finalResult=PyObject_CallObject(_pyfuncUnser,args);
1102       Py_DECREF(args);
1103
1104       DEBTRACE( "-----------------PythonNode::outputs-----------------" );
1105       int nres=1;
1106       if(finalResult == Py_None)
1107         nres=0;
1108       else if(PyTuple_Check(finalResult))
1109         nres=PyTuple_Size(finalResult);
1110
1111       if(getNumberOfOutputPorts() != nres)
1112         {
1113           std::string msg="Number of output arguments : Mismatch between definition and execution";
1114           Py_DECREF(finalResult);
1115           _errorDetails=msg;
1116           throw Exception(msg);
1117         }
1118
1119       try
1120       {
1121           int pos(0);
1122           for(std::list<OutputPort *>::iterator iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++, pos++)
1123             {
1124               OutputPyPort *p=(OutputPyPort *)*iter;
1125               DEBTRACE( "port name: " << p->getName() );
1126               DEBTRACE( "port kind: " << p->edGetType()->kind() );
1127               DEBTRACE( "port pos : " << pos );
1128               if(PyTuple_Check(finalResult))
1129                 ob=PyTuple_GetItem(finalResult,pos) ;
1130               else
1131                 ob=finalResult;
1132               DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1133               p->put(ob);
1134             }
1135           Py_DECREF(finalResult);
1136       }
1137       catch(ConversionException& ex)
1138       {
1139           Py_DECREF(finalResult);
1140           _errorDetails=ex.what();
1141           throw;
1142       }
1143   }
1144
1145   DEBTRACE( "++++++++++++++ ENDOF PyFuncNode::executeRemote: " << getName() << " ++++++++++++++++++++" );
1146 }
1147
1148 void PyFuncNode::executeLocal()
1149 {
1150   DEBTRACE( "++++++++++++++ PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
1151
1152   int pos=0;
1153   PyObject* ob;
1154   if(!_pyfunc)throw Exception("PyFuncNode badly loaded");
1155   {
1156       AutoGIL agil;
1157       DEBTRACE( "---------------PyFuncNode::inputs---------------" );
1158       PyObject* args = PyTuple_New(getNumberOfInputPorts()) ;
1159       list<InputPort *>::iterator iter2;
1160       for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++)
1161         {
1162           InputPyPort *p=(InputPyPort *)*iter2;
1163           DEBTRACE( "port name: " << p->getName() );
1164           DEBTRACE( "port kind: " << p->edGetType()->kind() );
1165           ob=p->getPyObj();
1166 #ifdef _DEVDEBUG_
1167           PyObject_Print(ob,stderr,Py_PRINT_RAW);
1168           cerr << endl;
1169 #endif
1170           DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1171           Py_INCREF(ob);
1172           PyTuple_SetItem(args,pos,ob);
1173           DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1174           pos++;
1175         }
1176       DEBTRACE( "---------------End PyFuncNode::inputs---------------" );
1177
1178       DEBTRACE( "----------------PyFuncNode::calculation---------------" );
1179 #ifdef _DEVDEBUG_
1180       PyObject_Print(_pyfunc,stderr,Py_PRINT_RAW);
1181       cerr << endl;
1182       PyObject_Print(args,stderr,Py_PRINT_RAW);
1183       cerr << endl;
1184 #endif
1185       DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
1186       PyObject* result = PyObject_CallObject( _pyfunc , args ) ;
1187       DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt );
1188       Py_DECREF(args);
1189       fflush(stdout);
1190       fflush(stderr);
1191       if(result == NULL)
1192         {
1193           _errorDetails="";
1194           PyObject* new_stderr = newPyStdOut(_errorDetails);
1195           PySys_SetObject((char*)"stderr", new_stderr);
1196           std::ostringstream stream;
1197           stream << "/tmp/PythonNode_";
1198           stream << getpid();
1199           ofstream errorfile(stream.str().c_str());
1200           if (errorfile.is_open())
1201             {
1202               errorfile << _script;
1203               errorfile.close();
1204             }
1205           PyErr_Print();
1206           PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
1207           Py_DECREF(new_stderr);
1208           throw Exception("Error during execution");
1209         }
1210       DEBTRACE( "----------------End PyFuncNode::calculation---------------" );
1211
1212       DEBTRACE( "-----------------PyFuncNode::outputs-----------------" );
1213       int nres=1;
1214       if(result == Py_None)
1215         nres=0;
1216       else if(PyTuple_Check(result))
1217         nres=PyTuple_Size(result);
1218
1219       if(getNumberOfOutputPorts() != nres)
1220         {
1221           std::string msg="Number of output arguments : Mismatch between definition and execution";
1222           Py_DECREF(result);
1223           _errorDetails=msg;
1224           throw Exception(msg);
1225         }
1226
1227       pos=0;
1228 #ifdef _DEVDEBUG_
1229       PyObject_Print(result,stderr,Py_PRINT_RAW);
1230       cerr << endl;
1231 #endif
1232       list<OutputPort *>::iterator iter;
1233       try
1234       {
1235           for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++)
1236             {
1237               OutputPyPort *p=(OutputPyPort *)*iter;
1238               DEBTRACE( "port name: " << p->getName() );
1239               DEBTRACE( "port kind: " << p->edGetType()->kind() );
1240               DEBTRACE( "port pos : " << pos );
1241               if(PyTuple_Check(result))ob=PyTuple_GetItem(result,pos) ;
1242               else ob=result;
1243               DEBTRACE( "ob refcnt: " << ob->ob_refcnt );
1244 #ifdef _DEVDEBUG_
1245               PyObject_Print(ob,stderr,Py_PRINT_RAW);
1246               cerr << endl;
1247 #endif
1248               p->put(ob);
1249               pos++;
1250             }
1251       }
1252       catch(ConversionException& ex)
1253       {
1254           Py_DECREF(result);
1255           _errorDetails=ex.what();
1256           throw;
1257       }
1258       DEBTRACE( "-----------------End PyFuncNode::outputs-----------------" );
1259       Py_DECREF(result);
1260   }
1261   DEBTRACE( "++++++++++++++ End PyFuncNode::execute: " << getName() << " ++++++++++++++++++++" );
1262 }
1263
1264 Node *PyFuncNode::simpleClone(ComposedNode *father, bool editionOnly) const
1265 {
1266   return new PyFuncNode(*this,father);
1267 }
1268
1269 void PyFuncNode::createRemoteAdaptedPyInterpretor(Engines::Container_ptr objContainer)
1270 {
1271   if(!CORBA::is_nil(_pynode))
1272     _pynode->UnRegister();
1273   _pynode=objContainer->createPyNode(getName().c_str(),getScript().c_str());
1274 }
1275
1276 Engines::PyNodeBase_var PyFuncNode::retrieveDftRemotePyInterpretorIfAny(Engines::Container_ptr objContainer) const
1277 {
1278   Engines::PyNode_var ret(objContainer->getDefaultPyNode(getName().c_str()));
1279   if(!CORBA::is_nil(ret))
1280     {
1281       ret->Register();
1282     }
1283   return Engines::PyNodeBase::_narrow(ret);
1284 }
1285
1286 void PyFuncNode::assignRemotePyInterpretor(Engines::PyNodeBase_var remoteInterp)
1287 {
1288   if(!CORBA::is_nil(_pynode))
1289     {
1290       Engines::PyNode_var tmpp(Engines::PyNode::_narrow(remoteInterp));
1291       if(_pynode->_is_equivalent(tmpp))
1292         return ;
1293     }
1294   if(!CORBA::is_nil(_pynode))
1295     _pynode->UnRegister();
1296   _pynode=Engines::PyNode::_narrow(remoteInterp);
1297 }
1298
1299 Engines::PyNodeBase_var PyFuncNode::getRemoteInterpreterHandle()
1300 {
1301   return Engines::PyNodeBase::_narrow(_pynode);
1302 }
1303
1304 //! Create a new node of same type with a given name
1305 PyFuncNode* PyFuncNode::cloneNode(const std::string& name)
1306 {
1307   PyFuncNode* n=new PyFuncNode(name);
1308   n->setScript(_script);
1309   n->setFname(_fname);
1310   list<InputPort *>::iterator iter;
1311   for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++)
1312     {
1313       InputPyPort *p=(InputPyPort *)*iter;
1314       n->edAddInputPort(p->getName(),p->edGetType());
1315     }
1316   list<OutputPort *>::iterator iter2;
1317   for(iter2 = _setOfOutputPort.begin(); iter2 != _setOfOutputPort.end(); iter2++)
1318     {
1319       OutputPyPort *p=(OutputPyPort *)*iter2;
1320       n->edAddOutputPort(p->getName(),p->edGetType());
1321     }
1322   return n;
1323 }
1324
1325 std::string PyFuncNode::getContainerLog()
1326 {
1327   return PythonEntry::GetContainerLog(_mode,_container,this);
1328 }
1329
1330 void PyFuncNode::shutdown(int level)
1331 {
1332   DEBTRACE("PyFuncNode::shutdown " << level);
1333   if(_mode=="local")return;
1334   if(_container)
1335     {
1336       if(!CORBA::is_nil(_pynode)) _pynode->UnRegister();
1337       _pynode=Engines::PyNode::_nil();
1338       _container->shutdown(level);
1339     }
1340 }
1341