Salome HOME
typo-fix by Kunda
[modules/kernel.git] / src / SALOMESDS / SALOMESDS_PickelizedPyObjServer.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
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 // Author : Anthony GEAY (EDF R&D)
20
21 #include "SALOMESDS_PickelizedPyObjServer.hxx"
22 #include "SALOMESDS_DataScopeServer.hxx"
23 #include "SALOMESDS_Exception.hxx"
24
25 #include <iostream>
26 #include <sstream>
27
28 using namespace SALOMESDS;
29
30 PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):BasicDataServer(father,varName),_self(0)
31 {
32   setSerializedContentInternal(value);
33 }
34
35 //! obj is consumed
36 PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):BasicDataServer(father,varName),_self(0)
37 {
38   setNewPyObj(obj);
39 }
40
41 PickelizedPyObjServer::~PickelizedPyObjServer()
42 {
43   Py_XDECREF(_self);
44 }
45
46 /*!
47  * Called remotely -> to protect against throw
48  */
49 SALOME::ByteVec *PickelizedPyObjServer::fetchSerializedContent()
50 {
51   Py_XINCREF(_self);//because pickelize consume _self
52   return FromCppToByteSeq(pickelize(_self));
53 }
54
55 bool PickelizedPyObjServer::isDict()
56 {
57   if(PyDict_Check(_self))
58     return true;
59   else
60     return false;
61 }
62
63 void PickelizedPyObjServer::checkKeyNotAlreadyPresent(PyObject *key)
64 {
65   checkKeyPresence(key,false);
66 }
67
68 void PickelizedPyObjServer::checkKeyPresent(PyObject *key)
69 {
70   checkKeyPresence(key,true);
71 }
72
73 void PickelizedPyObjServer::addKeyValueHard(PyObject *key, PyObject *value)
74 {
75   std::ostringstream oss; oss << "PickelizedPyObjServer::addKeyValueHard : var \"" << getVarNameCpp() << "\" is not permitted to alter its value !";
76   throw Exception(oss.str());
77 }
78
79 void PickelizedPyObjServer::removeKeyInVarErrorIfNotAlreadyExisting(PyObject *key)
80 {
81   std::ostringstream oss; oss << "PickelizedPyObjServer::removeKeyInVarErrorIfNotAlreadyExisting : var \"" << getVarNameCpp() << "\" is not permitted to alter its value !";
82   throw Exception(oss.str());
83 }
84
85 void PickelizedPyObjServer::FromByteSeqToCpp(const SALOME::ByteVec& bsToBeConv, std::string& ret)
86 {
87   std::size_t sz(bsToBeConv.length());
88   ret.resize(sz,' ');
89   char *buf(const_cast<char *>(ret.c_str()));
90   for(std::size_t i=0;i<sz;i++)
91     buf[i]=bsToBeConv[i];
92 }
93
94 void PickelizedPyObjServer::FromCppToByteSeq(const std::string& strToBeConv, SALOME::ByteVec& ret)
95 {
96   const char *buf(strToBeConv.c_str());
97   std::size_t sz(strToBeConv.size());
98   ret.length(sz);
99   for(std::size_t i=0;i<sz;i++)
100     ret[i]=buf[i];
101 }
102
103 SALOME::ByteVec *PickelizedPyObjServer::FromCppToByteSeq(const std::string& strToBeConv)
104 {
105   SALOME::ByteVec *ret(new SALOME::ByteVec);
106   FromCppToByteSeq(strToBeConv,*ret);
107   return ret;
108 }
109
110 //! New reference returned
111 PyObject *PickelizedPyObjServer::GetPyObjFromPickled(const std::string& pickledData, DataScopeServerBase *dsb)
112 {
113   std::size_t sz(pickledData.size());
114   PyObject *pickledDataPy(PyString_FromStringAndSize(NULL,sz));// agy : do not use PyString_FromString because std::string hides a vector of byte.
115   char *buf(PyString_AsString(pickledDataPy));// this buf can be used thanks to python documentation.
116   const char *inBuf(pickledData.c_str());
117   std::copy(inBuf,inBuf+sz,buf);
118   PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"loads"));
119   PyObject *args(PyTuple_New(1)); PyTuple_SetItem(args,0,pickledDataPy);
120   PyObject *ret(PyObject_CallObject(selfMeth,args));
121   Py_XDECREF(args);
122   Py_XDECREF(selfMeth);
123   return ret;
124 }
125
126 //! New reference returned
127 PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::string& pickledData)
128 {
129   return GetPyObjFromPickled(pickledData,_father);
130 }
131
132 //! New reference returned
133 PyObject *PickelizedPyObjServer::GetPyObjFromPickled(const std::vector<unsigned char>& pickledData, DataScopeServerBase *dsb)
134 {
135   std::size_t sz(pickledData.size());
136   PyObject *pickledDataPy(PyString_FromStringAndSize(NULL,sz));// agy : do not use PyString_FromString because std::string hides a vector of byte.
137   char *buf(PyString_AsString(pickledDataPy));// this buf can be used thanks to python documentation.
138   const unsigned char *inBuf(&pickledData[0]);
139   std::copy(inBuf,inBuf+sz,buf);
140   PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"loads"));
141   PyObject *args(PyTuple_New(1)); PyTuple_SetItem(args,0,pickledDataPy);
142   PyObject *ret(PyObject_CallObject(selfMeth,args));
143   Py_XDECREF(args);
144   Py_XDECREF(selfMeth);
145   return ret;
146 }
147
148 //! New reference returned
149 PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::vector<unsigned char>& pickledData)
150 {
151   return GetPyObjFromPickled(pickledData,_father);
152 }
153
154 //! obj is consumed by this method.
155 std::string PickelizedPyObjServer::Pickelize(PyObject *obj, DataScopeServerBase *dsb)
156 {
157   PyObject *args(PyTuple_New(2));
158   PyTuple_SetItem(args,0,obj);
159   PyTuple_SetItem(args,1,PyInt_FromLong(2));// because "assert(cPickle.HIGHEST_PROTOCOL is 2)"
160   PyObject *selfMeth(PyObject_GetAttrString(dsb->getPickler(),"dumps"));
161   PyObject *retPy(PyObject_CallObject(selfMeth,args));
162   Py_XDECREF(selfMeth);
163   Py_XDECREF(args);
164   std::size_t sz(PyString_Size(retPy));
165   std::string ret(sz,'\0');
166   const char *buf(PyString_AsString(retPy));
167   char *inBuf(const_cast<char *>(ret.c_str()));
168   for(std::size_t i=0;i<sz;i++)
169     inBuf[i]=buf[i];
170   Py_XDECREF(retPy);
171   return ret;
172 }
173
174 //! obj is consumed by this method.
175 std::string PickelizedPyObjServer::pickelize(PyObject *obj)
176 {
177   return Pickelize(obj,_father);
178 }
179
180 //! obj is consumed by this method.
181 void PickelizedPyObjServer::setNewPyObj(PyObject *obj)
182 {
183   if(!obj)
184     throw Exception("PickelizedPyObjServer::setNewPyObj : trying to assign a NULL pyobject in this !");
185   if(obj==_self)
186     return ;
187   if(_self)
188     {
189       PyObject *selfType(PyObject_Type(_self));
190       if(PyObject_IsInstance(obj,selfType)!=1)
191         {
192           Py_XDECREF(obj);
193           Py_XDECREF(selfType);
194           throw Exception("PickelizedPyObjServer::setNewPyObj : type of new object is not the same than those previously set !");
195         }
196       else
197         Py_XDECREF(selfType);
198     }
199   Py_XDECREF(_self);
200   _self=obj;
201 }
202
203 void PickelizedPyObjServer::setSerializedContentInternal(const SALOME::ByteVec& newValue)
204 {
205   std::string data;
206   FromByteSeqToCpp(newValue,data);
207   setNewPyObj(getPyObjFromPickled(data));
208 }
209
210 PyObject *PickelizedPyObjServer::CreateDftObjFromType(PyObject *globals, const std::string& typeName)
211 {
212   PyObject *builtins(PyDict_GetItemString(globals,"__builtins__"));
213   if(!builtins)
214     throw Exception("PickelizedPyObjServer constructor : no __builtins__ in globals !");
215   PyObject *builtins2(PyModule_GetDict(builtins));
216   if(!builtins2)
217     throw Exception("PickelizedPyObjServer constructor : internal error fail to invoke __dict__ on __builtins__ !");
218   PyObject *tmp(PyDict_GetItemString(builtins2,typeName.c_str()));
219   if(!tmp)
220     {
221       std::ostringstream oss; oss << "PickelizedPyObjServer::CreateDftObjFromType : Invalid type name \"" << typeName << "\" !";
222       throw Exception(oss.str());
223     }
224   PyObject *args(PyTuple_New(0));
225   PyObject *ret(PyObject_CallObject(tmp,args));
226   Py_XDECREF(args);
227   return ret;
228 }
229
230 void PickelizedPyObjServer::checkKeyPresence(PyObject *key, bool presence)
231 {
232   if(!isDict())
233     throw Exception("PickelizedPyObjServer::checkKeyPresence : not a dict !");
234   PyObject *selfMeth(PyObject_GetAttrString(_self,"__contains__"));//new ref
235   PyObject *args(PyTuple_New(1));
236   PyTuple_SetItem(args,0,key); Py_XINCREF(key);// key is stolen by PyTuple_SetItem
237   PyObject *retPy(PyObject_CallObject(selfMeth,args));
238   Py_XDECREF(args);
239   Py_XDECREF(selfMeth);
240   //
241   if(retPy!=Py_False && retPy!=Py_True)
242     throw Exception("PickelizedPyObjServer::checkKeyPresence : unexpected return of dict.__contains__ !");
243   if(!presence)
244     {
245       if(retPy==Py_True)
246         throw Exception("PickelizedPyObjServer::checkKeyPresence : key is already present and it should not !");
247     }
248   else
249     {
250       if(retPy==Py_False)
251         throw Exception("PickelizedPyObjServer::checkKeyPresence : key is not present and it should !");
252     }
253   Py_XDECREF(retPy);
254 }
255
256 PickelizedPyObjServerModifiable::PickelizedPyObjServerModifiable(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value)
257 {
258 }
259
260 PickelizedPyObjServerModifiable::PickelizedPyObjServerModifiable(DataScopeServerBase *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj)
261 {
262 }
263
264 void PickelizedPyObjServerModifiable::addKeyValueErrorIfAlreadyExisting(PyObject *key, PyObject *value)
265 {
266   checkKeyNotAlreadyPresent(key);
267   bool isOK(PyDict_SetItem(_self,key,value)==0);
268   if(!isOK)
269     throw Exception("PickelizedPyObjServerModifiable::addKeyValueErrorIfAlreadyExisting : error when trying to add key,value to dict !");
270 }
271
272 void PickelizedPyObjServerModifiable::removeKeyInVarErrorIfNotAlreadyExisting(PyObject *key)
273 {
274   checkKeyPresent(key);
275   if(PyDict_DelItem(_self,key)!=0)
276     throw Exception("PickelizedPyObjServerModifiable::removeKeyInVarErrorIfNotAlreadyExisting : error during deletion of key in dict !");
277 }