diff --git a/src/App/PropertyContainerPy.xml b/src/App/PropertyContainerPy.xml
index cbf300ae46..112ad67a08 100644
--- a/src/App/PropertyContainerPy.xml
+++ b/src/App/PropertyContainerPy.xml
@@ -57,6 +57,23 @@ If the list contains 'Hidden' then the item even doesn't appear in the property
Return the documentation string of the property of this class.
+
+
+ Dumps the content of the property, both the XML representation as well as the additional datafiles
+ required, into a byte representation. It will be returned as byte array.
+ dumpPropertyContent(propertyname) -- returns a byte array with full content
+ dumpPropertyContent(propertyname, [Compression=1-9]) -- Sets the data compression from 0 (no) to 9 (max)
+
+
+
+
+
+ Restore the content of given property from a byte representation as stored by \"dumpContent\".
+ It could be restored from any python object implementing the buffer protocol.
+ restorePropertyContent(propertyname, buffer) -- restores from the given byte array
+
+
+
A list of all property names
diff --git a/src/App/PropertyContainerPyImp.cpp b/src/App/PropertyContainerPyImp.cpp
index f50347672f..a07e157651 100644
--- a/src/App/PropertyContainerPyImp.cpp
+++ b/src/App/PropertyContainerPyImp.cpp
@@ -226,6 +226,42 @@ Py::List PropertyContainerPy::getPropertiesList(void) const
return ret;
}
+
+PyObject* PropertyContainerPy::dumpPropertyContent(PyObject *args, PyObject *kwds) {
+
+ int compression = 3;
+ char* property;
+ static char* kwds_def[] = {"Compression",NULL};
+ PyErr_Clear();
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwds_def, &property, &compression)) {
+ return NULL;
+ }
+
+ Property* prop = getPropertyContainerPtr()->getPropertyByName(property);
+ if (!prop) {
+ PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", property);
+ return 0;
+ }
+
+ return prop->dumpToPython(compression);
+}
+
+PyObject* PropertyContainerPy::restorePropertyContent(PyObject *args) {
+
+ PyObject* buffer;
+ char* property;
+ if( !PyArg_ParseTuple(args, "sO", &property, &buffer) )
+ return NULL;
+
+ Property* prop = getPropertyContainerPtr()->getPropertyByName(property);
+ if (!prop) {
+ PyErr_Format(PyExc_AttributeError, "Property container has no property '%s'", property);
+ return 0;
+ }
+
+ return prop->restoreFromPython(buffer);
+}
+
PyObject *PropertyContainerPy::getCustomAttributes(const char* attr) const
{
// search in PropertyList
diff --git a/src/Base/Persistence.cpp b/src/Base/Persistence.cpp
index cd215c4043..ddf52e931f 100644
--- a/src/Base/Persistence.cpp
+++ b/src/Base/Persistence.cpp
@@ -22,6 +22,9 @@
#include "PreCompiled.h"
+#include "Writer.h"
+#include "Reader.h"
+#include "PyObjectBase.h"
#ifndef _PreComp_
#endif
@@ -95,3 +98,102 @@ std::string Persistence::encodeAttribute(const std::string& str)
return tmp;
}
+
+PyObject* Persistence::dumpToPython(int compression) {
+
+ //setup the stream. the in flag is needed to make "read" work^
+ std::stringstream stream(std::stringstream::out | std::stringstream::in | std::stringstream::binary);
+
+ //we need to close the zipstream to get a good result, the only way to do this is to delete the ZipWriter.
+ //Hence the scope...
+ {
+ //create the writer
+ Base::ZipWriter writer(stream);
+ writer.setLevel(compression);
+ writer.putNextEntry("Document.xml");
+ writer.setMode("BinaryBrep");
+
+ //save the content (we need to encapsulte it with xml tags to be able to read single element xmls like happen for properties)
+ writer.Stream() << "" << std::endl;
+ Save(writer);
+ writer.Stream() << "";
+ writer.writeFiles();
+ }
+
+ //build the byte array with correct size
+ if(!stream.seekp(0, stream.end)) {
+ PyErr_SetString(PyExc_IOError, "Unable to find end of stream");
+ return NULL;
+ }
+ std::stringstream::pos_type offset = stream.tellp();
+ if(!stream.seekg(0, stream.beg)) {
+ PyErr_SetString(PyExc_IOError, "Unable to find begin of stream");
+ return NULL;
+ }
+
+ PyObject* ba = PyByteArray_FromStringAndSize(NULL, offset);
+
+ //use the buffer protocol to access the underlying array and write into it
+ Py_buffer buf = Py_buffer();
+ PyObject_GetBuffer(ba, &buf, PyBUF_WRITABLE);
+ try {
+ if(!stream.read((char*)buf.buf, offset)) {
+ PyErr_SetString(PyExc_IOError, "Error copying data into byte array");
+ return NULL;
+ }
+ PyBuffer_Release(&buf);
+ }
+ catch(...) {
+ PyBuffer_Release(&buf);
+ PyErr_SetString(PyExc_IOError, "Error copying data into byte array");
+ return NULL;
+ }
+
+ return ba;
+}
+
+PyObject* Persistence::restoreFromPython(PyObject *buffer) {
+
+ //check if it really is a buffer
+ if( !PyObject_CheckBuffer(buffer) ) {
+ PyErr_SetString(PyExc_TypeError, "Must be a buffer object");
+ return NULL;
+ }
+
+ Py_buffer buf;
+ if(PyObject_GetBuffer(buffer, &buf, PyBUF_SIMPLE) < 0)
+ return NULL;
+
+ if(!PyBuffer_IsContiguous(&buf, 'C')) {
+ PyErr_SetString(PyExc_TypeError, "Buffer must be contiguous");
+ return NULL;
+ }
+
+ try {
+
+ //TODO: this mkes a stupid copy, we should make a stream directly from the buffer
+ std::stringstream stream(std::string((char*)buf.buf, buf.len), std::stringstream::in | std::stringstream::binary);
+
+ zipios::ZipInputStream zipstream(stream);
+ Base::XMLReader reader("", zipstream);
+
+ if (!reader.isValid()) {
+ PyErr_SetString(PyExc_IOError, "Unable to read file");
+ return NULL;
+ }
+
+ reader.readElement("Content");
+ Restore(reader);
+ reader.readFiles(zipstream);
+ }
+ catch (const Base::Exception& e) {
+ PyErr_SetString(PyExc_IOError, e.what());
+ return NULL;
+ }
+ catch (const std::exception& e) {
+ PyErr_SetString(PyExc_IOError, e.what());
+ return NULL;
+ }
+
+ return Py_None;
+}
diff --git a/src/Base/Persistence.h b/src/Base/Persistence.h
index 7bbda4d31a..1ec0c0d81c 100644
--- a/src/Base/Persistence.h
+++ b/src/Base/Persistence.h
@@ -148,6 +148,12 @@ public:
virtual void RestoreDocFile(Reader &/*reader*/);
/// Encodes an attribute upon saving.
static std::string encodeAttribute(const std::string&);
+
+ //dump the persistence data into a python byte array data structure
+ PyObject* dumpToPython(int compression);
+
+ //restore the persistence data from a python data structure that supports the buffer protocol
+ PyObject* restoreFromPython(PyObject*);
};
} //namespace Base
diff --git a/src/Base/PersistencePyImp.cpp b/src/Base/PersistencePyImp.cpp
index 890773996b..823631b9ad 100644
--- a/src/Base/PersistencePyImp.cpp
+++ b/src/Base/PersistencePyImp.cpp
@@ -23,7 +23,6 @@
#include "PreCompiled.h"
#include "Writer.h"
-#include "Reader.h"
#include "Persistence.h"
// inclution of the generated files (generated By PersitancePy.xml)
@@ -63,53 +62,7 @@ PyObject* PersistencePy::dumpContent(PyObject *args, PyObject *kwds) {
return NULL;
}
- //setup the streams
- std::stringstream stream(std::stringstream::out | std::stringstream::in | std::stringstream::binary);
-
- //we need to close the zipstream to get a good result, the only way to do this is to delete the ZipWriter.
- //Hence the scope...
- {
- //create the writer
- Base::ZipWriter writer(stream);
- writer.setLevel(compression);
- writer.putNextEntry("Document.xml");
- writer.setMode("BinaryBrep");
-
- //save the content
- getPersistencePtr()->Save(writer);
- writer.writeFiles();
- }
-
- //build the byte array with correct size
- if(!stream.seekp(0, stream.end)) {
- PyErr_SetString(PyExc_IOError, "Unable to find end of stream");
- return NULL;
- }
- std::stringstream::pos_type offset = stream.tellp();
- if(!stream.seekg(0, stream.beg)) {
- PyErr_SetString(PyExc_IOError, "Unable to find begin of stream");
- return NULL;
- }
-
- PyObject* ba = PyByteArray_FromStringAndSize(NULL, offset);
-
- //use the buffer protocol to access the underlying array and write into it
- Py_buffer buf = Py_buffer();
- PyObject_GetBuffer(ba, &buf, PyBUF_WRITABLE);
- try {
- if(!stream.read((char*)buf.buf, offset)) {
- PyErr_SetString(PyExc_IOError, "Error copying data into byte array");
- return NULL;
- }
- PyBuffer_Release(&buf);
- }
- catch(...) {
- PyBuffer_Release(&buf);
- PyErr_SetString(PyExc_IOError, "Error copying data into byte array");
- return NULL;
- }
-
- return ba;
+ return getPersistencePtr()->dumpToPython(compression);
}
PyObject* PersistencePy::restoreContent(PyObject *args) {
@@ -119,46 +72,7 @@ PyObject* PersistencePy::restoreContent(PyObject *args) {
return NULL;
//check if it really is a buffer
- if( !PyObject_CheckBuffer(buffer) ) {
- PyErr_SetString(PyExc_TypeError, "Must be a buffer object");
- return NULL;
- }
-
- Py_buffer buf;
- if(PyObject_GetBuffer(buffer, &buf, PyBUF_SIMPLE) < 0)
- return NULL;
-
- if(!PyBuffer_IsContiguous(&buf, 'C')) {
- PyErr_SetString(PyExc_TypeError, "Buffer must be contiguous");
- return NULL;
- }
-
- try {
-
- //TODO: this mkes a stupid copy, we should make a stream directly from the buffer
- std::stringstream stream(std::string((char*)buf.buf, buf.len), std::stringstream::in | std::stringstream::binary);
-
- zipios::ZipInputStream zipstream(stream);
- Base::XMLReader reader("", zipstream);
-
- if (!reader.isValid()) {
- PyErr_SetString(PyExc_IOError, "Unable to read file");
- return NULL;
- }
-
- getPersistencePtr()->Restore(reader);
- reader.readFiles(zipstream);
- }
- catch (const Base::Exception& e) {
- PyErr_SetString(PyExc_IOError, e.what());
- return NULL;
- }
- catch (const std::exception& e) {
- PyErr_SetString(PyExc_IOError, e.what());
- return NULL;
- }
-
- return Py_None;
+ return getPersistencePtr()->restoreFromPython(buffer);
}
PyObject *PersistencePy::getCustomAttributes(const char*) const