diff options
Diffstat (limited to 'python/google/protobuf/pyext')
-rw-r--r-- | python/google/protobuf/pyext/descriptor.cc | 19 | ||||
-rw-r--r-- | python/google/protobuf/pyext/descriptor.h | 2 | ||||
-rw-r--r-- | python/google/protobuf/pyext/descriptor_pool.cc | 20 | ||||
-rw-r--r-- | python/google/protobuf/pyext/descriptor_pool.h | 1 | ||||
-rw-r--r-- | python/google/protobuf/pyext/python_protobuf.h | 57 | ||||
-rw-r--r-- | python/google/protobuf/pyext/repeated_composite_container.cc | 29 | ||||
-rw-r--r-- | python/google/protobuf/pyext/scoped_pyobject_ptr.h | 59 |
7 files changed, 104 insertions, 83 deletions
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 924ae0b9..f13e1bc1 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -32,6 +32,7 @@ #include <Python.h> #include <frameobject.h> +#include <google/protobuf/stubs/hash.h> #include <string> #include <google/protobuf/io/coded_stream.h> @@ -1666,6 +1667,15 @@ PyObject* PyServiceDescriptor_FromDescriptor( &PyServiceDescriptor_Type, service_descriptor, NULL); } +const ServiceDescriptor* PyServiceDescriptor_AsDescriptor(PyObject* obj) { + if (!PyObject_TypeCheck(obj, &PyServiceDescriptor_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a ServiceDescriptor"); + return NULL; + } + return reinterpret_cast<const ServiceDescriptor*>( + reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); +} + namespace method_descriptor { // Unchecked accessor to the C++ pointer. @@ -1769,6 +1779,15 @@ PyObject* PyMethodDescriptor_FromDescriptor( &PyMethodDescriptor_Type, method_descriptor, NULL); } +const MethodDescriptor* PyMethodDescriptor_AsDescriptor(PyObject* obj) { + if (!PyObject_TypeCheck(obj, &PyMethodDescriptor_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a MethodDescriptor"); + return NULL; + } + return reinterpret_cast<const MethodDescriptor*>( + reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); +} + // Add a enum values to a type dictionary. static bool AddEnumValues(PyTypeObject *type, const EnumDescriptor* enum_descriptor) { diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h index 1ae0e672..f081df84 100644 --- a/python/google/protobuf/pyext/descriptor.h +++ b/python/google/protobuf/pyext/descriptor.h @@ -80,6 +80,8 @@ const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj); const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj); const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj); const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj); +const ServiceDescriptor* PyServiceDescriptor_AsDescriptor(PyObject* obj); +const MethodDescriptor* PyMethodDescriptor_AsDescriptor(PyObject* obj); // Returns the raw C++ pointer. const void* PyDescriptor_AsVoidPtr(PyObject* obj); diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc index fa66bf9a..16f4d49d 100644 --- a/python/google/protobuf/pyext/descriptor_pool.cc +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -39,6 +39,7 @@ #include <google/protobuf/pyext/message.h> #include <google/protobuf/pyext/message_factory.h> #include <google/protobuf/pyext/scoped_pyobject_ptr.h> +#include <google/protobuf/stubs/hash.h> #if PY_MAJOR_VERSION >= 3 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize @@ -437,8 +438,23 @@ PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) { Py_RETURN_NONE; } -// The code below loads new Descriptors from a serialized FileDescriptorProto. +PyObject* AddServiceDescriptor(PyDescriptorPool* self, PyObject* descriptor) { + const ServiceDescriptor* service_descriptor = + PyServiceDescriptor_AsDescriptor(descriptor); + if (!service_descriptor) { + return NULL; + } + if (service_descriptor != + self->pool->FindServiceByName(service_descriptor->full_name())) { + PyErr_Format(PyExc_ValueError, + "The service descriptor %s does not belong to this pool", + service_descriptor->full_name().c_str()); + return NULL; + } + Py_RETURN_NONE; +} +// The code below loads new Descriptors from a serialized FileDescriptorProto. // Collects errors that occur during proto file building to allow them to be // propagated in the python exception instead of only living in ERROR logs. @@ -538,6 +554,8 @@ static PyMethodDef Methods[] = { "No-op. Add() must have been called before." }, { "AddExtensionDescriptor", (PyCFunction)AddExtensionDescriptor, METH_O, "No-op. Add() must have been called before." }, + { "AddServiceDescriptor", (PyCFunction)AddServiceDescriptor, METH_O, + "No-op. Add() must have been called before." }, { "FindFileByName", (PyCFunction)FindFileByName, METH_O, "Searches for a file descriptor by its .proto name." }, diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h index c4d7d403..53ee53dc 100644 --- a/python/google/protobuf/pyext/descriptor_pool.h +++ b/python/google/protobuf/pyext/descriptor_pool.h @@ -85,6 +85,7 @@ extern PyTypeObject PyDescriptorPool_Type; namespace cdescriptor_pool { + // Looks up a message by name. // Returns a message Descriptor, or NULL if not found. const Descriptor* FindMessageTypeByName(PyDescriptorPool* self, diff --git a/python/google/protobuf/pyext/python_protobuf.h b/python/google/protobuf/pyext/python_protobuf.h deleted file mode 100644 index beb6e460..00000000 --- a/python/google/protobuf/pyext/python_protobuf.h +++ /dev/null @@ -1,57 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: qrczak@google.com (Marcin Kowalczyk) -// -// This module exposes the C proto inside the given Python proto, in -// case the Python proto is implemented with a C proto. - -#ifndef GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ -#define GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ - -#include <Python.h> - -namespace google { -namespace protobuf { - -class Message; - -namespace python { - -// Return the pointer to the C proto inside the given Python proto, -// or NULL when this is not a Python proto implemented with a C proto. -const Message* GetCProtoInsidePyProto(PyObject* msg); -Message* MutableCProtoInsidePyProto(PyObject* msg); - -} // namespace python -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__ diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index 43a2bc12..9cb4e9a1 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -47,6 +47,7 @@ #include <google/protobuf/pyext/descriptor_pool.h> #include <google/protobuf/pyext/message.h> #include <google/protobuf/pyext/scoped_pyobject_ptr.h> +#include <google/protobuf/reflection.h> #if PY_MAJOR_VERSION >= 3 #define PyInt_Check PyLong_Check @@ -485,6 +486,32 @@ int Release(RepeatedCompositeContainer* self) { return 0; } +PyObject* DeepCopy(RepeatedCompositeContainer* self, PyObject* arg) { + ScopedPyObjectPtr cloneObj( + PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0)); + if (cloneObj == NULL) { + return NULL; + } + RepeatedCompositeContainer* clone = + reinterpret_cast<RepeatedCompositeContainer*>(cloneObj.get()); + + Message* new_message = self->message->New(); + clone->parent = NULL; + clone->parent_field_descriptor = self->parent_field_descriptor; + clone->message = new_message; + clone->owner.reset(new_message); + Py_INCREF(self->child_message_class); + clone->child_message_class = self->child_message_class; + clone->child_messages = PyList_New(0); + + new_message->GetReflection() + ->GetMutableRepeatedFieldRef<Message>(new_message, + self->parent_field_descriptor) + .MergeFrom(self->message->GetReflection()->GetRepeatedFieldRef<Message>( + *self->message, self->parent_field_descriptor)); + return cloneObj.release(); +} + int SetOwner(RepeatedCompositeContainer* self, const shared_ptr<Message>& new_owner) { GOOGLE_CHECK_ATTACHED(self); @@ -551,6 +578,8 @@ static PyMappingMethods MpMethods = { }; static PyMethodDef Methods[] = { + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, { "add", (PyCFunction) Add, METH_VARARGS | METH_KEYWORDS, "Adds an object to the repeated container." }, { "extend", (PyCFunction) Extend, METH_O, diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h index a128cd4c..a2afa7f1 100644 --- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h +++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h @@ -36,61 +36,70 @@ #include <google/protobuf/stubs/common.h> #include <Python.h> - namespace google { -class ScopedPyObjectPtr { +namespace protobuf { +namespace python { + +// Owns a python object and decrements the reference count on destruction. +// This class is not threadsafe. +template <typename PyObjectStruct> +class ScopedPythonPtr { public: - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized ScopedPyObjectPtr. - explicit ScopedPyObjectPtr(PyObject* p = NULL) : ptr_(p) { } + // Takes the ownership of the specified object to ScopedPythonPtr. + // The reference count of the specified py_object is not incremented. + explicit ScopedPythonPtr(PyObjectStruct* py_object = NULL) + : ptr_(py_object) {} - // Destructor. If there is a PyObject object, delete it. - ~ScopedPyObjectPtr() { - Py_XDECREF(ptr_); - } + // If a PyObject is owned, decrement its reference count. + ~ScopedPythonPtr() { Py_XDECREF(ptr_); } - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. + // Deletes the current owned object, if any. + // Then takes ownership of a new object without incrementing the reference + // count. // This function must be called with a reference that you own. // this->reset(this->get()) is wrong! // this->reset(this->release()) is OK. - PyObject* reset(PyObject* p = NULL) { + PyObjectStruct* reset(PyObjectStruct* p = NULL) { Py_XDECREF(ptr_); ptr_ = p; return ptr_; } - // Releases ownership of the object. + // Releases ownership of the object without decrementing the reference count. // The caller now owns the returned reference. - PyObject* release() { + PyObjectStruct* release() { PyObject* p = ptr_; ptr_ = NULL; return p; } - PyObject* operator->() const { + PyObjectStruct* operator->() const { assert(ptr_ != NULL); return ptr_; } - PyObject* get() const { return ptr_; } + PyObjectStruct* get() const { return ptr_; } - Py_ssize_t refcnt() const { return Py_REFCNT(ptr_); } + PyObject* as_pyobject() const { return reinterpret_cast<PyObject*>(ptr_); } + // Increments the reference count fo the current object. + // Should not be called when no object is held. void inc() const { Py_INCREF(ptr_); } - // Comparison operators. - // These return whether a ScopedPyObjectPtr and a raw pointer - // refer to the same object, not just to two different but equal - // objects. - bool operator==(const PyObject* p) const { return ptr_ == p; } - bool operator!=(const PyObject* p) const { return ptr_ != p; } + // True when a ScopedPyObjectPtr and a raw pointer refer to the same object. + // Comparison operators are non reflexive. + bool operator==(const PyObjectStruct* p) const { return ptr_ == p; } + bool operator!=(const PyObjectStruct* p) const { return ptr_ != p; } private: - PyObject* ptr_; + PyObjectStruct* ptr_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedPyObjectPtr); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedPythonPtr); }; +typedef ScopedPythonPtr<PyObject> ScopedPyObjectPtr; + +} // namespace python +} // namespace protobuf } // namespace google #endif // GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__ |