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