@@ -986,6 +986,53 @@ int DeleteRepeatedField(CMessage* self, const FieldDescriptor* field_descriptor,
986986 return 0 ;
987987}
988988
989+ int InitWKTOrMerge (const Descriptor* descriptor, PyObject* py_message,
990+ PyObject* value) {
991+ CMessage* cmessage = reinterpret_cast <CMessage*>(py_message);
992+ AssureWritable (cmessage);
993+ if (PyObject_TypeCheck (value, CMessage_Type)) {
994+ ScopedPyObjectPtr merged (MergeFrom (cmessage, value));
995+ if (merged == nullptr ) {
996+ return -1 ;
997+ }
998+ return 0 ;
999+ }
1000+ if (PyDict_Check (value) &&
1001+ (descriptor->well_known_type () == Descriptor::WELLKNOWNTYPE_STRUCT)) {
1002+ ScopedPyObjectPtr ok (PyObject_CallMethod (py_message, " update" , " O" , value));
1003+ if (ok.get () == nullptr && PyDict_Size (value) == 1 ) {
1004+ ScopedPyObjectPtr fields_str (PyUnicode_FromString (" fields" ));
1005+ if (PyDict_Contains (value, fields_str.get ())) {
1006+ // Fallback to init as normal message field.
1007+ PyErr_Clear ();
1008+ PyObject* tmp = Clear (cmessage);
1009+ Py_DECREF (tmp);
1010+ if (InitAttributes (cmessage, nullptr , value) < 0 ) {
1011+ return -1 ;
1012+ }
1013+ }
1014+ }
1015+ return 0 ;
1016+ }
1017+
1018+ if (descriptor->well_known_type () != Descriptor::WELLKNOWNTYPE_UNSPECIFIED &&
1019+ PyObject_HasAttrString (py_message, " _internal_assign" )) {
1020+ ScopedPyObjectPtr ok (
1021+ PyObject_CallMethod (py_message, " _internal_assign" , " O" , value));
1022+ if (ok.get () == nullptr ) {
1023+ return -1 ;
1024+ }
1025+ return 0 ;
1026+ }
1027+
1028+ PyErr_Format (PyExc_TypeError,
1029+ " Parameter to initialize message field must be "
1030+ " dict or instance of same class: expected %s got %s." ,
1031+ std::string (descriptor->full_name ()).c_str (),
1032+ Py_TYPE (value)->tp_name );
1033+ return -1 ;
1034+ }
1035+
9891036// Initializes fields of a message. Used in constructors.
9901037int InitAttributes (CMessage* self, PyObject* args, PyObject* kwargs) {
9911038 if (args != nullptr && PyTuple_Size (args) != 0 ) {
@@ -1084,20 +1131,22 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
10841131 }
10851132 ScopedPyObjectPtr next;
10861133 while ((next.reset (PyIter_Next (iter.get ()))) != nullptr ) {
1087- PyObject* kwargs = (PyDict_Check (next.get ()) ? next.get () : nullptr );
1088- ScopedPyObjectPtr new_msg (
1089- repeated_composite_container::Add (rc_container, nullptr , kwargs));
1090- if (new_msg == nullptr ) {
1091- return -1 ;
1092- }
1093- if (kwargs == nullptr ) {
1094- // next was not a dict, it's a message we need to merge
1095- ScopedPyObjectPtr merged (MergeFrom (
1096- reinterpret_cast <CMessage*>(new_msg.get ()), next.get ()));
1097- if (merged.get () == nullptr ) {
1134+ if ((PyDict_Check (next.get ())) &&
1135+ (descriptor->message_type ()->well_known_type () !=
1136+ Descriptor::WELLKNOWNTYPE_STRUCT)) {
1137+ ScopedPyObjectPtr new_msg (repeated_composite_container::Add (
1138+ rc_container, nullptr , next.get ()));
1139+ if (new_msg == nullptr ) {
10981140 return -1 ;
10991141 }
1142+ continue ;
11001143 }
1144+ ScopedPyObjectPtr new_msg (repeated_composite_container::Add (
1145+ rc_container, nullptr , nullptr ));
1146+ if (new_msg == nullptr ) {
1147+ return -1 ;
1148+ }
1149+ InitWKTOrMerge (descriptor->message_type (), new_msg.get (), next.get ());
11011150 }
11021151 if (PyErr_Occurred ()) {
11031152 // Check to see how PyIter_Next() exited.
@@ -1142,53 +1191,19 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
11421191 return -1 ;
11431192 }
11441193 CMessage* cmessage = reinterpret_cast <CMessage*>(message.get ());
1145- if (PyDict_Check (value)) {
1194+ if (PyDict_Check (value) &&
1195+ (descriptor->message_type ()->well_known_type () !=
1196+ Descriptor::WELLKNOWNTYPE_STRUCT)) {
11461197 // Make the message exist even if the dict is empty.
11471198 AssureWritable (cmessage);
1148- if (descriptor->message_type ()->well_known_type () ==
1149- Descriptor::WELLKNOWNTYPE_STRUCT) {
1150- ScopedPyObjectPtr ok (PyObject_CallMethod (
1151- reinterpret_cast <PyObject*>(cmessage), " update" , " O" , value));
1152- if (ok.get () == nullptr && PyDict_Size (value) == 1 ) {
1153- ScopedPyObjectPtr fields_str (PyUnicode_FromString (" fields" ));
1154- if (PyDict_Contains (value, fields_str.get ())) {
1155- // Fallback to init as normal message field.
1156- PyErr_Clear ();
1157- PyObject* tmp = Clear (cmessage);
1158- Py_DECREF (tmp);
1159- if (InitAttributes (cmessage, nullptr , value) < 0 ) {
1160- return -1 ;
1161- }
1162- }
1163- }
1164- } else {
1165- if (InitAttributes (cmessage, nullptr , value) < 0 ) {
1166- return -1 ;
1167- }
1168- }
1169- } else if (PyObject_TypeCheck (value, CMessage_Type)) {
1170- ScopedPyObjectPtr merged (MergeFrom (cmessage, value));
1171- if (merged == nullptr ) {
1199+ if (InitAttributes (cmessage, nullptr , value) < 0 ) {
11721200 return -1 ;
11731201 }
1174- } else if (descriptor->message_type ()->well_known_type () !=
1175- Descriptor::WELLKNOWNTYPE_UNSPECIFIED &&
1176- PyObject_HasAttrString (reinterpret_cast <PyObject*>(cmessage),
1177- " _internal_assign" )) {
1178- AssureWritable (cmessage);
1179- ScopedPyObjectPtr ok (
1180- PyObject_CallMethod (reinterpret_cast <PyObject*>(cmessage),
1181- " _internal_assign" , " O" , value));
1182- if (ok.get () == nullptr ) {
1202+ } else {
1203+ if (InitWKTOrMerge (descriptor->message_type (), message.get (), value) <
1204+ 0 ) {
11831205 return -1 ;
11841206 }
1185- } else {
1186- PyErr_Format (PyExc_TypeError,
1187- " Parameter to initialize message field must be "
1188- " dict or instance of same class: expected %s got %s." ,
1189- std::string (descriptor->full_name ()).c_str (),
1190- Py_TYPE (value)->tp_name );
1191- return -1 ;
11921207 }
11931208 } else {
11941209 ScopedPyObjectPtr new_val;
0 commit comments