diff options
author | Josh Haberman <jhaberman@gmail.com> | 2018-09-04 10:58:54 -0700 |
---|---|---|
committer | Josh Haberman <jhaberman@gmail.com> | 2018-09-04 10:58:54 -0700 |
commit | d61aede89cf188367766b971f59cf57d7835d8e8 (patch) | |
tree | a19842c62c3c8f51389912ecafdf932d0a572bea /python | |
parent | 45d03a977193d1dcce5251e4bffe17bf0ba738ec (diff) | |
download | protobuf-d61aede89cf188367766b971f59cf57d7835d8e8.tar.gz protobuf-d61aede89cf188367766b971f59cf57d7835d8e8.tar.bz2 protobuf-d61aede89cf188367766b971f59cf57d7835d8e8.zip |
Down-integrate from google3.
Diffstat (limited to 'python')
20 files changed, 232 insertions, 65 deletions
diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py index a7616cbc..5453f50c 100644 --- a/python/google/protobuf/descriptor_database.py +++ b/python/google/protobuf/descriptor_database.py @@ -134,7 +134,11 @@ class DescriptorDatabase(object): # descriptor can also be found. The behavior is the same with # protobuf C++. top_level, _, _ = symbol.rpartition('.') - return self._file_desc_protos_by_symbol[top_level] + try: + return self._file_desc_protos_by_symbol[top_level] + except KeyError: + # Raise the original symbol as a KeyError for better diagnostics. + raise KeyError(symbol) def FindFileContainingExtension(self, extendee_name, extension_number): # TODO(jieluo): implement this API. diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index d2ec4f7b..5a540184 100755 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -81,9 +81,8 @@ we repeatedly read a tag, look up the corresponding decoder, and invoke it. __author__ = 'kenton@google.com (Kenton Varda)' import struct - -import six import sys +import six _UCS2_MAXUNICODE = 65535 if six.PY3: diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py index 97e5315a..da5dbd92 100644 --- a/python/google/protobuf/internal/descriptor_database_test.py +++ b/python/google/protobuf/internal/descriptor_database_test.py @@ -103,9 +103,8 @@ class DescriptorDatabaseTest(unittest.TestCase): self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( 'protobuf_unittest.TestAllTypes.none_field')) - self.assertRaises(KeyError, - db.FindFileContainingSymbol, - 'protobuf_unittest.NoneMessage') + with self.assertRaisesRegexp(KeyError, r'\'protobuf_unittest\.NoneMessage\''): + db.FindFileContainingSymbol('protobuf_unittest.NoneMessage') def testConflictRegister(self): db = descriptor_database.DescriptorDatabase() diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index ccb9221c..4dd1104a 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -1217,13 +1217,13 @@ class Proto2Test(BaseTestCase): message.optional_bool = True message.optional_nested_message.bb = 15 - self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField(u"optional_int32")) self.assertTrue(message.HasField("optional_bool")) self.assertTrue(message.HasField("optional_nested_message")) # Clearing the fields unsets them and resets their value to default. message.ClearField("optional_int32") - message.ClearField("optional_bool") + message.ClearField(u"optional_bool") message.ClearField("optional_nested_message") self.assertFalse(message.HasField("optional_int32")) @@ -1435,6 +1435,16 @@ class Proto2Test(BaseTestCase): with self.assertRaises(ValueError): unittest_pb2.TestAllTypes(repeated_nested_enum='FOO') + def testPythonicInitWithDict(self): + # Both string/unicode field name keys should work. + kwargs = { + 'optional_int32': 100, + u'optional_fixed32': 200, + } + msg = unittest_pb2.TestAllTypes(**kwargs) + self.assertEqual(100, msg.optional_int32) + self.assertEqual(200, msg.optional_fixed32) + def test_documentation(self): # Also used by the interactive help() function. @@ -2210,9 +2220,8 @@ class Proto3Test(BaseTestCase): msg.map_int32_int32[35] = 64 msg.map_string_foreign_message['foo'].c = 5 self.assertEqual(0, len(msg.FindInitializationErrors())) - - @unittest.skipIf(sys.maxunicode == UCS2_MAXUNICODE, - 'Skip for ucs2') + + @unittest.skipIf(sys.maxunicode == UCS2_MAXUNICODE, 'Skip for ucs2') def testStrictUtf8Check(self): # Test u'\ud801' is rejected at parser in both python2 and python3. serialized = (b'r\x03\xed\xa0\x81') diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py index ab5d160f..4e0f545c 100755 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -1003,8 +1003,13 @@ def _AddEqualsMethod(message_descriptor, cls): if not self.ListFields() == other.ListFields(): return False - # pylint: disable=protected-access - return self._unknown_field_set == other._unknown_field_set + # TODO(jieluo): Fix UnknownFieldSet to consider MessageSet extensions, + # then use it for the comparison. + unknown_fields = list(self._unknown_fields) + unknown_fields.sort() + other_unknown_fields = list(other._unknown_fields) + other_unknown_fields.sort() + return unknown_fields == other_unknown_fields cls.__eq__ = __eq__ diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 31ceda24..90d2fe3c 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -1579,6 +1579,8 @@ class ReflectionTest(BaseTestCase): proto1.repeated_int32.append(3) container = copy.deepcopy(proto1.repeated_int32) self.assertEqual([2, 3], container) + container.remove(container[0]) + self.assertEqual([3], container) message1 = proto1.repeated_nested_message.add() message1.bb = 1 @@ -1586,6 +1588,8 @@ class ReflectionTest(BaseTestCase): self.assertEqual(proto1.repeated_nested_message, messages) message1.bb = 2 self.assertNotEqual(proto1.repeated_nested_message, messages) + messages.remove(messages[0]) + self.assertEqual(len(messages), 0) # TODO(anuraag): Implement deepcopy for extension dict diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index c68f42d2..ccf8ac16 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -835,6 +835,29 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase): ' }\n' '}\n') + # In cpp implementation, __str__ calls the cpp implementation of text format. + def testPrintMapUsingCppImplementation(self): + message = map_unittest_pb2.TestMap() + inner_msg = message.map_int32_foreign_message[111] + inner_msg.c = 1 + self.assertEqual( + str(message), + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 1\n' + ' }\n' + '}\n') + inner_msg.c = 2 + self.assertEqual( + str(message), + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 2\n' + ' }\n' + '}\n') + def testMapOrderEnforcement(self): message = map_unittest_pb2.TestMap() for letter in string.ascii_uppercase[13:26]: @@ -1397,6 +1420,24 @@ class Proto3Tests(unittest.TestCase): ' < data: "string" > ' '>') + def testPrintAndParseMessageInvalidAny(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + # Only include string after last '/' in type_url. + message.any_value.type_url = message.any_value.TypeName() + text = text_format.MessageToString(message) + self.assertEqual( + text, 'any_value {\n' + ' type_url: "protobuf_unittest.OneString"\n' + ' value: "\\n\\006string"\n' + '}\n') + + parsed_message = any_test_pb2.TestAny() + text_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + def testUnknownEnums(self): message = unittest_proto3_arena_pb2.TestAllTypes() message2 = unittest_proto3_arena_pb2.TestAllTypes() @@ -1866,5 +1907,64 @@ class PrettyPrinterTest(TextFormatBase): 'repeated_nested_message { My lucky number is 42 } ' 'repeated_nested_message { My lucky number is 99 }')) + +class WhitespaceTest(TextFormatBase): + + def setUp(self): + self.out = text_format.TextWriter(False) + self.addCleanup(self.out.close) + self.message = unittest_pb2.NestedTestAllTypes() + self.message.child.payload.optional_string = 'value' + self.field = self.message.DESCRIPTOR.fields_by_name['child'] + self.value = self.message.child + + def testMessageToString(self): + self.CompareToGoldenText( + text_format.MessageToString(self.message), + textwrap.dedent("""\ + child { + payload { + optional_string: "value" + } + } + """)) + + def testPrintMessage(self): + text_format.PrintMessage(self.message, self.out) + self.CompareToGoldenText( + self.out.getvalue(), + textwrap.dedent("""\ + child { + payload { + optional_string: "value" + } + } + """)) + + def testPrintField(self): + text_format.PrintField(self.field, self.value, self.out) + self.CompareToGoldenText( + self.out.getvalue(), + textwrap.dedent("""\ + child { + payload { + optional_string: "value" + } + } + """)) + + def testPrintFieldValue(self): + text_format.PrintFieldValue( + self.field, self.value, self.out) + self.CompareToGoldenText( + self.out.getvalue(), + textwrap.dedent("""\ + { + payload { + optional_string: "value" + } + }""")) + + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py index 37a65cfa..95c5615f 100644 --- a/python/google/protobuf/internal/well_known_types.py +++ b/python/google/protobuf/internal/well_known_types.py @@ -40,6 +40,7 @@ This files defines well known classes which need extra maintenance including: __author__ = 'jieluo@google.com (Jie Luo)' +import calendar import collections from datetime import datetime from datetime import timedelta @@ -92,7 +93,7 @@ class Any(object): def Is(self, descriptor): """Checks if this Any represents the given protobuf type.""" - return self.TypeName() == descriptor.full_name + return '/' in self.type_url and self.TypeName() == descriptor.full_name class Timestamp(object): @@ -233,9 +234,15 @@ class Timestamp(object): def FromDatetime(self, dt): """Converts datetime to Timestamp.""" - td = dt - datetime(1970, 1, 1) - self.seconds = td.seconds + td.days * _SECONDS_PER_DAY - self.nanos = td.microseconds * _NANOS_PER_MICROSECOND + # Using this guide: http://wiki.python.org/moin/WorkingWithTime + # And this conversion guide: http://docs.python.org/library/time.html + + # Turn the date parameter into a tuple (struct_time) that can then be + # manipulated into a long value of seconds. During the conversion from + # struct_time to long, the source date in UTC, and so it follows that the + # correct transformation is calendar.timegm() + self.seconds = calendar.timegm(dt.utctimetuple()) + self.nanos = dt.microsecond * _NANOS_PER_MICROSECOND class Duration(object): diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py index 965940b2..4dc2ae4f 100644 --- a/python/google/protobuf/internal/well_known_types_test.py +++ b/python/google/protobuf/internal/well_known_types_test.py @@ -35,7 +35,7 @@ __author__ = 'jieluo@google.com (Jie Luo)' import collections -from datetime import datetime +import datetime try: import unittest2 as unittest #PY26 @@ -240,14 +240,34 @@ class TimeUtilTest(TimeUtilTestBase): def testDatetimeConverison(self): message = timestamp_pb2.Timestamp() - dt = datetime(1970, 1, 1) + dt = datetime.datetime(1970, 1, 1) message.FromDatetime(dt) self.assertEqual(dt, message.ToDatetime()) message.FromMilliseconds(1999) - self.assertEqual(datetime(1970, 1, 1, 0, 0, 1, 999000), + self.assertEqual(datetime.datetime(1970, 1, 1, 0, 0, 1, 999000), message.ToDatetime()) + def testDatetimeConversionWithTimezone(self): + class TZ(datetime.tzinfo): + + def utcoffset(self, _): + return datetime.timedelta(hours=1) + + def dst(self, _): + return datetime.timedelta(0) + + def tzname(self, _): + return 'UTC+1' + + message1 = timestamp_pb2.Timestamp() + dt = datetime.datetime(1970, 1, 1, 1, tzinfo=TZ()) + message1.FromDatetime(dt) + message2 = timestamp_pb2.Timestamp() + dt = datetime.datetime(1970, 1, 1, 0) + message2.FromDatetime(dt) + self.assertEqual(message1, message2) + def testTimedeltaConversion(self): message = duration_pb2.Duration() message.FromNanoseconds(1999999999) @@ -879,6 +899,17 @@ class AnyTest(unittest.TestCase): raise AttributeError('%s should not have Pack method.' % msg_descriptor.full_name) + def testUnpackWithNoSlashInTypeUrl(self): + msg = any_test_pb2.TestAny() + all_types = unittest_pb2.TestAllTypes() + all_descriptor = all_types.DESCRIPTOR + msg.value.Pack(all_types) + # Reset type_url to part of type_url after '/' + msg.value.type_url = msg.value.TypeName() + self.assertFalse(msg.value.Is(all_descriptor)) + unpacked_message = unittest_pb2.TestAllTypes() + self.assertFalse(msg.value.Unpack(unpacked_message)) + def testMessageName(self): # Creates and sets message. submessage = any_test_pb2.TestAny() diff --git a/python/google/protobuf/pyext/descriptor_database.h b/python/google/protobuf/pyext/descriptor_database.h index daf25e0b..30aa1b73 100644 --- a/python/google/protobuf/pyext/descriptor_database.h +++ b/python/google/protobuf/pyext/descriptor_database.h @@ -48,18 +48,18 @@ class PyDescriptorDatabase : public DescriptorDatabase { // with a copy of FileDescriptorProto. // Find a file by file name. - bool FindFileByName(const string& filename, + bool FindFileByName(const std::string& filename, FileDescriptorProto* output); // Find the file that declares the given fully-qualified symbol name. - bool FindFileContainingSymbol(const string& symbol_name, + bool FindFileContainingSymbol(const std::string& symbol_name, FileDescriptorProto* output); // Find the file which defines an extension extending the given message type // with the given field number. // Containing_type must be a fully-qualified type name. // Python objects are not required to implement this method. - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output); @@ -67,7 +67,7 @@ class PyDescriptorDatabase : public DescriptorDatabase { // containing_type, and appends them to output in an undefined // order. // Python objects are not required to implement this method. - bool FindAllExtensionNumbers(const string& containing_type, + bool FindAllExtensionNumbers(const std::string& containing_type, std::vector<int>* output); private: diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h index 8289daea..8e7b4d6b 100644 --- a/python/google/protobuf/pyext/descriptor_pool.h +++ b/python/google/protobuf/pyext/descriptor_pool.h @@ -89,7 +89,7 @@ namespace cdescriptor_pool { // Looks up a message by name. // Returns a message Descriptor, or NULL if not found. const Descriptor* FindMessageTypeByName(PyDescriptorPool* self, - const string& name); + const std::string& name); // The functions below are also exposed as methods of the DescriptorPool type. diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index 2205f12f..f42d9be2 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -68,6 +68,8 @@ #include <google/protobuf/util/message_differencer.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/port_def.inc> + #if PY_MAJOR_VERSION >= 3 #define PyInt_AsLong PyLong_AsLong #define PyInt_FromLong PyLong_FromLong @@ -642,7 +644,7 @@ void OutOfRangeError(PyObject* arg) { template<class RangeType, class ValueType> bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { - if (GOOGLE_PREDICT_FALSE(value == -1 && PyErr_Occurred())) { + if (ABSL_PREDICT_FALSE(value == -1 && PyErr_Occurred())) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { // Replace it with the same ValueError as pure python protos instead of // the default one. @@ -651,7 +653,7 @@ bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { } // Otherwise propagate existing error. return false; } - if (GOOGLE_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) { + if (ABSL_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) { OutOfRangeError(arg); return false; } @@ -663,22 +665,22 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // The fast path. #if PY_MAJOR_VERSION < 3 // For the typical case, offer a fast path. - if (GOOGLE_PREDICT_TRUE(PyInt_Check(arg))) { + if (PROTOBUF_PREDICT_TRUE(PyInt_Check(arg))) { long int_result = PyInt_AsLong(arg); - if (GOOGLE_PREDICT_TRUE(IsValidNumericCast<T>(int_result))) { + if (PROTOBUF_PREDICT_TRUE(IsValidNumericCast<T>(int_result))) { *value = static_cast<T>(int_result); return true; } else { OutOfRangeError(arg); return false; } - } + } #endif // This effectively defines an integer as "an object that can be cast as // an integer and can be used as an ordinal number". // This definition includes everything that implements numbers.Integral // and shouldn't cast the net too wide. - if (GOOGLE_PREDICT_FALSE(!PyIndex_Check(arg))) { + if (ABSL_PREDICT_FALSE(!PyIndex_Check(arg))) { FormatTypeError(arg, "int, long"); return false; } @@ -695,7 +697,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // Unlike PyLong_AsLongLong, PyLong_AsUnsignedLongLong is very // picky about the exact type. PyObject* casted = PyNumber_Long(arg); - if (GOOGLE_PREDICT_FALSE(casted == nullptr)) { + if (ABSL_PREDICT_FALSE(casted == nullptr)) { // Propagate existing error. return false; } @@ -720,7 +722,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // Valid subclasses of numbers.Integral should have a __long__() method // so fall back to that. PyObject* casted = PyNumber_Long(arg); - if (GOOGLE_PREDICT_FALSE(casted == nullptr)) { + if (ABSL_PREDICT_FALSE(casted == nullptr)) { // Propagate existing error. return false; } @@ -746,7 +748,7 @@ template bool CheckAndGetInteger<uint64>(PyObject*, uint64*); bool CheckAndGetDouble(PyObject* arg, double* value) { *value = PyFloat_AsDouble(arg); - if (GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) { + if (ABSL_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) { FormatTypeError(arg, "int, long, float"); return false; } @@ -1106,11 +1108,10 @@ static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor, // needs to do this to make sure CMessages stay alive if they're still // referenced after deletion. Repeated scalar container doesn't need to worry. int InternalDeleteRepeatedField( - CMessage* self, + Message* message, const FieldDescriptor* field_descriptor, PyObject* slice, PyObject* cmessage_list) { - Message* message = self->message; Py_ssize_t length, from, to, step, slice_length; const Reflection* reflection = message->GetReflection(); int min, max; @@ -1188,7 +1189,7 @@ int InternalDeleteRepeatedField( CMessage* last_cmessage = reinterpret_cast<CMessage*>( PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1)); repeated_composite_container::ReleaseLastTo( - self, field_descriptor, last_cmessage); + message, field_descriptor, last_cmessage); if (PySequence_DelItem(cmessage_list, -1) < 0) { return -1; } @@ -1214,7 +1215,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { PyObject* name; PyObject* value; while (PyDict_Next(kwargs, &pos, &name, &value)) { - if (!PyString_Check(name)) { + if (!(PyString_Check(name) || PyUnicode_Check(name))) { PyErr_SetString(PyExc_ValueError, "Field name must be a string"); return -1; } @@ -1808,13 +1809,16 @@ PyObject* ClearFieldByDescriptor( } PyObject* ClearField(CMessage* self, PyObject* arg) { - if (!PyString_Check(arg)) { + if (!(PyString_Check(arg) || PyUnicode_Check(arg))) { PyErr_SetString(PyExc_TypeError, "field name must be a string"); return NULL; } #if PY_MAJOR_VERSION < 3 - const char* field_name = PyString_AS_STRING(arg); - Py_ssize_t size = PyString_GET_SIZE(arg); + char* field_name; + Py_ssize_t size; + if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) { + return NULL; + } #else Py_ssize_t size; const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size); diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index cbd422be..c112a88f 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -166,13 +166,13 @@ PyObject* InternalGetSubMessage( // Deletes a range of C++ submessages in a repeated field (following a // removal in a RepeatedCompositeContainer). // -// Releases messages to the provided cmessage_list if it is not NULL rather +// Releases submessages to the provided cmessage_list if it is not NULL rather // than just removing them from the underlying proto. This cmessage_list must // have a CMessage for each underlying submessage. The CMessages referred to // by slice will be removed from cmessage_list by this function. // // Corresponds to reflection api method RemoveLast. -int InternalDeleteRepeatedField(CMessage* self, +int InternalDeleteRepeatedField(Message* message, const FieldDescriptor* field_descriptor, PyObject* slice, PyObject* cmessage_list); @@ -332,7 +332,7 @@ bool CheckAndSetString( bool append, int index); PyObject* ToStringObject(const FieldDescriptor* descriptor, - const string& value); + const std::string& value); // Check if the passed field descriptor belongs to the given message. // If not, return false and set a Python exception (a KeyError) diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc index 8d465eb5..b8e28df4 100644 --- a/python/google/protobuf/pyext/message_module.cc +++ b/python/google/protobuf/pyext/message_module.cc @@ -31,7 +31,7 @@ #include <Python.h> #include <google/protobuf/pyext/message.h> -#include <google/protobuf/proto_api.h> +#include <google/protobuf/python/proto_api.h> #include <google/protobuf/message_lite.h> diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index d6bc3d7b..ca700580 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -272,8 +272,8 @@ int AssignSubscript(RepeatedCompositeContainer* self, } // Delete from the underlying Message, if any. - if (self->parent != NULL) { - if (cmessage::InternalDeleteRepeatedField(self->parent, + if (self->message != nullptr) { + if (cmessage::InternalDeleteRepeatedField(self->message, self->parent_field_descriptor, slice, self->child_messages) < 0) { @@ -486,15 +486,15 @@ static PyObject* Pop(PyObject* pself, PyObject* args) { } // Release field of parent message and transfer the ownership to target. -void ReleaseLastTo(CMessage* parent, +void ReleaseLastTo(Message* message, const FieldDescriptor* field, CMessage* target) { - GOOGLE_CHECK(parent != nullptr); + GOOGLE_CHECK(message != nullptr); GOOGLE_CHECK(field != nullptr); GOOGLE_CHECK(target != nullptr); CMessage::OwnerRef released_message( - parent->message->GetReflection()->ReleaseLast(parent->message, field)); + message->GetReflection()->ReleaseLast(message, field)); // TODO(tibell): Deal with proto1. target->parent = NULL; @@ -524,7 +524,7 @@ int Release(RepeatedCompositeContainer* self) { for (Py_ssize_t i = size - 1; i >= 0; --i) { CMessage* child_cmessage = reinterpret_cast<CMessage*>( PyList_GET_ITEM(self->child_messages, i)); - ReleaseLastTo(self->parent, field, child_cmessage); + ReleaseLastTo(message, field, child_cmessage); } // Detach from containing message. diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index 464699aa..d0755771 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -154,7 +154,7 @@ int SetOwner(RepeatedCompositeContainer* self, // Message to 'target'. // // Corresponds to reflection api method ReleaseMessage. -void ReleaseLastTo(CMessage* parent, +void ReleaseLastTo(Message* message, const FieldDescriptor* field, CMessage* target); diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index cdb64269..ac06cff3 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -104,7 +104,8 @@ static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) { if (arg == NULL) { ScopedPyObjectPtr py_index(PyLong_FromLong(index)); - return cmessage::InternalDeleteRepeatedField(self->parent, field_descriptor, + return cmessage::InternalDeleteRepeatedField(self->message, + field_descriptor, py_index.get(), NULL); } @@ -467,7 +468,7 @@ static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) { if (value == NULL) { return cmessage::InternalDeleteRepeatedField( - self->parent, field_descriptor, slice, NULL); + self->message, field_descriptor, slice, nullptr); } if (!create_list) { diff --git a/python/google/protobuf/pyext/safe_numerics.h b/python/google/protobuf/pyext/safe_numerics.h index 60112cfa..93ae640e 100644 --- a/python/google/protobuf/pyext/safe_numerics.h +++ b/python/google/protobuf/pyext/safe_numerics.h @@ -132,10 +132,10 @@ template <class Dest, class Source> inline bool IsValidNumericCast(Source source) { typedef std::numeric_limits<Source> SourceLimits; typedef std::numeric_limits<Dest> DestLimits; - GOOGLE_COMPILE_ASSERT(SourceLimits::is_specialized, argument_must_be_numeric); - GOOGLE_COMPILE_ASSERT(SourceLimits::is_integer, argument_must_be_integral); - GOOGLE_COMPILE_ASSERT(DestLimits::is_specialized, result_must_be_numeric); - GOOGLE_COMPILE_ASSERT(DestLimits::is_integer, result_must_be_integral); + static_assert(SourceLimits::is_specialized, "argument must be numeric"); + static_assert(SourceLimits::is_integer, "argument must be integral"); + static_assert(DestLimits::is_specialized, "result must be numeric"); + static_assert(DestLimits::is_integer, "result must be integral"); return IsValidNumericCastImpl< sizeof(Dest) == sizeof(Source), @@ -150,7 +150,7 @@ inline bool IsValidNumericCast(Source source) { // checked_numeric_cast<> is analogous to static_cast<> for numeric types, // except that it CHECKs that the specified numeric conversion will not // overflow or underflow. Floating point arguments are not currently allowed -// (this is COMPILE_ASSERTd), though this could be supported if necessary. +// (this is static_asserted), though this could be supported if necessary. template <class Dest, class Source> inline Dest checked_numeric_cast(Source source) { GOOGLE_CHECK(IsValidNumericCast<Dest>(source)); diff --git a/python/google/protobuf/pyext/unknown_fields.h b/python/google/protobuf/pyext/unknown_fields.h index 94d55e14..a2619551 100755 --- a/python/google/protobuf/pyext/unknown_fields.h +++ b/python/google/protobuf/pyext/unknown_fields.h @@ -34,6 +34,7 @@ #include <Python.h> #include <memory> +#include <hash_map> #include <set> #include <google/protobuf/pyext/message.h> diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index 5dd41830..998cd681 100755 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -155,7 +155,7 @@ def MessageToString(message, (per the "Format Specification Mini-Language"); otherwise, str() is used. use_field_number: If True, print field numbers instead of names. descriptor_pool: A DescriptorPool used to resolve Any types. - indent: The indent level, in terms of spaces, for pretty print. + indent: The initial indent level, in terms of spaces, for pretty print. message_formatter: A function(message, indent, as_one_line): unicode|None to custom format selected sub-messages (usually based on message type). Use to pretty print parts of the protobuf for easier diffing. @@ -296,7 +296,7 @@ class _Printer(object): Args: out: To record the text format result. - indent: The indent level for pretty print. + indent: The initial indent level for pretty print. as_utf8: Return unescaped Unicode for non-ASCII characters. In Python 3 actual Unicode characters may appear as is in strings. In Python 2 the return value will be valid UTF-8 rather than ASCII. @@ -330,11 +330,13 @@ class _Printer(object): def _TryPrintAsAnyMessage(self, message): """Serializes if message is a google.protobuf.Any field.""" + if '/' not in message.type_url: + return False packed_message = _BuildMessageFromTypeName(message.TypeName(), self.descriptor_pool) if packed_message: packed_message.MergeFromString(message.value) - self.out.write('%s[%s]' % (self.indent * ' ', message.type_url)) + self.out.write('%s[%s] ' % (self.indent * ' ', message.type_url)) self._PrintMessageFieldValue(packed_message) self.out.write(' ' if self.as_one_line else '\n') return True @@ -413,11 +415,12 @@ class _Printer(object): if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE: # The colon is optional in this case, but our cross-language golden files # don't include it. - out.write(': ') + out.write(':') def PrintField(self, field, value): """Print a single field name/value pair.""" self._PrintFieldName(field) + self.out.write(' ') self.PrintFieldValue(field, value) self.out.write(' ' if self.as_one_line else '\n') @@ -441,11 +444,11 @@ class _Printer(object): closeb = '}' if self.as_one_line: - self.out.write(' %s ' % openb) + self.out.write('%s ' % openb) self.PrintMessage(value) self.out.write(closeb) else: - self.out.write(' %s\n' % openb) + self.out.write('%s\n' % openb) self.indent += 2 self.PrintMessage(value) self.indent -= 2 |