Commit 3ff56252 authored by Joshua Haberman's avatar Joshua Haberman

Merge pull request #722 from dano/py2_py3_straddle

Add tox, Python 2.6 compatibility, and many Python 3 compatibility fixes
parents eb65c69e 46969b99
......@@ -55,6 +55,7 @@ src/google/protobuf/util/**/*.pb.h
*_pb2.py
python/*.egg
python/.eggs/
python/.tox
python/build/
python/google/protobuf/compiler/
......
......@@ -538,7 +538,6 @@ python_EXTRA_DIST= \
python/google/protobuf/text_format.py \
python/google/protobuf/__init__.py \
python/google/__init__.py \
python/ez_setup.py \
python/setup.py \
python/mox.py \
python/stubout.py \
......
This diff is collapsed.
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Needs to stay compatible with Python 2.5 due to GAE.
#
# Copyright 2007 Google Inc. All Rights Reserved.
__version__ = '3.0.0a4.dev0'
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Needs to stay compatible with Python 2.5 due to GAE.
#
# Copyright 2007 Google Inc. All Rights Reserved.
"""Descriptors essentially contain exactly the information found in a .proto
......@@ -918,5 +916,5 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
desc_name = '.'.join(full_message_name)
return Descriptor(desc_proto.name, desc_name, None, None, fields,
nested_types.values(), enum_types.values(), [],
list(nested_types.values()), list(enum_types.values()), [],
options=desc_proto.options)
......@@ -149,9 +149,14 @@ import collections
import functools
import re
import types
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
import uuid
import six
ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
_SEPARATOR = uuid.uuid1().hex
_FIRST_ARG = object()
......@@ -170,13 +175,13 @@ def _StrClass(cls):
def _NonStringIterable(obj):
return (isinstance(obj, collections.Iterable) and not
isinstance(obj, basestring))
isinstance(obj, six.string_types))
def _FormatParameterList(testcase_params):
if isinstance(testcase_params, collections.Mapping):
return ', '.join('%s=%s' % (argname, _CleanRepr(value))
for argname, value in testcase_params.iteritems())
for argname, value in testcase_params.items())
elif _NonStringIterable(testcase_params):
return ', '.join(map(_CleanRepr, testcase_params))
else:
......@@ -258,7 +263,9 @@ def _ModifyClass(class_object, testcases, naming_type):
'Cannot add parameters to %s,'
' which already has parameterized methods.' % (class_object,))
class_object._id_suffix = id_suffix = {}
for name, obj in class_object.__dict__.items():
# We change the size of __dict__ while we iterate over it,
# which Python 3.x will complain about, so use copy().
for name, obj in class_object.__dict__.copy().items():
if (name.startswith(unittest.TestLoader.testMethodPrefix)
and isinstance(obj, types.FunctionType)):
delattr(class_object, name)
......@@ -266,7 +273,7 @@ def _ModifyClass(class_object, testcases, naming_type):
_UpdateClassDictForParamTestCase(
methods, id_suffix, name,
_ParameterizedTestIter(obj, testcases, naming_type))
for name, meth in methods.iteritems():
for name, meth in methods.items():
setattr(class_object, name, meth)
......
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#PY25 compatible for GAE.
#
# Copyright 2009 Google Inc. All Rights Reserved.
"""Code for decoding protocol buffer primitives.
......@@ -85,8 +83,12 @@ we repeatedly read a tag, look up the corresponding decoder, and invoke it.
__author__ = 'kenton@google.com (Kenton Varda)'
import struct
import sys ##PY25
_PY2 = sys.version_info[0] < 3 ##PY25
import six
if six.PY3:
long = int
from google.protobuf.internal import encoder
from google.protobuf.internal import wire_format
from google.protobuf import message
......@@ -114,14 +116,11 @@ def _VarintDecoder(mask, result_type):
decoder returns a (value, new_pos) pair.
"""
local_ord = ord
py2 = _PY2 ##PY25
##!PY25 py2 = str is bytes
def DecodeVarint(buffer, pos):
result = 0
shift = 0
while 1:
b = local_ord(buffer[pos]) if py2 else buffer[pos]
b = six.indexbytes(buffer, pos)
result |= ((b & 0x7f) << shift)
pos += 1
if not (b & 0x80):
......@@ -137,14 +136,11 @@ def _VarintDecoder(mask, result_type):
def _SignedVarintDecoder(mask, result_type):
"""Like _VarintDecoder() but decodes signed values."""
local_ord = ord
py2 = _PY2 ##PY25
##!PY25 py2 = str is bytes
def DecodeVarint(buffer, pos):
result = 0
shift = 0
while 1:
b = local_ord(buffer[pos]) if py2 else buffer[pos]
b = six.indexbytes(buffer, pos)
result |= ((b & 0x7f) << shift)
pos += 1
if not (b & 0x80):
......@@ -183,10 +179,8 @@ def ReadTag(buffer, pos):
use that, but not in Python.
"""
py2 = _PY2 ##PY25
##!PY25 py2 = str is bytes
start = pos
while (ord(buffer[pos]) if py2 else buffer[pos]) & 0x80:
while six.indexbytes(buffer, pos) & 0x80:
pos += 1
pos += 1
return (buffer[start:pos], pos)
......@@ -301,7 +295,6 @@ def _FloatDecoder():
"""
local_unpack = struct.unpack
b = (lambda x:x) if _PY2 else lambda x:x.encode('latin1') ##PY25
def InnerDecode(buffer, pos):
# We expect a 32-bit value in little-endian byte order. Bit 1 is the sign
......@@ -312,17 +305,12 @@ def _FloatDecoder():
# If this value has all its exponent bits set, then it's non-finite.
# In Python 2.4, struct.unpack will convert it to a finite 64-bit value.
# To avoid that, we parse it specially.
if ((float_bytes[3:4] in b('\x7F\xFF')) ##PY25
##!PY25 if ((float_bytes[3:4] in b'\x7F\xFF')
and (float_bytes[2:3] >= b('\x80'))): ##PY25
##!PY25 and (float_bytes[2:3] >= b'\x80')):
if (float_bytes[3:4] in b'\x7F\xFF' and float_bytes[2:3] >= b'\x80'):
# If at least one significand bit is set...
if float_bytes[0:3] != b('\x00\x00\x80'): ##PY25
##!PY25 if float_bytes[0:3] != b'\x00\x00\x80':
if float_bytes[0:3] != b'\x00\x00\x80':
return (_NAN, new_pos)
# If sign bit is set...
if float_bytes[3:4] == b('\xFF'): ##PY25
##!PY25 if float_bytes[3:4] == b'\xFF':
if float_bytes[3:4] == b'\xFF':
return (_NEG_INF, new_pos)
return (_POS_INF, new_pos)
......@@ -341,7 +329,6 @@ def _DoubleDecoder():
"""
local_unpack = struct.unpack
b = (lambda x:x) if _PY2 else lambda x:x.encode('latin1') ##PY25
def InnerDecode(buffer, pos):
# We expect a 64-bit value in little-endian byte order. Bit 1 is the sign
......@@ -352,12 +339,9 @@ def _DoubleDecoder():
# If this value has all its exponent bits set and at least one significand
# bit set, it's not a number. In Python 2.4, struct.unpack will treat it
# as inf or -inf. To avoid that, we treat it specially.
##!PY25 if ((double_bytes[7:8] in b'\x7F\xFF')
##!PY25 and (double_bytes[6:7] >= b'\xF0')
##!PY25 and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')):
if ((double_bytes[7:8] in b('\x7F\xFF')) ##PY25
and (double_bytes[6:7] >= b('\xF0')) ##PY25
and (double_bytes[0:7] != b('\x00\x00\x00\x00\x00\x00\xF0'))): ##PY25
if ((double_bytes[7:8] in b'\x7F\xFF')
and (double_bytes[6:7] >= b'\xF0')
and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')):
return (_NAN, new_pos)
# Note that we expect someone up-stack to catch struct.error and convert
......@@ -480,12 +464,12 @@ def StringDecoder(field_number, is_repeated, is_packed, key, new_default):
"""Returns a decoder for a string field."""
local_DecodeVarint = _DecodeVarint
local_unicode = unicode
local_unicode = six.text_type
def _ConvertToUnicode(byte_str):
try:
return local_unicode(byte_str, 'utf-8')
except UnicodeDecodeError, e:
except UnicodeDecodeError as e:
# add more information to the error message and re-raise it.
e.reason = '%s in field: %s' % (e, key.full_name)
raise
......
......@@ -34,7 +34,10 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import descriptor_pb2
from google.protobuf.internal import factory_test2_pb2
from google.protobuf import descriptor_database
......@@ -48,17 +51,17 @@ class DescriptorDatabaseTest(unittest.TestCase):
factory_test2_pb2.DESCRIPTOR.serialized_pb)
db.Add(file_desc_proto)
self.assertEquals(file_desc_proto, db.FindFileByName(
self.assertEqual(file_desc_proto, db.FindFileByName(
'google/protobuf/internal/factory_test2.proto'))
self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Message'))
self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Message.NestedFactory2Message'))
self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Enum'))
self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum'))
self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
self.assertEqual(file_desc_proto, db.FindFileContainingSymbol(
'google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum'))
if __name__ == '__main__':
......
#! /usr/bin/env python
#! /usr/bin/python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
......@@ -36,7 +36,6 @@ __author__ = 'robinson@google.com (Will Robinson)'
import sys
import unittest
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
......@@ -46,6 +45,11 @@ from google.protobuf import descriptor
from google.protobuf import symbol_database
from google.protobuf import text_format
try:
import unittest2 as unittest
except ImportError:
import unittest
TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
name: 'TestEmptyMessage'
......@@ -455,7 +459,7 @@ class GeneratedDescriptorTest(unittest.TestCase):
# properties of an immutable abc.Mapping.
self.assertGreater(len(mapping), 0) # Sized
self.assertEqual(len(mapping), len(list(mapping))) # Iterable
if sys.version_info.major >= 3:
if sys.version_info >= (3,):
key, item = next(iter(mapping.items()))
else:
key, item = mapping.items()[0]
......@@ -464,7 +468,7 @@ class GeneratedDescriptorTest(unittest.TestCase):
# keys(), iterkeys() &co
item = (next(iter(mapping.keys())), next(iter(mapping.values())))
self.assertEqual(item, next(iter(mapping.items())))
if sys.version_info.major < 3:
if sys.version_info < (3,):
def CheckItems(seq, iterator):
self.assertEqual(next(iterator), seq[0])
self.assertEqual(list(iterator), seq[1:])
......@@ -772,7 +776,7 @@ class MakeDescriptorTest(unittest.TestCase):
reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto)
options = reformed_descriptor.GetOptions()
self.assertEquals(101,
self.assertEqual(101,
options.Extensions[unittest_custom_options_pb2.msgopt].i)
if __name__ == '__main__':
......
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#PY25 compatible for GAE.
#
# Copyright 2009 Google Inc. All Rights Reserved.
"""Code for encoding protocol message primitives.
......@@ -45,7 +43,7 @@ FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The
sizer takes a value of this field's type and computes its byte size. The
encoder takes a writer function and a value. It encodes the value into byte
strings and invokes the writer function to write those strings. Typically the
writer function is the write() method of a cStringIO.
writer function is the write() method of a BytesIO.
We try to do as much work as possible when constructing the writer and the
sizer rather than when calling them. In particular:
......@@ -71,8 +69,9 @@ sizer rather than when calling them. In particular:
__author__ = 'kenton@google.com (Kenton Varda)'
import struct
import sys ##PY25
_PY2 = sys.version_info[0] < 3 ##PY25
import six
from google.protobuf.internal import wire_format
......@@ -372,16 +371,14 @@ def MapSizer(field_descriptor):
def _VarintEncoder():
"""Return an encoder for a basic varint value (does not include tag)."""
local_chr = _PY2 and chr or (lambda x: bytes((x,))) ##PY25
##!PY25 local_chr = chr if bytes is str else lambda x: bytes((x,))
def EncodeVarint(write, value):
bits = value & 0x7f
value >>= 7
while value:
write(local_chr(0x80|bits))
write(six.int2byte(0x80|bits))
bits = value & 0x7f
value >>= 7
return write(local_chr(bits))
return write(six.int2byte(bits))
return EncodeVarint
......@@ -390,18 +387,16 @@ def _SignedVarintEncoder():
"""Return an encoder for a basic signed varint value (does not include
tag)."""
local_chr = _PY2 and chr or (lambda x: bytes((x,))) ##PY25
##!PY25 local_chr = chr if bytes is str else lambda x: bytes((x,))
def EncodeSignedVarint(write, value):
if value < 0:
value += (1 << 64)
bits = value & 0x7f
value >>= 7
while value:
write(local_chr(0x80|bits))
write(six.int2byte(0x80|bits))
bits = value & 0x7f
value >>= 7
return write(local_chr(bits))
return write(six.int2byte(bits))
return EncodeSignedVarint
......@@ -416,8 +411,7 @@ def _VarintBytes(value):
pieces = []
_EncodeVarint(pieces.append, value)
return "".encode("latin1").join(pieces) ##PY25
##!PY25 return b"".join(pieces)
return b"".join(pieces)
def TagBytes(field_number, wire_type):
......@@ -555,33 +549,26 @@ def _FloatingPointEncoder(wire_type, format):
format: The format string to pass to struct.pack().
"""
b = _PY2 and (lambda x:x) or (lambda x:x.encode('latin1')) ##PY25
value_size = struct.calcsize(format)
if value_size == 4:
def EncodeNonFiniteOrRaise(write, value):
# Remember that the serialized form uses little-endian byte order.
if value == _POS_INF:
write(b('\x00\x00\x80\x7F')) ##PY25
##!PY25 write(b'\x00\x00\x80\x7F')
write(b'\x00\x00\x80\x7F')
elif value == _NEG_INF:
write(b('\x00\x00\x80\xFF')) ##PY25
##!PY25 write(b'\x00\x00\x80\xFF')
write(b'\x00\x00\x80\xFF')
elif value != value: # NaN
write(b('\x00\x00\xC0\x7F')) ##PY25
##!PY25 write(b'\x00\x00\xC0\x7F')
write(b'\x00\x00\xC0\x7F')
else:
raise
elif value_size == 8:
def EncodeNonFiniteOrRaise(write, value):
if value == _POS_INF:
write(b('\x00\x00\x00\x00\x00\x00\xF0\x7F')) ##PY25
##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F')
write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F')
elif value == _NEG_INF:
write(b('\x00\x00\x00\x00\x00\x00\xF0\xFF')) ##PY25
##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF')
write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF')
elif value != value: # NaN
write(b('\x00\x00\x00\x00\x00\x00\xF8\x7F')) ##PY25
##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F')
write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F')
else:
raise
else:
......@@ -657,10 +644,8 @@ DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
def BoolEncoder(field_number, is_repeated, is_packed):
"""Returns an encoder for a boolean field."""
##!PY25 false_byte = b'\x00'
##!PY25 true_byte = b'\x01'
false_byte = '\x00'.encode('latin1') ##PY25
true_byte = '\x01'.encode('latin1') ##PY25
false_byte = b'\x00'
true_byte = b'\x01'
if is_packed:
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
local_EncodeVarint = _EncodeVarint
......@@ -796,8 +781,7 @@ def MessageSetItemEncoder(field_number):
}
}
"""
start_bytes = "".encode("latin1").join([ ##PY25
##!PY25 start_bytes = b"".join([
start_bytes = b"".join([
TagBytes(1, wire_format.WIRETYPE_START_GROUP),
TagBytes(2, wire_format.WIRETYPE_VARINT),
_VarintBytes(field_number),
......
......@@ -41,7 +41,10 @@ further ensures that we can use Python protocol message objects as we expect.
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf.internal import test_bad_identifiers_pb2
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
......@@ -153,7 +156,7 @@ class GeneratorTest(unittest.TestCase):
# extension and for its value to be set to -789.
def testNestedTypes(self):
self.assertEquals(
self.assertEqual(
set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types),
set([
unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
......@@ -291,10 +294,10 @@ class GeneratorTest(unittest.TestCase):
self.assertIs(desc.oneofs[0], desc.oneofs_by_name['oneof_field'])
nested_names = set(['oneof_uint32', 'oneof_nested_message',
'oneof_string', 'oneof_bytes'])
self.assertItemsEqual(
self.assertEqual(
nested_names,
[field.name for field in desc.oneofs[0].fields])
for field_name, field_desc in desc.fields_by_name.iteritems():
set([field.name for field in desc.oneofs[0].fields]))
for field_name, field_desc in desc.fields_by_name.items():
if field_name in nested_names:
self.assertIs(desc.oneofs[0], field_desc.containing_oneof)
else:
......@@ -305,36 +308,36 @@ class SymbolDatabaseRegistrationTest(unittest.TestCase):
"""Checks that messages, enums and files are correctly registered."""
def testGetSymbol(self):
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes, symbol_database.Default().GetSymbol(
'protobuf_unittest.TestAllTypes'))
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes.NestedMessage,
symbol_database.Default().GetSymbol(
'protobuf_unittest.TestAllTypes.NestedMessage'))
with self.assertRaises(KeyError):
symbol_database.Default().GetSymbol('protobuf_unittest.NestedMessage')
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes.OptionalGroup,
symbol_database.Default().GetSymbol(
'protobuf_unittest.TestAllTypes.OptionalGroup'))
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes.RepeatedGroup,
symbol_database.Default().GetSymbol(
'protobuf_unittest.TestAllTypes.RepeatedGroup'))
def testEnums(self):
self.assertEquals(
self.assertEqual(
'protobuf_unittest.ForeignEnum',
symbol_database.Default().pool.FindEnumTypeByName(
'protobuf_unittest.ForeignEnum').full_name)
self.assertEquals(
self.assertEqual(
'protobuf_unittest.TestAllTypes.NestedEnum',
symbol_database.Default().pool.FindEnumTypeByName(
'protobuf_unittest.TestAllTypes.NestedEnum').full_name)
def testFindFileByName(self):
self.assertEquals(
self.assertEqual(
'google/protobuf/unittest.proto',
symbol_database.Default().pool.FindFileByName(
'google/protobuf/unittest.proto').name)
......
......@@ -34,7 +34,10 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import descriptor_pb2
from google.protobuf.internal import factory_test1_pb2
from google.protobuf.internal import factory_test2_pb2
......@@ -81,9 +84,9 @@ class MessageFactoryTest(unittest.TestCase):
serialized = msg.SerializeToString()
converted = factory_test2_pb2.Factory2Message.FromString(serialized)
reserialized = converted.SerializeToString()
self.assertEquals(serialized, reserialized)
self.assertEqual(serialized, reserialized)
result = cls.FromString(reserialized)
self.assertEquals(msg, result)
self.assertEqual(msg, result)
def testGetPrototype(self):
db = descriptor_database.DescriptorDatabase()
......@@ -93,11 +96,11 @@ class MessageFactoryTest(unittest.TestCase):
factory = message_factory.MessageFactory()
cls = factory.GetPrototype(pool.FindMessageTypeByName(
'google.protobuf.python.internal.Factory2Message'))
self.assertIsNot(cls, factory_test2_pb2.Factory2Message)
self.assertFalse(cls is factory_test2_pb2.Factory2Message)
self._ExerciseDynamicClass(cls)
cls2 = factory.GetPrototype(pool.FindMessageTypeByName(
'google.protobuf.python.internal.Factory2Message'))
self.assertIs(cls, cls2)
self.assertTrue(cls is cls2)
def testGetMessages(self):
# performed twice because multiple calls with the same input must be allowed
......@@ -124,8 +127,8 @@ class MessageFactoryTest(unittest.TestCase):
'google.protobuf.python.internal.another_field']
msg1.Extensions[ext1] = 'test1'
msg1.Extensions[ext2] = 'test2'
self.assertEquals('test1', msg1.Extensions[ext1])
self.assertEquals('test2', msg1.Extensions[ext2])
self.assertEqual('test1', msg1.Extensions[ext1])
self.assertEqual('test2', msg1.Extensions[ext2])
if __name__ == '__main__':
......
......@@ -48,9 +48,16 @@ import math
import operator
import pickle
import sys
import unittest
import unittest
import six
if six.PY3:
long = int
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf.internal import _parameterized
from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_pb2
......@@ -320,7 +327,7 @@ class MessageTest(unittest.TestCase):
def testHighPrecisionFloatPrinting(self, message_module):
message = message_module.TestAllTypes()
message.optional_double = 0.12345678912345678
if sys.version_info.major >= 3:
if sys.version_info >= (3,):
self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n')
else:
self.assertEqual(str(message), 'optional_double: 0.123456789123\n')
......@@ -439,7 +446,7 @@ class MessageTest(unittest.TestCase):
message.repeated_nested_message.sort(key=get_bb, reverse=True)
self.assertEqual([k.bb for k in message.repeated_nested_message],
[6, 5, 4, 3, 2, 1])
if sys.version_info.major >= 3: return # No cmp sorting in PY3.
if sys.version_info >= (3,): return # No cmp sorting in PY3.
message.repeated_nested_message.sort(sort_function=cmp_bb)
self.assertEqual([k.bb for k in message.repeated_nested_message],
[1, 2, 3, 4, 5, 6])
......@@ -458,7 +465,7 @@ class MessageTest(unittest.TestCase):
self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
message.repeated_int32.sort(key=abs, reverse=True)
self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
if sys.version_info.major < 3: # No cmp sorting in PY3.
if sys.version_info < (3,): # No cmp sorting in PY3.
abs_cmp = lambda a, b: cmp(abs(a), abs(b))
message.repeated_int32.sort(sort_function=abs_cmp)
self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
......@@ -472,7 +479,7 @@ class MessageTest(unittest.TestCase):
self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
message.repeated_string.sort(key=len, reverse=True)
self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
if sys.version_info.major < 3: # No cmp sorting in PY3.
if sys.version_info < (3,): # No cmp sorting in PY3.
len_cmp = lambda a, b: cmp(len(a), len(b))
message.repeated_string.sort(sort_function=len_cmp)
self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
......@@ -495,7 +502,7 @@ class MessageTest(unittest.TestCase):
m2.repeated_nested_message.add().bb = 2
m2.repeated_nested_message.add().bb = 3
if sys.version_info.major >= 3: return # No cmp() in PY3.
if sys.version_info >= (3,): return # No cmp() in PY3.
# These comparisons should not raise errors.
_ = m1 < m2
......@@ -676,7 +683,7 @@ class MessageTest(unittest.TestCase):
in the value being converted to a Unicode string."""
m = message_module.TestAllTypes()
m.optional_string = str('')
self.assertTrue(isinstance(m.optional_string, unicode))
self.assertTrue(isinstance(m.optional_string, six.text_type))
# TODO(haberman): why are these tests Google-internal only?
......@@ -1229,7 +1236,7 @@ class Proto3Test(unittest.TestCase):
self.assertTrue('abc' in msg.map_string_string)
self.assertTrue(888 in msg.map_int32_enum)
self.assertTrue(isinstance(msg.map_string_string['abc'], unicode))
self.assertTrue(isinstance(msg.map_string_string['abc'], six.text_type))
# Accessing an unset key still throws TypeError of the type of the key
# is incorrect.
......@@ -1244,14 +1251,14 @@ class Proto3Test(unittest.TestCase):
msg = map_unittest_pb2.TestMap()
self.assertIsNone(msg.map_int32_int32.get(5))
self.assertEquals(10, msg.map_int32_int32.get(5, 10))
self.assertEqual(10, msg.map_int32_int32.get(5, 10))
self.assertIsNone(msg.map_int32_int32.get(5))
msg.map_int32_int32[5] = 15
self.assertEquals(15, msg.map_int32_int32.get(5))
self.assertEqual(15, msg.map_int32_int32.get(5))
self.assertIsNone(msg.map_int32_foreign_message.get(5))
self.assertEquals(10, msg.map_int32_foreign_message.get(5, 10))
self.assertEqual(10, msg.map_int32_foreign_message.get(5, 10))
submsg = msg.map_int32_foreign_message[5]
self.assertIs(submsg, msg.map_int32_foreign_message.get(5))
......@@ -1312,13 +1319,13 @@ class Proto3Test(unittest.TestCase):
msg.map_string_string[bytes_obj] = bytes_obj
(key, value) = msg.map_string_string.items()[0]
(key, value) = list(msg.map_string_string.items())[0]
self.assertEqual(key, unicode_obj)
self.assertEqual(value, unicode_obj)
self.assertTrue(isinstance(key, unicode))
self.assertTrue(isinstance(value, unicode))
self.assertTrue(isinstance(key, six.text_type))
self.assertTrue(isinstance(value, six.text_type))
def testMessageMap(self):
msg = map_unittest_pb2.TestMap()
......@@ -1503,7 +1510,7 @@ class Proto3Test(unittest.TestCase):
def testMapIteration(self):
msg = map_unittest_pb2.TestMap()
for k, v in msg.map_int32_int32.iteritems():
for k, v in msg.map_int32_int32.items():
# Should not be reached.
self.assertTrue(False)
......@@ -1513,7 +1520,7 @@ class Proto3Test(unittest.TestCase):
self.assertEqual(3, len(msg.map_int32_int32))
matching_dict = {2: 4, 3: 6, 4: 8}
self.assertMapIterEquals(msg.map_int32_int32.iteritems(), matching_dict)
self.assertMapIterEquals(msg.map_int32_int32.items(), matching_dict)
def testMapIterationClearMessage(self):
# Iterator needs to work even if message and map are deleted.
......@@ -1523,7 +1530,7 @@ class Proto3Test(unittest.TestCase):
msg.map_int32_int32[3] = 6
msg.map_int32_int32[4] = 8
it = msg.map_int32_int32.iteritems()
it = msg.map_int32_int32.items()
del msg
matching_dict = {2: 4, 3: 6, 4: 8}
......@@ -1551,7 +1558,7 @@ class Proto3Test(unittest.TestCase):
msg.ClearField('map_int32_int32')
matching_dict = {2: 4, 3: 6, 4: 8}
self.assertMapIterEquals(map.iteritems(), matching_dict)
self.assertMapIterEquals(map.items(), matching_dict)
def testMapIterValidAfterFieldCleared(self):
# Map iterator needs to work even if field is cleared.
......@@ -1563,7 +1570,7 @@ class Proto3Test(unittest.TestCase):
msg.map_int32_int32[3] = 6
msg.map_int32_int32[4] = 8
it = msg.map_int32_int32.iteritems()
it = msg.map_int32_int32.items()
msg.ClearField('map_int32_int32')
matching_dict = {2: 4, 3: 6, 4: 8}
......
......@@ -32,8 +32,15 @@
"""Tests for google.protobuf.proto_builder."""
import collections
import unittest
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict #PY26
try:
import unittest2 as unittest #PY26
except ImportError:
import unittest
from google.protobuf import descriptor_pb2
from google.protobuf import descriptor_pool
......@@ -44,7 +51,7 @@ from google.protobuf import text_format
class ProtoBuilderTest(unittest.TestCase):
def setUp(self):
self.ordered_fields = collections.OrderedDict([
self.ordered_fields = OrderedDict([
('foo', descriptor_pb2.FieldDescriptorProto.TYPE_INT64),
('bar', descriptor_pb2.FieldDescriptorProto.TYPE_STRING),
])
......
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Keep it Python2.5 compatible for GAE.
#
# Copyright 2007 Google Inc. All Rights Reserved.
#
# This code is meant to work on Python 2.4 and above only.
......@@ -54,21 +52,14 @@ this file*.
__author__ = 'robinson@google.com (Will Robinson)'
from io import BytesIO
import sys
if sys.version_info[0] < 3:
try:
from cStringIO import StringIO as BytesIO
except ImportError:
from StringIO import StringIO as BytesIO
import copy_reg as copyreg
_basestring = basestring
else:
from io import BytesIO
import copyreg
_basestring = str
import struct
import weakref
import six
import six.moves.copyreg as copyreg
# We use "as" to avoid name collisions with variables.
from google.protobuf.internal import containers
from google.protobuf.internal import decoder
......@@ -281,7 +272,7 @@ def _AttachFieldHelpers(cls, field_descriptor):
def _AddClassAttributesForNestedExtensions(descriptor, dictionary):
extension_dict = descriptor.extensions_by_name
for extension_name, extension_field in extension_dict.iteritems():
for extension_name, extension_field in extension_dict.items():
assert extension_name not in dictionary
dictionary[extension_name] = extension_field
......@@ -383,7 +374,7 @@ def _ReraiseTypeErrorWithFieldName(message_name, field_name):
exc = TypeError('%s for field %s.%s' % (str(exc), message_name, field_name))
# re-raise possibly-amended exception with original traceback:
raise type(exc)(exc, sys.exc_info()[2])
six.reraise(type(exc), exc, sys.exc_info()[2])
def _AddInitMethod(message_descriptor, cls):
......@@ -396,7 +387,7 @@ def _AddInitMethod(message_descriptor, cls):
enum_type with the same name. If the value is not a string, it's
returned as-is. (No conversion or bounds-checking is done.)
"""
if isinstance(value, _basestring):
if isinstance(value, six.string_types):
try:
return enum_type.values_by_name[value].number
except KeyError:
......@@ -418,7 +409,7 @@ def _AddInitMethod(message_descriptor, cls):
self._is_present_in_parent = False
self._listener = message_listener_mod.NullMessageListener()
self._listener_for_children = _Listener(self)
for field_name, field_value in kwargs.iteritems():
for field_name, field_value in kwargs.items():
field = _GetFieldByName(message_descriptor, field_name)
if field is None:
raise TypeError("%s() got an unexpected keyword argument '%s'" %
......@@ -675,7 +666,7 @@ def _AddPropertiesForNonRepeatedCompositeField(field, cls):
def _AddPropertiesForExtensions(descriptor, cls):
"""Adds properties for all fields in this protocol message type."""
extension_dict = descriptor.extensions_by_name
for extension_name, extension_field in extension_dict.iteritems():
for extension_name, extension_field in extension_dict.items():
constant_name = extension_name.upper() + "_FIELD_NUMBER"
setattr(cls, constant_name, extension_field.number)
......@@ -730,7 +721,7 @@ def _AddListFieldsMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def ListFields(self):
all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)]
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
all_fields.sort(key = lambda item: item[0].number)
return all_fields
......@@ -1128,7 +1119,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
# ScalarMaps can't have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in xrange(len(value)):
for i in range(len(value)):
element = value[i]
prefix = "%s[%d]." % (name, i)
sub_errors = element.FindInitializationErrors()
......@@ -1158,7 +1149,7 @@ def _AddMergeFromMethod(cls):
fields = self._fields
for field, value in msg._fields.iteritems():
for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
field_value = fields.get(field)
if field_value is None:
......
......@@ -34,7 +34,10 @@
__author__ = 'petar@google.com (Petar Petrov)'
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import unittest_pb2
from google.protobuf import service_reflection
from google.protobuf import service
......
......@@ -32,7 +32,10 @@
"""Tests for google.protobuf.symbol_database."""
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import unittest_pb2
from google.protobuf import symbol_database
......@@ -64,53 +67,53 @@ class SymbolDatabaseTest(unittest.TestCase):
messages['protobuf_unittest.TestAllTypes'])
def testGetSymbol(self):
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes, self._Database().GetSymbol(
'protobuf_unittest.TestAllTypes'))
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes.NestedMessage, self._Database().GetSymbol(
'protobuf_unittest.TestAllTypes.NestedMessage'))
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes.OptionalGroup, self._Database().GetSymbol(
'protobuf_unittest.TestAllTypes.OptionalGroup'))
self.assertEquals(
self.assertEqual(
unittest_pb2.TestAllTypes.RepeatedGroup, self._Database().GetSymbol(
'protobuf_unittest.TestAllTypes.RepeatedGroup'))
def testEnums(self):
# Check registration of types in the pool.
self.assertEquals(
self.assertEqual(
'protobuf_unittest.ForeignEnum',
self._Database().pool.FindEnumTypeByName(
'protobuf_unittest.ForeignEnum').full_name)
self.assertEquals(
self.assertEqual(
'protobuf_unittest.TestAllTypes.NestedEnum',
self._Database().pool.FindEnumTypeByName(
'protobuf_unittest.TestAllTypes.NestedEnum').full_name)
def testFindMessageTypeByName(self):
self.assertEquals(
self.assertEqual(
'protobuf_unittest.TestAllTypes',
self._Database().pool.FindMessageTypeByName(
'protobuf_unittest.TestAllTypes').full_name)
self.assertEquals(
self.assertEqual(
'protobuf_unittest.TestAllTypes.NestedMessage',
self._Database().pool.FindMessageTypeByName(
'protobuf_unittest.TestAllTypes.NestedMessage').full_name)
def testFindFindContainingSymbol(self):
# Lookup based on either enum or message.
self.assertEquals(
self.assertEqual(
'google/protobuf/unittest.proto',
self._Database().pool.FindFileContainingSymbol(
'protobuf_unittest.TestAllTypes.NestedEnum').name)
self.assertEquals(
self.assertEqual(
'google/protobuf/unittest.proto',
self._Database().pool.FindFileContainingSymbol(
'protobuf_unittest.TestAllTypes').name)
def testFindFileByName(self):
self.assertEquals(
self.assertEqual(
'google/protobuf/unittest.proto',
self._Database().pool.FindFileByName(
'google/protobuf/unittest.proto').name)
......
......@@ -32,7 +32,10 @@
"""Tests for google.protobuf.text_encoding."""
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import text_encoding
TEST_VALUES = [
......@@ -53,15 +56,15 @@ TEST_VALUES = [
class TextEncodingTestCase(unittest.TestCase):
def testCEscape(self):
for escaped, escaped_utf8, unescaped in TEST_VALUES:
self.assertEquals(escaped,
self.assertEqual(escaped,
text_encoding.CEscape(unescaped, as_utf8=False))
self.assertEquals(escaped_utf8,
self.assertEqual(escaped_utf8,
text_encoding.CEscape(unescaped, as_utf8=True))
def testCUnescape(self):
for escaped, escaped_utf8, unescaped in TEST_VALUES:
self.assertEquals(unescaped, text_encoding.CUnescape(escaped))
self.assertEquals(unescaped, text_encoding.CUnescape(escaped_utf8))
self.assertEqual(unescaped, text_encoding.CUnescape(escaped))
self.assertEqual(unescaped, text_encoding.CUnescape(escaped_utf8))
if __name__ == "__main__":
......
......@@ -35,9 +35,13 @@
__author__ = 'kenton@google.com (Kenton Varda)'
import re
import unittest
import unittest
import six
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf.internal import _parameterized
from google.protobuf import map_unittest_pb2
......@@ -61,7 +65,7 @@ class TextFormatBase(unittest.TestCase):
self.assertMultiLineEqual(text, ''.join(golden_lines))
def CompareToGoldenText(self, text, golden_text):
self.assertMultiLineEqual(text, golden_text)
self.assertEqual(text, golden_text)
def RemoveRedundantZeros(self, text):
# Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove
......@@ -100,7 +104,7 @@ class TextFormatTest(TextFormatBase):
'repeated_string: "\\303\\274\\352\\234\\237"\n')
def testPrintExoticUnicodeSubclass(self, message_module):
class UnicodeSub(unicode):
class UnicodeSub(six.text_type):
pass
message = message_module.TestAllTypes()
message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f'))
......@@ -172,7 +176,7 @@ class TextFormatTest(TextFormatBase):
parsed_message = message_module.TestAllTypes()
r = text_format.Parse(wire_text, parsed_message)
self.assertIs(r, parsed_message)
self.assertEquals(message, parsed_message)
self.assertEqual(message, parsed_message)
# Test as_utf8 = True.
wire_text = text_format.MessageToString(
......@@ -180,7 +184,7 @@ class TextFormatTest(TextFormatBase):
parsed_message = message_module.TestAllTypes()
r = text_format.Parse(wire_text, parsed_message)
self.assertIs(r, parsed_message)
self.assertEquals(message, parsed_message,
self.assertEqual(message, parsed_message,
'\n%s != %s' % (message, parsed_message))
def testPrintRawUtf8String(self, message_module):
......@@ -190,7 +194,7 @@ class TextFormatTest(TextFormatBase):
self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n')
parsed_message = message_module.TestAllTypes()
text_format.Parse(text, parsed_message)
self.assertEquals(message, parsed_message,
self.assertEqual(message, parsed_message,
'\n%s != %s' % (message, parsed_message))
def testPrintFloatFormat(self, message_module):
......@@ -217,13 +221,13 @@ class TextFormatTest(TextFormatBase):
text_message = text_format.MessageToString(message, float_format='.15g')
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_message),
'payload {{\n {}\n {}\n {}\n {}\n}}\n'.format(*formatted_fields))
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(*formatted_fields))
# as_one_line=True is a separate code branch where float_format is passed.
text_message = text_format.MessageToString(message, as_one_line=True,
float_format='.15g')
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_message),
'payload {{ {} {} {} {} }}'.format(*formatted_fields))
'payload {{ {0} {1} {2} {3} }}'.format(*formatted_fields))
def testMessageToString(self, message_module):
message = message_module.ForeignMessage()
......@@ -286,7 +290,7 @@ class TextFormatTest(TextFormatBase):
message = message_module.TestAllTypes()
text = ''
text_format.Parse(text, message)
self.assertEquals(message_module.TestAllTypes(), message)
self.assertEqual(message_module.TestAllTypes(), message)
def testParseInvalidUtf8(self, message_module):
message = message_module.TestAllTypes()
......@@ -296,7 +300,7 @@ class TextFormatTest(TextFormatBase):
def testParseSingleWord(self, message_module):
message = message_module.TestAllTypes()
text = 'foo'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
(r'1:1 : Message type "\w+.TestAllTypes" has no field named '
r'"foo".'),
......@@ -305,7 +309,7 @@ class TextFormatTest(TextFormatBase):
def testParseUnknownField(self, message_module):
message = message_module.TestAllTypes()
text = 'unknown_field: 8\n'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
(r'1:1 : Message type "\w+.TestAllTypes" has no field named '
r'"unknown_field".'),
......@@ -314,7 +318,7 @@ class TextFormatTest(TextFormatBase):
def testParseBadEnumValue(self, message_module):
message = message_module.TestAllTypes()
text = 'optional_nested_enum: BARR'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
(r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
r'has no value named BARR.'),
......@@ -322,7 +326,7 @@ class TextFormatTest(TextFormatBase):
message = message_module.TestAllTypes()
text = 'optional_nested_enum: 100'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
(r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
r'has no value with number 100.'),
......@@ -331,7 +335,7 @@ class TextFormatTest(TextFormatBase):
def testParseBadIntValue(self, message_module):
message = message_module.TestAllTypes()
text = 'optional_int32: bork'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
('1:17 : Couldn\'t parse integer: bork'),
text_format.Parse, text, message)
......@@ -401,7 +405,7 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
message = unittest_pb2.TestAllTypes()
test_util.SetAllFields(message)
self.assertEquals(message, parsed_message)
self.assertEqual(message, parsed_message)
def testPrintAllFields(self):
message = unittest_pb2.TestAllTypes()
......@@ -454,7 +458,7 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
message = unittest_pb2.TestAllTypes()
test_util.SetAllFields(message)
self.assertEquals(message, parsed_message)
self.assertEqual(message, parsed_message)
def testPrintMap(self):
message = map_unittest_pb2.TestMap()
......@@ -555,8 +559,8 @@ class Proto2Tests(TextFormatBase):
text_format.Parse(text, message)
ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
self.assertEquals(23, message.message_set.Extensions[ext1].i)
self.assertEquals('foo', message.message_set.Extensions[ext2].str)
self.assertEqual(23, message.message_set.Extensions[ext1].i)
self.assertEqual('foo', message.message_set.Extensions[ext2].str)
def testPrintAllExtensions(self):
message = unittest_pb2.TestAllExtensions()
......@@ -581,7 +585,7 @@ class Proto2Tests(TextFormatBase):
message = unittest_pb2.TestAllExtensions()
test_util.SetAllExtensions(message)
self.assertEquals(message, parsed_message)
self.assertEqual(message, parsed_message)
def testParseAllExtensions(self):
message = unittest_pb2.TestAllExtensions()
......@@ -595,12 +599,12 @@ class Proto2Tests(TextFormatBase):
def testParseBadExtension(self):
message = unittest_pb2.TestAllExtensions()
text = '[unknown_extension]: 8\n'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
'1:2 : Extension "unknown_extension" not registered.',
text_format.Parse, text, message)
message = unittest_pb2.TestAllTypes()
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
'extensions.'),
......@@ -619,7 +623,7 @@ class Proto2Tests(TextFormatBase):
message = unittest_pb2.TestAllExtensions()
text = ('[protobuf_unittest.optional_int32_extension]: 42 '
'[protobuf_unittest.optional_int32_extension]: 67')
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
('1:96 : Message type "protobuf_unittest.TestAllExtensions" '
'should not have multiple '
......@@ -630,7 +634,7 @@ class Proto2Tests(TextFormatBase):
message = unittest_pb2.TestAllTypes()
text = ('optional_nested_message { bb: 1 } '
'optional_nested_message { bb: 2 }')
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
'should not have multiple "bb" fields.'),
......@@ -640,7 +644,7 @@ class Proto2Tests(TextFormatBase):
message = unittest_pb2.TestAllTypes()
text = ('optional_int32: 42 '
'optional_int32: 67')
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError,
('1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
'have multiple "optional_int32" fields.'),
......@@ -649,11 +653,11 @@ class Proto2Tests(TextFormatBase):
def testParseGroupNotClosed(self):
message = unittest_pb2.TestAllTypes()
text = 'RepeatedGroup: <'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError, '1:16 : Expected ">".',
text_format.Parse, text, message)
text = 'RepeatedGroup: {'
self.assertRaisesRegexp(
six.assertRaisesRegex(self,
text_format.ParseError, '1:16 : Expected "}".',
text_format.Parse, text, message)
......
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#PY25 compatible for GAE.
#
# Copyright 2008 Google Inc. All Rights Reserved.
"""Provides type checking routines.
......@@ -49,9 +47,11 @@ TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization
__author__ = 'robinson@google.com (Will Robinson)'
import sys ##PY25
if sys.version < '2.6': bytes = str ##PY25
from google.protobuf.internal import api_implementation
import six
if six.PY3:
long = int
from google.protobuf.internal import decoder
from google.protobuf.internal import encoder
from google.protobuf.internal import wire_format
......@@ -117,9 +117,9 @@ class IntValueChecker(object):
"""Checker used for integer fields. Performs type-check and range check."""
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, (int, long)):
if not isinstance(proposed_value, six.integer_types):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), (int, long)))
(proposed_value, type(proposed_value), six.integer_types))
raise TypeError(message)
if not self._MIN <= proposed_value <= self._MAX:
raise ValueError('Value out of range: %d' % proposed_value)
......@@ -141,9 +141,9 @@ class EnumValueChecker(object):
self._enum_type = enum_type
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, (int, long)):
if not isinstance(proposed_value, six.integer_types):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), (int, long)))
(proposed_value, type(proposed_value), six.integer_types))
raise TypeError(message)
if proposed_value not in self._enum_type.values_by_number:
raise ValueError('Unknown enum value: %d' % proposed_value)
......@@ -161,9 +161,9 @@ class UnicodeValueChecker(object):
"""
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, (bytes, unicode)):
if not isinstance(proposed_value, (bytes, six.text_type)):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), (bytes, unicode)))
(proposed_value, type(proposed_value), (bytes, six.text_type)))
raise TypeError(message)
# If the value is of type 'bytes' make sure that it is valid UTF-8 data.
......
......@@ -35,7 +35,11 @@
__author__ = 'bohdank@google.com (Bohdan Koval)'
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
......
......@@ -34,7 +34,10 @@
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
try:
import unittest2 as unittest
except ImportError:
import unittest
from google.protobuf import message
from google.protobuf.internal import wire_format
......
......@@ -28,8 +28,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#PY25 compatible for GAE.
#
# Copyright 2012 Google Inc. All Rights Reserved.
"""Provides a factory class for generating dynamic messages.
......@@ -43,7 +41,6 @@ my_proto_instance = message_classes['some.proto.package.MessageName']()
__author__ = 'matthewtoia@google.com (Matt Toia)'
import sys ##PY25
from google.protobuf import descriptor_database
from google.protobuf import descriptor_pool
from google.protobuf import message
......@@ -75,8 +72,7 @@ class MessageFactory(object):
"""
if descriptor.full_name not in self._classes:
descriptor_name = descriptor.name
if sys.version_info[0] < 3: ##PY25
##!PY25 if str is bytes: # PY2
if str is bytes: # PY2
descriptor_name = descriptor.name.encode('ascii', 'ignore')
result_class = reflection.GeneratedProtocolMessageType(
descriptor_name,
......@@ -111,7 +107,7 @@ class MessageFactory(object):
result = {}
for file_name in files:
file_desc = self.pool.FindFileByName(file_name)
for name, msg in file_desc.message_types_by_name.iteritems():
for name, msg in file_desc.message_types_by_name.items():
if file_desc.package:
full_name = '.'.join([file_desc.package, name])
else:
......@@ -128,7 +124,7 @@ class MessageFactory(object):
# ignore the registration if the original was the same, or raise
# an error if they were different.
for name, extension in file_desc.extensions_by_name.iteritems():
for name, extension in file_desc.extensions_by_name.items():
if extension.containing_type.full_name not in self._classes:
self.GetPrototype(extension.containing_type)
extended_class = self._classes[extension.containing_type.full_name]
......
......@@ -30,7 +30,10 @@
"""Dynamic Protobuf class creator."""
import collections
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict #PY26
import hashlib
import os
......@@ -80,7 +83,7 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
# an OrderedDict we keep the order, but otherwise we sort the field to ensure
# consistent ordering.
field_items = fields.items()
if not isinstance(fields, collections.OrderedDict):
if not isinstance(fields, OrderedDict):
field_items = sorted(field_items)
# Use a consistent file name that is unlikely to conflict with any imported
......
......@@ -27,16 +27,13 @@
# 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.
#PY25 compatible for GAE.
#
"""Encoding related utilities."""
import re
import sys ##PY25
import six
# Lookup table for utf8
_cescape_utf8_to_str = [chr(i) for i in xrange(0, 256)]
_cescape_utf8_to_str = [chr(i) for i in range(0, 256)]
_cescape_utf8_to_str[9] = r'\t' # optional escape
_cescape_utf8_to_str[10] = r'\n' # optional escape
_cescape_utf8_to_str[13] = r'\r' # optional escape
......@@ -46,9 +43,9 @@ _cescape_utf8_to_str[34] = r'\"' # necessary escape
_cescape_utf8_to_str[92] = r'\\' # necessary escape
# Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32)
_cescape_byte_to_str = ([r'\%03o' % i for i in xrange(0, 32)] +
[chr(i) for i in xrange(32, 127)] +
[r'\%03o' % i for i in xrange(127, 256)])
_cescape_byte_to_str = ([r'\%03o' % i for i in range(0, 32)] +
[chr(i) for i in range(32, 127)] +
[r'\%03o' % i for i in range(127, 256)])
_cescape_byte_to_str[9] = r'\t' # optional escape
_cescape_byte_to_str[10] = r'\n' # optional escape
_cescape_byte_to_str[13] = r'\r' # optional escape
......@@ -75,7 +72,7 @@ def CEscape(text, as_utf8):
"""
# PY3 hack: make Ord work for str and bytes:
# //platforms/networking/data uses unicode here, hence basestring.
Ord = ord if isinstance(text, basestring) else lambda x: x
Ord = ord if isinstance(text, six.string_types) else lambda x: x
if as_utf8:
return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text)
return ''.join(_cescape_byte_to_str[Ord(c)] for c in text)
......@@ -100,8 +97,7 @@ def CUnescape(text):
# allow single-digit hex escapes (like '\xf').
result = _CUNESCAPE_HEX.sub(ReplaceHex, text)
if sys.version_info[0] < 3: ##PY25
##!PY25 if str is bytes: # PY2
if str is bytes: # PY2
return result.decode('string_escape')
result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result)
return (result.encode('ascii') # Make it bytes to allow decode.
......
......@@ -28,17 +28,20 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#PY25 compatible for GAE.
#
# Copyright 2007 Google Inc. All Rights Reserved.
"""Contains routines for printing protocol messages in text format."""
__author__ = 'kenton@google.com (Kenton Varda)'
import cStringIO
import io
import re
import six
if six.PY3:
long = int
from google.protobuf.internal import type_checkers
from google.protobuf import descriptor
from google.protobuf import text_encoding
......@@ -89,7 +92,7 @@ def MessageToString(message, as_utf8=False, as_one_line=False,
Returns:
A string of the text formatted protocol buffer message.
"""
out = cStringIO.StringIO()
out = io.BytesIO()
PrintMessage(message, out, as_utf8=as_utf8, as_one_line=as_one_line,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
......@@ -136,7 +139,6 @@ def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
use_index_order=use_index_order,
float_format=float_format)
def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False,
pointy_brackets=False, use_index_order=False, float_format=None):
"""Print a single field name/value pair. For repeated fields, the value
......@@ -157,7 +159,11 @@ def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False,
# For groups, use the capitalized name.
out.write(field.message_type.name)
else:
out.write(field.name)
if isinstance(field.name, six.text_type):
name = field.name.encode('utf-8')
else:
name = field.name
out.write(name)
if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
# The colon is optional in this case, but our cross-language golden files
......@@ -211,7 +217,7 @@ def PrintFieldValue(field, value, out, indent=0, as_utf8=False,
out.write(str(value))
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
out.write('\"')
if isinstance(value, unicode):
if isinstance(value, six.text_type):
out_value = value.encode('utf-8')
else:
out_value = value
......@@ -537,7 +543,7 @@ class _Tokenizer(object):
def _PopLine(self):
while len(self._current_line) <= self._column:
try:
self._current_line = self._lines.next()
self._current_line = next(self._lines)
except StopIteration:
self._current_line = ''
self._more_lines = False
......@@ -607,7 +613,7 @@ class _Tokenizer(object):
"""
try:
result = ParseInteger(self.token, is_signed=True, is_long=False)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -623,7 +629,7 @@ class _Tokenizer(object):
"""
try:
result = ParseInteger(self.token, is_signed=False, is_long=False)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -639,7 +645,7 @@ class _Tokenizer(object):
"""
try:
result = ParseInteger(self.token, is_signed=True, is_long=True)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -655,7 +661,7 @@ class _Tokenizer(object):
"""
try:
result = ParseInteger(self.token, is_signed=False, is_long=True)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -671,7 +677,7 @@ class _Tokenizer(object):
"""
try:
result = ParseFloat(self.token)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -687,7 +693,7 @@ class _Tokenizer(object):
"""
try:
result = ParseBool(self.token)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -703,8 +709,8 @@ class _Tokenizer(object):
"""
the_bytes = self.ConsumeByteString()
try:
return unicode(the_bytes, 'utf-8')
except UnicodeDecodeError, e:
return six.text_type(the_bytes, 'utf-8')
except UnicodeDecodeError as e:
raise self._StringParseError(e)
def ConsumeByteString(self):
......@@ -719,8 +725,7 @@ class _Tokenizer(object):
the_list = [self._ConsumeSingleByteString()]
while self.token and self.token[0] in ('\'', '"'):
the_list.append(self._ConsumeSingleByteString())
return ''.encode('latin1').join(the_list) ##PY25
##!PY25 return b''.join(the_list)
return b''.join(the_list)
def _ConsumeSingleByteString(self):
"""Consume one token of a string literal.
......@@ -741,7 +746,7 @@ class _Tokenizer(object):
try:
result = text_encoding.CUnescape(text[1:-1])
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......@@ -749,7 +754,7 @@ class _Tokenizer(object):
def ConsumeEnum(self, field):
try:
result = ParseEnum(field, self.token)
except ValueError, e:
except ValueError as e:
raise self._ParseError(str(e))
self.NextToken()
return result
......
......@@ -8,19 +8,7 @@ import sys
# We must use setuptools, not distutils, because we need to use the
# namespace_packages option for the "google" package.
try:
from setuptools import setup, Extension, find_packages
except ImportError:
try:
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, Extension, find_packages
except ImportError:
sys.stderr.write(
"Could not import setuptools; make sure you have setuptools or "
"ez_setup installed.\n"
)
raise
from setuptools import setup, Extension, find_packages
from distutils.command.clean import clean as _clean
......@@ -79,16 +67,14 @@ def generate_proto(source, require = True):
if protoc is None:
sys.stderr.write(
"protoc is not installed nor found in ../src. "
"Please compile it or install the binary package.\n"
)
"protoc is not installed nor found in ../src. Please compile it "
"or install the binary package.\n")
sys.exit(-1)
protoc_command = [protoc, "-I../src", "-I.", "--python_out=.", source]
protoc_command = [ protoc, "-I../src", "-I.", "--python_out=.", source ]
if subprocess.call(protoc_command) != 0:
sys.exit(-1)
def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/map_unittest.proto", False)
generate_proto("../src/google/protobuf/unittest.proto", False)
......@@ -119,13 +105,12 @@ class clean(_clean):
for filename in filenames:
filepath = os.path.join(dirpath, filename)
if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
filepath.endswith(".so") or filepath.endswith(".o") or \
filepath.endswith('google/protobuf/compiler/__init__.py'):
filepath.endswith(".so") or filepath.endswith(".o") or \
filepath.endswith('google/protobuf/compiler/__init__.py'):
os.remove(filepath)
# _clean is an old-style class, so super() doesn't work.
_clean.run(self)
class build_py(_build_py):
def run(self):
# Generate necessary .proto file if it doesn't exist.
......@@ -141,13 +126,7 @@ class build_py(_build_py):
pass
# _build_py is an old-style class, so super() doesn't work.
_build_py.run(self)
# TODO(mrovner): Subclass to run 2to3 on some files only.
# Tracing what https://wiki.python.org/moin/PortingPythonToPy3k's
# "Approach 2" section on how to get 2to3 to run on source files during
# install under Python 3. This class seems like a good place to put logic
# that calls python3's distutils.util.run_2to3 on the subset of the files we
# have in our release that are subject to conversion.
# See code reference in previous code review.
if __name__ == '__main__':
ext_module_list = []
......@@ -167,6 +146,12 @@ if __name__ == '__main__':
)
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
# Keep this list of dependencies in sync with tox.ini.
install_requires = ['six', 'setuptools']
if sys.version_info <= (2,7):
install_requires.append('ordereddict')
install_requires.append('unittest2')
setup(
name='protobuf',
version=GetVersion(),
......@@ -177,8 +162,14 @@ if __name__ == '__main__':
maintainer_email='protobuf@googlegroups.com',
license='New BSD License',
classifiers=[
'Programming Language :: Python :: 2.7',
],
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
],
namespace_packages=['google'],
packages=find_packages(
exclude=[
......@@ -190,6 +181,6 @@ if __name__ == '__main__':
'clean': clean,
'build_py': build_py,
},
install_requires=['setuptools'],
install_requires=install_requires,
ext_modules=ext_module_list,
)
[tox]
envlist =
# Py3 tests currently fail because of text handling issues,
# So only test py26/py27 for now.
#py{26,27,33,34}-{cpp,python}
py{26,27}-{cpp,python}
[testenv]
usedevelop=true
setenv =
cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs
cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs
cpp: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
commands =
python setup.py -q build_py
python: python setup.py -q build
cpp: python setup.py -q build --cpp_implementation
python: python setup.py -q test -q
cpp: python setup.py -q test -q --cpp_implementation
deps =
# Keep this list of dependencies in sync with setup.py.
six
py26: ordereddict
py26: unittest2
......@@ -111,25 +111,45 @@ build_javanano_oracle7() {
build_javanano
}
internal_install_python_deps() {
sudo pip install tox
# Only install Python2.6 on Linux.
if [ $(uname -s) == "Linux" ]; then
sudo apt-get install -y python-software-properties # for apt-add-repository
sudo apt-add-repository -y ppa:fkrull/deadsnakes
sudo apt-get update -qq
sudo apt-get install -y python2.6 python2.6-dev
fi
}
build_python() {
internal_build_cpp
internal_install_python_deps
cd python
python setup.py build
python setup.py test
python setup.py sdist
sudo pip install virtualenv && virtualenv /tmp/protoenv && /tmp/protoenv/bin/pip install dist/*
# Only test Python 2.6 on Linux
if [ $(uname -s) == "Linux" ]; then
envlist=py26-python,py27-python
else
envlist=py27-python
fi
tox -e $envlist
cd ..
}
build_python_cpp() {
internal_build_cpp
export LD_LIBRARY_PATH=../src/.libs # for Linux
internal_install_python_deps
export LD_LIBRARY_PATH=../src/.libs # for Linux
export DYLD_LIBRARY_PATH=../src/.libs # for OS X
cd python
python setup.py build --cpp_implementation
python setup.py test --cpp_implementation
python setup.py sdist --cpp_implementation
sudo pip install virtualenv && virtualenv /tmp/protoenv && /tmp/protoenv/bin/pip install dist/*
# Only test Python 2.6 on Linux
if [ $(uname -s) == "Linux" ]; then
envlist=py26-cpp,py27-cpp
else
envlist=py27-cpp
fi
tox -e $envlist
cd ..
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment