aboutsummaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2018-09-04 10:58:54 -0700
committerJosh Haberman <jhaberman@gmail.com>2018-09-04 10:58:54 -0700
commitd61aede89cf188367766b971f59cf57d7835d8e8 (patch)
treea19842c62c3c8f51389912ecafdf932d0a572bea /python
parent45d03a977193d1dcce5251e4bffe17bf0ba738ec (diff)
downloadprotobuf-d61aede89cf188367766b971f59cf57d7835d8e8.tar.gz
protobuf-d61aede89cf188367766b971f59cf57d7835d8e8.tar.bz2
protobuf-d61aede89cf188367766b971f59cf57d7835d8e8.zip
Down-integrate from google3.
Diffstat (limited to 'python')
-rw-r--r--python/google/protobuf/descriptor_database.py6
-rwxr-xr-xpython/google/protobuf/internal/decoder.py3
-rw-r--r--python/google/protobuf/internal/descriptor_database_test.py5
-rwxr-xr-xpython/google/protobuf/internal/message_test.py19
-rwxr-xr-xpython/google/protobuf/internal/python_message.py9
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py4
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py100
-rw-r--r--python/google/protobuf/internal/well_known_types.py15
-rw-r--r--python/google/protobuf/internal/well_known_types_test.py37
-rw-r--r--python/google/protobuf/pyext/descriptor_database.h8
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.h2
-rw-r--r--python/google/protobuf/pyext/message.cc36
-rw-r--r--python/google/protobuf/pyext/message.h6
-rw-r--r--python/google/protobuf/pyext/message_module.cc2
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc12
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.h2
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc5
-rw-r--r--python/google/protobuf/pyext/safe_numerics.h10
-rwxr-xr-xpython/google/protobuf/pyext/unknown_fields.h1
-rwxr-xr-xpython/google/protobuf/text_format.py15
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