|
@@ -25,13 +25,6 @@ LightMutex TypedWritable::_bam_writers_lock;
|
|
|
TypeHandle TypedWritable::_type_handle;
|
|
TypeHandle TypedWritable::_type_handle;
|
|
|
TypedWritable* const TypedWritable::Null = (TypedWritable*)0L;
|
|
TypedWritable* const TypedWritable::Null = (TypedWritable*)0L;
|
|
|
|
|
|
|
|
-#ifdef HAVE_PYTHON
|
|
|
|
|
-#include "py_panda.h"
|
|
|
|
|
-#ifndef CPPPARSER
|
|
|
|
|
-extern EXPCL_PANDA_PUTIL Dtool_PyTypedObject Dtool_BamWriter;
|
|
|
|
|
-#endif // CPPPARSER
|
|
|
|
|
-#endif // HAVE_PYTHON
|
|
|
|
|
-
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: TypedWritable::Destructor
|
|
// Function: TypedWritable::Destructor
|
|
|
// Access: Public, Virtual
|
|
// Access: Public, Virtual
|
|
@@ -156,115 +149,6 @@ as_reference_count() {
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#ifdef HAVE_PYTHON
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: TypedWritable::__reduce__
|
|
|
|
|
-// Access: Published
|
|
|
|
|
-// Description: This special Python method is implement to provide
|
|
|
|
|
-// support for the pickle module.
|
|
|
|
|
-//
|
|
|
|
|
-// This hooks into the native pickle and cPickle
|
|
|
|
|
-// modules, but it cannot properly handle
|
|
|
|
|
-// self-referential BAM objects.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-PyObject *TypedWritable::
|
|
|
|
|
-__reduce__(PyObject *self) const {
|
|
|
|
|
- return __reduce_persist__(self, NULL);
|
|
|
|
|
-}
|
|
|
|
|
-#endif // HAVE_PYTHON
|
|
|
|
|
-
|
|
|
|
|
-#ifdef HAVE_PYTHON
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: TypedWritable::__reduce_persist__
|
|
|
|
|
-// Access: Published
|
|
|
|
|
-// Description: This special Python method is implement to provide
|
|
|
|
|
-// support for the pickle module.
|
|
|
|
|
-//
|
|
|
|
|
-// This is similar to __reduce__, but it provides
|
|
|
|
|
-// additional support for the missing persistent-state
|
|
|
|
|
-// object needed to properly support self-referential
|
|
|
|
|
-// BAM objects written to the pickle stream. This hooks
|
|
|
|
|
-// into the pickle and cPickle modules implemented in
|
|
|
|
|
-// direct/src/stdpy.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-PyObject *TypedWritable::
|
|
|
|
|
-__reduce_persist__(PyObject *self, PyObject *pickler) const {
|
|
|
|
|
- // We should return at least a 2-tuple, (Class, (args)): the
|
|
|
|
|
- // necessary class object whose constructor we should call
|
|
|
|
|
- // (e.g. this), and the arguments necessary to reconstruct this
|
|
|
|
|
- // object.
|
|
|
|
|
-
|
|
|
|
|
- // Check that we have a decode_from_bam_stream python method. If not,
|
|
|
|
|
- // we can't use this interface.
|
|
|
|
|
- PyObject *method = PyObject_GetAttrString(self, "decode_from_bam_stream");
|
|
|
|
|
- if (method == NULL) {
|
|
|
|
|
- ostringstream stream;
|
|
|
|
|
- stream << "Cannot pickle objects of type " << get_type() << "\n";
|
|
|
|
|
- string message = stream.str();
|
|
|
|
|
- PyErr_SetString(PyExc_TypeError, message.c_str());
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
- Py_DECREF(method);
|
|
|
|
|
-
|
|
|
|
|
- BamWriter *writer = NULL;
|
|
|
|
|
- if (pickler != NULL) {
|
|
|
|
|
- PyObject *py_writer = PyObject_GetAttrString(pickler, "bamWriter");
|
|
|
|
|
- if (py_writer == NULL) {
|
|
|
|
|
- // It's OK if there's no bamWriter.
|
|
|
|
|
- PyErr_Clear();
|
|
|
|
|
- } else {
|
|
|
|
|
- DTOOL_Call_ExtractThisPointerForType(py_writer, &Dtool_BamWriter, (void **)&writer);
|
|
|
|
|
- Py_DECREF(py_writer);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // First, streamify the object, if possible.
|
|
|
|
|
- string bam_stream;
|
|
|
|
|
- if (!encode_to_bam_stream(bam_stream, writer)) {
|
|
|
|
|
- ostringstream stream;
|
|
|
|
|
- stream << "Could not bamify object of type " << get_type() << "\n";
|
|
|
|
|
- string message = stream.str();
|
|
|
|
|
- PyErr_SetString(PyExc_TypeError, message.c_str());
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Start by getting this class object.
|
|
|
|
|
- PyObject *this_class = PyObject_Type(self);
|
|
|
|
|
- if (this_class == NULL) {
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PyObject *func;
|
|
|
|
|
- if (writer != NULL) {
|
|
|
|
|
- // The modified pickle support: call the "persistent" version of
|
|
|
|
|
- // this function, which receives the unpickler itself as an
|
|
|
|
|
- // additional parameter.
|
|
|
|
|
- func = find_global_decode(this_class, "py_decode_TypedWritable_from_bam_stream_persist");
|
|
|
|
|
- if (func == NULL) {
|
|
|
|
|
- PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_TypedWritable_from_bam_stream_persist()");
|
|
|
|
|
- Py_DECREF(this_class);
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
- // The traditional pickle support: call the non-persistent version
|
|
|
|
|
- // of this function.
|
|
|
|
|
-
|
|
|
|
|
- func = find_global_decode(this_class, "py_decode_TypedWritable_from_bam_stream");
|
|
|
|
|
- if (func == NULL) {
|
|
|
|
|
- PyErr_SetString(PyExc_TypeError, "Couldn't find py_decode_TypedWritable_from_bam_stream()");
|
|
|
|
|
- Py_DECREF(this_class);
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PyObject *result = Py_BuildValue("(O(Os#))", func, this_class, bam_stream.data(), bam_stream.size());
|
|
|
|
|
- Py_DECREF(func);
|
|
|
|
|
- Py_DECREF(this_class);
|
|
|
|
|
- return result;
|
|
|
|
|
-}
|
|
|
|
|
-#endif // HAVE_PYTHON
|
|
|
|
|
-
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: TypedWritable::encode_to_bam_stream
|
|
// Function: TypedWritable::encode_to_bam_stream
|
|
|
// Access: Published
|
|
// Access: Published
|
|
@@ -291,10 +175,10 @@ encode_to_bam_stream(string &data, BamWriter *writer) const {
|
|
|
if (!dout.open(stream)) {
|
|
if (!dout.open(stream)) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (writer == NULL) {
|
|
if (writer == NULL) {
|
|
|
// Create our own writer.
|
|
// Create our own writer.
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!dout.write_header(_bam_header)) {
|
|
if (!dout.write_header(_bam_header)) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -303,7 +187,7 @@ encode_to_bam_stream(string &data, BamWriter *writer) const {
|
|
|
if (!writer.init()) {
|
|
if (!writer.init()) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!writer.write_object(this)) {
|
|
if (!writer.write_object(this)) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -361,12 +245,11 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
|
|
|
|
|
|
|
|
if (reader == NULL) {
|
|
if (reader == NULL) {
|
|
|
// Create a local reader.
|
|
// Create a local reader.
|
|
|
-
|
|
|
|
|
string head;
|
|
string head;
|
|
|
if (!din.read_header(head, _bam_header.size())) {
|
|
if (!din.read_header(head, _bam_header.size())) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (head != _bam_header) {
|
|
if (head != _bam_header) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -375,15 +258,15 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
|
|
|
if (!reader.init()) {
|
|
if (!reader.init()) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!reader.read_object(ptr, ref_ptr)) {
|
|
if (!reader.read_object(ptr, ref_ptr)) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!reader.resolve()) {
|
|
if (!reader.resolve()) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (ref_ptr == NULL) {
|
|
if (ref_ptr == NULL) {
|
|
|
// Can't support non-reference-counted objects.
|
|
// Can't support non-reference-counted objects.
|
|
|
return false;
|
|
return false;
|
|
@@ -400,12 +283,12 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
|
|
|
reader->set_source(NULL);
|
|
reader->set_source(NULL);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!reader->resolve()) {
|
|
if (!reader->resolve()) {
|
|
|
reader->set_source(NULL);
|
|
reader->set_source(NULL);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (ref_ptr == NULL) {
|
|
if (ref_ptr == NULL) {
|
|
|
// Can't support non-reference-counted objects.
|
|
// Can't support non-reference-counted objects.
|
|
|
reader->set_source(NULL);
|
|
reader->set_source(NULL);
|
|
@@ -425,139 +308,3 @@ decode_raw_from_bam_stream(TypedWritable *&ptr, ReferenceCount *&ref_ptr,
|
|
|
ref_ptr->unref();
|
|
ref_ptr->unref();
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
-#ifdef HAVE_PYTHON
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: TypedWritable::find_global_decode
|
|
|
|
|
-// Access: Public, Static
|
|
|
|
|
-// Description: This is a support function for __reduce__(). It
|
|
|
|
|
-// searches for the global function
|
|
|
|
|
-// py_decode_TypedWritable_from_bam_stream() in this
|
|
|
|
|
-// class's module, or in the module for any base class.
|
|
|
|
|
-// (It's really looking for the libpanda module, but we
|
|
|
|
|
-// can't be sure what name that module was loaded under,
|
|
|
|
|
-// so we search upwards this way.)
|
|
|
|
|
-//
|
|
|
|
|
-// Returns: new reference on success, or NULL on failure.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-PyObject *TypedWritable::
|
|
|
|
|
-find_global_decode(PyObject *this_class, const char *func_name) {
|
|
|
|
|
- PyObject *module_name = PyObject_GetAttrString(this_class, "__module__");
|
|
|
|
|
- if (module_name != NULL) {
|
|
|
|
|
- // borrowed reference
|
|
|
|
|
- PyObject *sys_modules = PyImport_GetModuleDict();
|
|
|
|
|
- if (sys_modules != NULL) {
|
|
|
|
|
- // borrowed reference
|
|
|
|
|
- PyObject *module = PyDict_GetItem(sys_modules, module_name);
|
|
|
|
|
- if (module != NULL){
|
|
|
|
|
- PyObject *func = PyObject_GetAttrString(module, (char *)func_name);
|
|
|
|
|
- if (func != NULL) {
|
|
|
|
|
- Py_DECREF(module_name);
|
|
|
|
|
- return func;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- Py_DECREF(module_name);
|
|
|
|
|
-
|
|
|
|
|
- PyObject *bases = PyObject_GetAttrString(this_class, "__bases__");
|
|
|
|
|
- if (bases != NULL) {
|
|
|
|
|
- if (PySequence_Check(bases)) {
|
|
|
|
|
- Py_ssize_t size = PySequence_Size(bases);
|
|
|
|
|
- for (Py_ssize_t i = 0; i < size; ++i) {
|
|
|
|
|
- PyObject *base = PySequence_GetItem(bases, i);
|
|
|
|
|
- if (base != NULL) {
|
|
|
|
|
- PyObject *func = find_global_decode(base, func_name);
|
|
|
|
|
- Py_DECREF(base);
|
|
|
|
|
- if (func != NULL) {
|
|
|
|
|
- Py_DECREF(bases);
|
|
|
|
|
- return func;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- Py_DECREF(bases);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return NULL;
|
|
|
|
|
-}
|
|
|
|
|
-#endif // HAVE_PYTHON
|
|
|
|
|
-
|
|
|
|
|
-#ifdef HAVE_PYTHON
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: py_decode_TypedWritable_from_bam_stream
|
|
|
|
|
-// Access: Published
|
|
|
|
|
-// Description: This wrapper is defined as a global function to suit
|
|
|
|
|
-// pickle's needs.
|
|
|
|
|
-//
|
|
|
|
|
-// This hooks into the native pickle and cPickle
|
|
|
|
|
-// modules, but it cannot properly handle
|
|
|
|
|
-// self-referential BAM objects.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-PyObject *
|
|
|
|
|
-py_decode_TypedWritable_from_bam_stream(PyObject *this_class, const string &data) {
|
|
|
|
|
- return py_decode_TypedWritable_from_bam_stream_persist(NULL, this_class, data);
|
|
|
|
|
-}
|
|
|
|
|
-#endif // HAVE_PYTHON
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-#ifdef HAVE_PYTHON
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-// Function: py_decode_TypedWritable_from_bam_stream_persist
|
|
|
|
|
-// Access: Published
|
|
|
|
|
-// Description: This wrapper is defined as a global function to suit
|
|
|
|
|
-// pickle's needs.
|
|
|
|
|
-//
|
|
|
|
|
-// This is similar to
|
|
|
|
|
-// py_decode_TypedWritable_from_bam_stream, but it
|
|
|
|
|
-// provides additional support for the missing
|
|
|
|
|
-// persistent-state object needed to properly support
|
|
|
|
|
-// self-referential BAM objects written to the pickle
|
|
|
|
|
-// stream. This hooks into the pickle and cPickle
|
|
|
|
|
-// modules implemented in direct/src/stdpy.
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
|
|
-PyObject *
|
|
|
|
|
-py_decode_TypedWritable_from_bam_stream_persist(PyObject *pickler, PyObject *this_class, const string &data) {
|
|
|
|
|
-
|
|
|
|
|
- PyObject *py_reader = NULL;
|
|
|
|
|
- if (pickler != NULL) {
|
|
|
|
|
- py_reader = PyObject_GetAttrString(pickler, "bamReader");
|
|
|
|
|
- if (py_reader == NULL) {
|
|
|
|
|
- // It's OK if there's no bamReader.
|
|
|
|
|
- PyErr_Clear();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // We need the function PandaNode::decode_from_bam_stream or
|
|
|
|
|
- // TypedWritableReferenceCount::decode_from_bam_stream, which
|
|
|
|
|
- // invokes the BamReader to reconstruct this object. Since we use
|
|
|
|
|
- // the specific object's class as the pointer, we get the particular
|
|
|
|
|
- // instance of decode_from_bam_stream appropriate to this class.
|
|
|
|
|
-
|
|
|
|
|
- PyObject *func = PyObject_GetAttrString(this_class, "decode_from_bam_stream");
|
|
|
|
|
- if (func == NULL) {
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- PyObject *result;
|
|
|
|
|
- if (py_reader != NULL){
|
|
|
|
|
- result = PyObject_CallFunction(func, (char *)"(s#O)", data.data(), data.size(), py_reader);
|
|
|
|
|
- Py_DECREF(py_reader);
|
|
|
|
|
- } else {
|
|
|
|
|
- result = PyObject_CallFunction(func, (char *)"(s#)", data.data(), data.size());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (result == NULL) {
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (result == Py_None) {
|
|
|
|
|
- Py_DECREF(result);
|
|
|
|
|
- PyErr_SetString(PyExc_ValueError, "Could not unpack bam stream");
|
|
|
|
|
- return NULL;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return result;
|
|
|
|
|
-}
|
|
|
|
|
-#endif // HAVE_PYTHON
|
|
|
|
|
-
|
|
|