Version: 8.3.0
PyStdout.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 "PyStdout.hxx"
21 #include "Exception.hxx"
22 #include "AutoGIL.hxx"
23 
24 #include <structmember.h>
25 
26 #include <string>
27 #include <sstream>
28 
29 #ifdef WIN32
30 #include <process.h>
31 #define getpid _getpid
32 #endif
33 
34 namespace YACS
35 {
36  namespace ENGINE
37  {
38 
39  typedef struct {
40  PyObject_HEAD
41  int softspace;
42  std::string *out;
43  } PyStdOut;
44 
45 static void
47 {
48  PyObject_Del(self);
49 }
50 
51 static PyObject *
52 PyStdOut_write(PyStdOut *self, PyObject *args)
53 {
54  char *c;
55  int l;
56  if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
57  return NULL;
58 
59  //std::cerr << c ;
60  *(self->out)=*(self->out)+std::string(c);
61 
62  Py_INCREF(Py_None);
63  return Py_None;
64 }
65 
66 static PyMethodDef PyStdOut_methods[] = {
67  {"write", (PyCFunction)PyStdOut_write, METH_VARARGS,
68  PyDoc_STR("write(string) -> None")},
69  {NULL, NULL} /* sentinel */
70 };
71 
72 static PyMemberDef PyStdOut_memberlist[] = {
73  {(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
74  (char*)"flag indicating that a space needs to be printed; used by print"},
75  {NULL} /* Sentinel */
76 };
77 
78 static PyTypeObject PyStdOut_Type = {
79  /* The ob_type field must be initialized in the module init function
80  * to be portable to Windows without using C++. */
81  PyObject_HEAD_INIT(NULL)
82  0, /*ob_size*/
83  "PyOut", /*tp_name*/
84  sizeof(PyStdOut), /*tp_basicsize*/
85  0, /*tp_itemsize*/
86  /* methods */
87  (destructor)PyStdOut_dealloc, /*tp_dealloc*/
88  0, /*tp_print*/
89  0, /*tp_getattr*/
90  0, /*tp_setattr*/
91  0, /*tp_compare*/
92  0, /*tp_repr*/
93  0, /*tp_as_number*/
94  0, /*tp_as_sequence*/
95  0, /*tp_as_mapping*/
96  0, /*tp_hash*/
97  0, /*tp_call*/
98  0, /*tp_str*/
99  PyObject_GenericGetAttr, /*tp_getattro*/
100  /* softspace is writable: we must supply tp_setattro */
101  PyObject_GenericSetAttr, /* tp_setattro */
102  0, /*tp_as_buffer*/
103  Py_TPFLAGS_DEFAULT, /*tp_flags*/
104  0, /*tp_doc*/
105  0, /*tp_traverse*/
106  0, /*tp_clear*/
107  0, /*tp_richcompare*/
108  0, /*tp_weaklistoffset*/
109  0, /*tp_iter*/
110  0, /*tp_iternext*/
111  PyStdOut_methods, /*tp_methods*/
112  PyStdOut_memberlist, /*tp_members*/
113  0, /*tp_getset*/
114  0, /*tp_base*/
115  0, /*tp_dict*/
116  0, /*tp_descr_get*/
117  0, /*tp_descr_set*/
118  0, /*tp_dictoffset*/
119  0, /*tp_init*/
120  0, /*tp_alloc*/
121  0, /*tp_new*/
122  0, /*tp_free*/
123  0, /*tp_is_gc*/
124 };
125 
126 
127 #define PyStdOut_Check(v) ((v)->ob_type == &PyStdOut_Type)
128 
129 PyObject * newPyStdOut( std::string& out )
130 {
131  PyStdOut *self;
132  self = PyObject_New(PyStdOut, &PyStdOut_Type);
133  if (self == NULL)
134  return NULL;
135  self->softspace = 0;
136  self->out=&out;
137  return (PyObject*)self;
138 }
139 
140 PyObject *evalPy(const std::string& funcName, const std::string& strToEval)
141 {
142  std::ostringstream oss0; oss0 << "def " << funcName << "():\n";
143  std::string::size_type i0(0);
144  while(i0<strToEval.length() && i0!=std::string::npos)
145  {
146  std::string::size_type i2(strToEval.find('\n',i0));
147  std::string::size_type lgth(i2!=std::string::npos?i2-i0:std::string::npos);
148  std::string part(strToEval.substr(i0,lgth));
149  if(!part.empty())
150  oss0 << " " << part << "\n";
151  i0=i2!=std::string::npos?i2+1:std::string::npos;
152  }
153  std::string zeCodeStr(oss0.str());
154  std::ostringstream stream;
155  stream << "/tmp/PythonNode_";
156  stream << getpid();
157  AutoPyRef context(PyDict_New());
158  PyDict_SetItemString( context, "__builtins__", PyEval_GetBuiltins() );
159  AutoPyRef code(Py_CompileString(zeCodeStr.c_str(), "kkkk", Py_file_input));
160  if(code.isNull())
161  {
162  std::string errorDetails;
163  PyObject *new_stderr(newPyStdOut(errorDetails));
164  PySys_SetObject((char*)"stderr", new_stderr);
165  PyErr_Print();
166  PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
167  Py_DECREF(new_stderr);
168  std::ostringstream oss; oss << "evalPy failed : " << errorDetails;
169  throw Exception(oss.str());
170  }
171  AutoPyRef res(PyEval_EvalCode(reinterpret_cast<PyCodeObject *>((PyObject *)code),context,context));
172  PyObject *ret(PyDict_GetItemString(context,funcName.c_str())); //borrowed ref
173  if(!ret)
174  throw YACS::Exception("evalPy : Error on returned func !");
175  Py_XINCREF(ret);
176  return ret;
177 }
178 
179 PyObject *evalFuncPyWithNoParams(PyObject *func)
180 {
181  if(!func)
182  throw YACS::Exception("evalFuncPyWithNoParams : input func is NULL !");
183  AutoPyRef args(PyTuple_New(0));
184  AutoPyRef ret(PyObject_CallObject(func,args));
185  if(ret.isNull())
186  throw YACS::Exception("evalFuncPyWithNoParams : ret is null !");
187  return ret.retn();
188 }
189 
190 }
191 }
192