PropertyPythonObject.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 #endif
00028 
00029 #include "PropertyPythonObject.h"
00030 #include "DocumentObjectPy.h"
00031 #include "DocumentObject.h"
00032 #include <Base/Base64.h>
00033 #include <Base/Writer.h>
00034 #include <Base/Reader.h>
00035 #include <Base/Console.h>
00036 #include <Base/Interpreter.h>
00037 #include <iostream>
00038 
00039 using namespace App;
00040 
00041 
00042 TYPESYSTEM_SOURCE(App::PropertyPythonObject , App::Property);
00043 
00044 PropertyPythonObject::PropertyPythonObject()
00045 {
00046 }
00047 
00048 PropertyPythonObject::~PropertyPythonObject()
00049 {
00050     // this is needed because the release of the pickled object may need the
00051     // GIL. Thus, we grab the GIL and replace the pickled with an empty object
00052     Base::PyGILStateLocker lock;
00053     this->object = Py::Object();
00054 }
00055 
00056 void PropertyPythonObject::setValue(Py::Object o)
00057 {
00058     aboutToSetValue();
00059     this->object = o;
00060     hasSetValue();
00061 }
00062 
00063 Py::Object PropertyPythonObject::getValue() const
00064 {
00065     return object;
00066 }
00067 
00068 PyObject *PropertyPythonObject::getPyObject(void)
00069 {
00070     return Py::new_reference_to(this->object);
00071 }
00072 
00073 void PropertyPythonObject::setPyObject(PyObject * obj)
00074 {
00075     aboutToSetValue();
00076     this->object = obj;
00077     hasSetValue();
00078 }
00079 
00080 std::string PropertyPythonObject::toString() const
00081 {
00082     std::string repr;
00083     Base::PyGILStateLocker lock;
00084     try {
00085         Py::Module pickle(PyImport_ImportModule("cPickle"),true);
00086         Py::Callable method(pickle.getAttr(std::string("dumps")));
00087         Py::Tuple args(1);
00088         args.setItem(0, this->object);
00089         Py::Object res = method.apply(args);
00090         Py::String str(res);
00091         repr = str.as_std_string();
00092     }
00093     catch (Py::Exception&) {
00094         Base::PyException e; // extract the Python error text
00095         Base::Console().Warning("PropertyPythonObject::toString: %s\n", e.what());
00096     }
00097 
00098     return repr;
00099 }
00100 
00101 void PropertyPythonObject::fromString(const std::string& repr)
00102 {
00103     Base::PyGILStateLocker lock;
00104     try {
00105         Py::Module pickle(PyImport_ImportModule("cPickle"),true);
00106         Py::Callable method(pickle.getAttr(std::string("loads")));
00107         Py::Tuple args(1);
00108         args.setItem(0, Py::String(repr));
00109         Py::Object res = method.apply(args);
00110         this->object = res;
00111     }
00112     catch (Py::Exception&) {
00113         Base::PyException e; // extract the Python error text
00114         Base::Console().Warning("PropertyPythonObject::fromString: %s\n", e.what());
00115     }
00116 }
00117 
00118 std::string PropertyPythonObject::encodeValue(const std::string& str) const
00119 {
00120     std::string tmp;
00121     for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
00122         if (*it == '<')
00123             tmp += "&lt;";
00124         else if (*it == '"')
00125             tmp += "&quot;";
00126         else if (*it == '&')
00127             tmp += "&amp;";
00128         else if (*it == '>')
00129             tmp += "&gt";
00130         else if (*it == '\n')
00131             tmp += "\\n";
00132         else
00133             tmp += *it;
00134     }
00135 
00136     return tmp;
00137 }
00138 
00139 std::string PropertyPythonObject::decodeValue(const std::string& str) const
00140 {
00141     std::string tmp;
00142     for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
00143         if (*it == '\\') {
00144             ++it;
00145             if (it != str.end() && *it == 'n') {
00146                 tmp += '\n';
00147             }
00148         }
00149         else
00150             tmp += *it;
00151     }
00152 
00153     return tmp;
00154 }
00155 
00156 void PropertyPythonObject::saveObject(Base::Writer &writer) const
00157 {
00158     Base::PyGILStateLocker lock;
00159     try {
00160         PropertyContainer* parent = this->getContainer();
00161         if (parent->isDerivedFrom(Base::Type::fromName("App::DocumentObject"))) {
00162             if (this->object.hasAttr("__object__")) {
00163                 writer.Stream() << " object=\"yes\"";
00164             }
00165         }
00166         if (parent->isDerivedFrom(Base::Type::fromName("Gui::ViewProvider"))) {
00167             if (this->object.hasAttr("__vobject__")) {
00168                 writer.Stream() << " vobject=\"yes\"";
00169             }
00170         }
00171     }
00172     catch (Py::Exception& e) {
00173         e.clear();
00174     }
00175 }
00176 
00177 void PropertyPythonObject::restoreObject(Base::XMLReader &reader)
00178 {
00179     Base::PyGILStateLocker lock;
00180     try {
00181         PropertyContainer* parent = this->getContainer();
00182         if (reader.hasAttribute("object")) {
00183             if (strcmp(reader.getAttribute("object"),"yes") == 0) {
00184                 Py::Object obj = Py::asObject(parent->getPyObject());
00185                 this->object.setAttr("__object__", obj);
00186             }
00187         }
00188         if (reader.hasAttribute("vobject")) {
00189             if (strcmp(reader.getAttribute("vobject"),"yes") == 0) {
00190                 Py::Object obj = Py::asObject(parent->getPyObject());
00191                 this->object.setAttr("__vobject__", obj);
00192             }
00193         }
00194     }
00195     catch (Py::Exception& e) {
00196         e.clear();
00197     }
00198     catch (const Base::Exception& e) {
00199         Base::Console().Error("%s\n",e.what());
00200     }
00201     catch (...) {
00202         Base::Console().Error("Critical error in PropertyPythonObject::restoreObject\n");
00203     }
00204 }
00205 
00206 void PropertyPythonObject::Save (Base::Writer &writer) const
00207 {
00208     //if (writer.isForceXML()) {
00209         std::string repr = this->toString();
00210         repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size());
00211         std::string val = /*encodeValue*/(repr);
00212         writer.Stream() << writer.ind() << "<Python value=\"" << val
00213                         <<"\" encoded=\"yes\"";
00214         saveObject(writer);
00215         writer.Stream() << "/>" << std::endl;
00216     //}
00217     //else {
00218     //    writer.Stream() << writer.ind() << "<Python file=\"" << 
00219     //    writer.addFile("pickle", this) << "\"/>" << std::endl;
00220     //}
00221 }
00222 
00223 void PropertyPythonObject::Restore(Base::XMLReader &reader)
00224 {
00225     reader.readElement("Python");
00226     if (reader.hasAttribute("file")) {
00227         std::string file(reader.getAttribute("file"));
00228         reader.addFile(file.c_str(),this);
00229     }
00230     else {
00231         std::string buffer = reader.getAttribute("value");
00232         if (reader.hasAttribute("encoded") &&
00233             strcmp(reader.getAttribute("encoded"),"yes") == 0) {
00234             buffer = Base::base64_decode(buffer);
00235         }
00236         else {
00237             buffer = decodeValue(buffer);
00238         }
00239 
00240         aboutToSetValue();
00241         this->fromString(buffer);
00242         restoreObject(reader);
00243         hasSetValue();
00244     }
00245 }
00246 
00247 void PropertyPythonObject::SaveDocFile (Base::Writer &writer) const
00248 {
00249     std::string buffer = this->toString();
00250     for (std::string::iterator it = buffer.begin(); it != buffer.end(); ++it)
00251         writer.Stream().put(*it);
00252 }
00253 
00254 void PropertyPythonObject::RestoreDocFile(Base::Reader &reader)
00255 {
00256     aboutToSetValue();
00257     std::string buffer;
00258     char c;
00259     while (reader.get(c)) {
00260         buffer.push_back(c);
00261     }
00262     this->fromString(buffer);
00263     hasSetValue();
00264 }
00265 
00266 unsigned int PropertyPythonObject::getMemSize (void) const
00267 {
00268     return sizeof(Py::Object);
00269 }
00270 
00271 Property *PropertyPythonObject::Copy(void) const
00272 {
00273     PropertyPythonObject *p = new PropertyPythonObject();
00274     p->object = this->object;
00275     return p;
00276 }
00277 
00278 void PropertyPythonObject::Paste(const Property &from)
00279 {
00280     if (from.getTypeId() == PropertyPythonObject::getClassTypeId()) {
00281         aboutToSetValue();
00282         this->object = static_cast<const PropertyPythonObject&>(from).object;
00283         hasSetValue();
00284     }
00285 }

Generated on Wed Nov 23 19:00:31 2011 for FreeCAD by  doxygen 1.6.1