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