Salome HOME
updated copyright message
[modules/yacs.git] / src / runtime / PyStdout.cxx
1 // Copyright (C) 2006-2023  CEA, EDF
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 "PythonCppUtils.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
46 PyStdOut_dealloc(PyStdOut *self)
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, "s#: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   PyVarObject_HEAD_INIT(NULL, 0)
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   AutoPyRef context(PyDict_New());
155   PyDict_SetItemString( context, "__builtins__", PyEval_GetBuiltins() );
156   AutoPyRef code(Py_CompileString(zeCodeStr.c_str(), "kkkk", Py_file_input));
157   if(code.isNull())
158     {
159       std::string errorDetails;
160       PyObject *new_stderr(newPyStdOut(errorDetails));
161       PySys_SetObject((char*)"stderr", new_stderr);
162       PyErr_Print();
163       PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
164       Py_DECREF(new_stderr);
165       std::ostringstream oss; oss << "evalPy failed : " << errorDetails;
166       throw Exception(oss.str());
167     }
168   AutoPyRef res(PyEval_EvalCode((PyObject *)code,context,context));
169   PyObject *ret(PyDict_GetItemString(context,funcName.c_str())); //borrowed ref
170   if(!ret)
171     throw YACS::Exception("evalPy : Error on returned func !");
172   Py_XINCREF(ret);
173   return ret;
174 }
175
176 PyObject *evalFuncPyWithNoParams(PyObject *func)
177 {
178   if(!func)
179     throw YACS::Exception("evalFuncPyWithNoParams : input func is NULL !");
180   AutoPyRef args(PyTuple_New(0));
181   AutoPyRef ret(PyObject_CallObject(func,args));
182   if(ret.isNull())
183     throw YACS::Exception("evalFuncPyWithNoParams : ret is null !");
184   return ret.retn();
185 }
186
187 }
188 }
189