1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony GEAY (EDF R&D)
21 #include "SALOMESDS_PickelizedPyObjServer.hxx"
22 #include "SALOMESDS_DataScopeServer.hxx"
23 #include "SALOMESDS_Exception.hxx"
28 using namespace SALOMESDS;
30 PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):BasicDataServer(father,varName),_self(0)
32 setSerializedContentInternal(value);
36 PickelizedPyObjServer::PickelizedPyObjServer(DataScopeServerBase *father, const std::string& varName, PyObject *obj):BasicDataServer(father,varName),_self(0)
41 PickelizedPyObjServer::~PickelizedPyObjServer()
47 * Called remotely -> to protect against throw
49 SALOME::ByteVec *PickelizedPyObjServer::fetchSerializedContent()
51 Py_XINCREF(_self);//because pickelize consume _self
52 return FromCppToByteSeq(pickelize(_self));
55 bool PickelizedPyObjServer::isDict()
57 if(PyDict_Check(_self))
63 void PickelizedPyObjServer::checkKeyNotAlreadyPresent(PyObject *key)
65 checkKeyPresence(key,false);
68 void PickelizedPyObjServer::checkKeyPresent(PyObject *key)
70 checkKeyPresence(key,true);
73 void PickelizedPyObjServer::addKeyValueHard(PyObject *key, PyObject *value)
75 std::ostringstream oss; oss << "PickelizedPyObjServer::addKeyValueHard : var \"" << getVarNameCpp() << "\" is not permitted to alter its value !";
76 throw Exception(oss.str());
79 void PickelizedPyObjServer::removeKeyInVarErrorIfNotAlreadyExisting(PyObject *key)
81 std::ostringstream oss; oss << "PickelizedPyObjServer::removeKeyInVarErrorIfNotAlreadyExisting : var \"" << getVarNameCpp() << "\" is not permitted to alter its value !";
82 throw Exception(oss.str());
85 void PickelizedPyObjServer::FromByteSeqToCpp(const SALOME::ByteVec& bsToBeConv, std::string& ret)
87 std::size_t sz(bsToBeConv.length());
89 char *buf(const_cast<char *>(ret.c_str()));
90 for(std::size_t i=0;i<sz;i++)
94 void PickelizedPyObjServer::FromCppToByteSeq(const std::string& strToBeConv, SALOME::ByteVec& ret)
96 const char *buf(strToBeConv.c_str());
97 std::size_t sz(strToBeConv.size());
99 for(std::size_t i=0;i<sz;i++)
103 SALOME::ByteVec *PickelizedPyObjServer::FromCppToByteSeq(const std::string& strToBeConv)
105 SALOME::ByteVec *ret(new SALOME::ByteVec);
106 FromCppToByteSeq(strToBeConv,*ret);
110 //! New reference returned
111 PyObject *PickelizedPyObjServer::GetPyObjFromPickled(const std::string& pickledData, DataScopeServerBase *dsb)
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));
122 Py_XDECREF(selfMeth);
126 //! New reference returned
127 PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::string& pickledData)
129 return GetPyObjFromPickled(pickledData,_father);
132 //! New reference returned
133 PyObject *PickelizedPyObjServer::GetPyObjFromPickled(const std::vector<unsigned char>& pickledData, DataScopeServerBase *dsb)
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));
144 Py_XDECREF(selfMeth);
148 //! New reference returned
149 PyObject *PickelizedPyObjServer::getPyObjFromPickled(const std::vector<unsigned char>& pickledData)
151 return GetPyObjFromPickled(pickledData,_father);
154 //! obj is consumed by this method.
155 std::string PickelizedPyObjServer::Pickelize(PyObject *obj, DataScopeServerBase *dsb)
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);
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++)
174 //! obj is consumed by this method.
175 std::string PickelizedPyObjServer::pickelize(PyObject *obj)
177 return Pickelize(obj,_father);
180 //! obj is consumed by this method.
181 void PickelizedPyObjServer::setNewPyObj(PyObject *obj)
184 throw Exception("PickelizedPyObjServer::setNewPyObj : trying to assign a NULL pyobject in this !");
187 if(PyList_Check(obj)==0 && PyDict_Check(obj)==0 && PyTuple_Check(obj)==0 && PyString_Check(obj)==0 && PyInt_Check(obj)==0 && PyBool_Check(obj)==0 && PyFloat_Check(obj)==0 && obj!=Py_None)
188 throw Exception("PickelizedPyObjServer::setNewPyObj : Supported python types are [list,tuple,dict,str,int,bool,float,None] !");
191 PyObject *selfType(PyObject_Type(_self));
192 if(PyObject_IsInstance(obj,selfType)!=1)
195 Py_XDECREF(selfType);
196 throw Exception("PickelizedPyObjServer::setNewPyObj : type of new object is not the same than those previously set !");
199 Py_XDECREF(selfType);
205 void PickelizedPyObjServer::setSerializedContentInternal(const SALOME::ByteVec& newValue)
208 FromByteSeqToCpp(newValue,data);
209 setNewPyObj(getPyObjFromPickled(data));
212 PyObject *PickelizedPyObjServer::CreateDftObjFromType(PyObject *globals, const std::string& typeName)
214 PyObject *builtins(PyDict_GetItemString(globals,"__builtins__"));
216 throw Exception("PickelizedPyObjServer constructor : no __builtins__ in globals !");
217 PyObject *builtins2(PyModule_GetDict(builtins));
219 throw Exception("PickelizedPyObjServer constructor : internal error fail to invoke __dict__ on __builtins__ !");
220 PyObject *tmp(PyDict_GetItemString(builtins2,typeName.c_str()));
223 std::ostringstream oss; oss << "PickelizedPyObjServer::CreateDftObjFromType : Invalid type name \"" << typeName << "\" !";
224 throw Exception(oss.str());
226 PyObject *args(PyTuple_New(0));
227 PyObject *ret(PyObject_CallObject(tmp,args));
232 void PickelizedPyObjServer::checkKeyPresence(PyObject *key, bool presence)
235 throw Exception("PickelizedPyObjServer::checkKeyPresence : not a dict !");
236 PyObject *selfMeth(PyObject_GetAttrString(_self,"__contains__"));//new ref
237 PyObject *args(PyTuple_New(1));
238 PyTuple_SetItem(args,0,key); Py_XINCREF(key);// key is stolen by PyTuple_SetItem
239 PyObject *retPy(PyObject_CallObject(selfMeth,args));
241 Py_XDECREF(selfMeth);
243 if(retPy!=Py_False && retPy!=Py_True)
244 throw Exception("PickelizedPyObjServer::checkKeyPresence : unexpected return of dict.__contains__ !");
248 throw Exception("PickelizedPyObjServer::checkKeyPresence : key is already present and it should not !");
253 throw Exception("PickelizedPyObjServer::checkKeyPresence : key is not present and it should !");
258 PickelizedPyObjServerModifiable::PickelizedPyObjServerModifiable(DataScopeServerBase *father, const std::string& varName, const SALOME::ByteVec& value):PickelizedPyObjServer(father,varName,value)
262 PickelizedPyObjServerModifiable::PickelizedPyObjServerModifiable(DataScopeServerBase *father, const std::string& varName, PyObject *obj):PickelizedPyObjServer(father,varName,obj)
266 void PickelizedPyObjServerModifiable::addKeyValueErrorIfAlreadyExisting(PyObject *key, PyObject *value)
268 checkKeyNotAlreadyPresent(key);
269 bool isOK(PyDict_SetItem(_self,key,value)==0);
271 throw Exception("PickelizedPyObjServerModifiable::addKeyValueErrorIfAlreadyExisting : error when trying to add key,value to dict !");
274 void PickelizedPyObjServerModifiable::removeKeyInVarErrorIfNotAlreadyExisting(PyObject *key)
276 checkKeyPresent(key);
277 if(PyDict_DelItem(_self,key)!=0)
278 throw Exception("PickelizedPyObjServerModifiable::removeKeyInVarErrorIfNotAlreadyExisting : error during deletion of key in dict !");