aboutsummaryrefslogtreecommitdiffhomepage
path: root/python/google/protobuf/pyext/descriptor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'python/google/protobuf/pyext/descriptor.cc')
-rw-r--r--python/google/protobuf/pyext/descriptor.cc80
1 files changed, 59 insertions, 21 deletions
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 6bbc92b9..8af0cb12 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -193,39 +193,36 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) {
// Always returns a new reference.
template<class DescriptorClass>
static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
- // Options (and their extensions) are completely resolved in the proto file
- // containing the descriptor.
- PyDescriptorPool* pool = GetDescriptorPool_FromPool(
+ // Options are cached in the pool that owns the descriptor.
+ // First search in the cache.
+ PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool(
GetFileDescriptor(descriptor)->pool());
-
hash_map<const void*, PyObject*>* descriptor_options =
- pool->descriptor_options;
- // First search in the cache.
+ caching_pool->descriptor_options;
if (descriptor_options->find(descriptor) != descriptor_options->end()) {
PyObject *value = (*descriptor_options)[descriptor];
Py_INCREF(value);
return value;
}
+ // Similar to the C++ implementation, we return an Options object from the
+ // default (generated) factory, so that client code know that they can use
+ // extensions from generated files:
+ // d.GetOptions().Extensions[some_pb2.extension]
+ //
+ // The consequence is that extensions not defined in the default pool won't
+ // be available. If needed, we could add an optional 'message_factory'
+ // parameter to the GetOptions() function.
+ PyMessageFactory* message_factory =
+ GetDefaultDescriptorPool()->py_message_factory;
+
// Build the Options object: get its Python class, and make a copy of the C++
// read-only instance.
const Message& options(descriptor->options());
const Descriptor *message_type = options.GetDescriptor();
- PyMessageFactory* message_factory = pool->py_message_factory;
- CMessageClass* message_class = message_factory::GetMessageClass(
+ CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
message_factory, message_type);
if (message_class == NULL) {
- // The Options message was not found in the current DescriptorPool.
- // This means that the pool cannot contain any extensions to the Options
- // message either, so falling back to the basic pool we can only increase
- // the chances of successfully parsing the options.
- PyErr_Clear();
- pool = GetDefaultDescriptorPool();
- message_factory = pool->py_message_factory;
- message_class = message_factory::GetMessageClass(
- message_factory, message_type);
- }
- if (message_class == NULL) {
PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
message_type->full_name().c_str());
return NULL;
@@ -253,7 +250,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
options.SerializeToString(&serialized);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
- input.SetExtensionRegistry(pool->pool, message_factory->message_factory);
+ input.SetExtensionRegistry(message_factory->pool->pool,
+ message_factory->message_factory);
bool success = cmsg->message->MergePartialFromCodedStream(&input);
if (!success) {
PyErr_Format(PyExc_ValueError, "Error parsing Options message");
@@ -569,6 +567,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
+static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_serialized_options");
+}
+
static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
}
@@ -628,6 +631,8 @@ static PyGetSetDef Getters[] = {
{ "is_extendable", (getter)IsExtendable, (setter)NULL},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
+ "Serialized Options"},
{ "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
{NULL}
};
@@ -790,7 +795,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
break;
}
case FieldDescriptor::CPPTYPE_STRING: {
- string value = _GetDescriptor(self)->default_value_string();
+ const string& value = _GetDescriptor(self)->default_value_string();
result = ToStringObject(_GetDescriptor(self), value);
break;
}
@@ -902,6 +907,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
+static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_serialized_options");
+}
static PyGetSetDef Getters[] = {
{ "full_name", (getter)GetFullName, NULL, "Full name"},
@@ -931,6 +940,8 @@ static PyGetSetDef Getters[] = {
"Containing oneof"},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
+ "Serialized Options"},
{NULL}
};
@@ -1060,6 +1071,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
+static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_serialized_options");
+}
+
static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
}
@@ -1084,6 +1100,8 @@ static PyGetSetDef Getters[] = {
"Containing type"},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
+ "Serialized Options"},
{NULL}
};
@@ -1184,6 +1202,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
+static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_serialized_options");
+}
static PyGetSetDef Getters[] = {
{ "name", (getter)GetName, NULL, "name"},
@@ -1193,6 +1215,8 @@ static PyGetSetDef Getters[] = {
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
+ "Serialized Options"},
{NULL}
};
@@ -1335,6 +1359,11 @@ static int SetOptions(PyFileDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
+static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_serialized_options");
+}
+
static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
return PyString_InternFromString(
FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
@@ -1360,6 +1389,8 @@ static PyGetSetDef Getters[] = {
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
+ "Serialized Options"},
{ "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
{NULL}
};
@@ -1505,6 +1536,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
return CheckCalledFromGeneratedFile("_options");
}
+static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_serialized_options");
+}
+
static PyGetSetDef Getters[] = {
{ "name", (getter)GetName, NULL, "Name"},
{ "full_name", (getter)GetFullName, NULL, "Full name"},
@@ -1513,6 +1549,8 @@ static PyGetSetDef Getters[] = {
{ "containing_type", (getter)GetContainingType, NULL, "Containing type"},
{ "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
{ "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions,
+ "Serialized Options"},
{ "fields", (getter)GetFields, NULL, "Fields"},
{NULL}
};