diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py index 4e2f35e4dd..691978653f 100644 --- a/python/google/protobuf/internal/json_format_test.py +++ b/python/google/protobuf/internal/json_format_test.py @@ -410,6 +410,9 @@ class JsonFormatTest(JsonFormatBase): '"unknownName".') def testDuplicateField(self): + # Duplicate key check is not supported for python2.6 + if sys.version_info < (2, 7): + return self.CheckError('{"int32Value": 1,\n"int32Value":2}', 'Failed to load JSON: duplicate key int32Value') @@ -468,15 +471,17 @@ class JsonFormatTest(JsonFormatBase): (r'Failed to load JSON: Expecting property name' r'( enclosed in double quotes)?: line 1'), json_format.Parse, text, message) - text = r'{"stringMap": {"a": 3, "\u0061": 2}}' + text = '{"boolMap": {"null": 1}}' self.assertRaisesRegexp( json_format.ParseError, - 'Failed to load JSON: duplicate key a', + 'Failed to parse boolMap field: Expect "true" or "false", not null.', json_format.Parse, text, message) - text = '{"boolMap": {"null": 1}}' + if sys.version_info < (2, 7): + return + text = r'{"stringMap": {"a": 3, "\u0061": 2}}' self.assertRaisesRegexp( json_format.ParseError, - 'Failed to parse boolMap field: Expect "true" or "false", not null.', + 'Failed to load JSON: duplicate key a', json_format.Parse, text, message) def testInvalidTimestamp(self): diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py index 09110e04dd..d95557d740 100644 --- a/python/google/protobuf/json_format.py +++ b/python/google/protobuf/json_format.py @@ -37,6 +37,7 @@ from datetime import datetime import json import math import re +import sys from google.protobuf import descriptor @@ -114,7 +115,14 @@ def _RegularMessageToJsonObject(message, including_default_value_fields): # Convert a map field. js_map = {} for key in value: - js_map[key] = _ConvertFieldToJsonObject( + if isinstance(key, bool): + if key: + recorded_key = 'true' + else: + recorded_key = 'false' + else: + recorded_key = key + js_map[recorded_key] = _ConvertFieldToJsonObject( field.message_type.fields_by_name['value'], value[key], including_default_value_fields) js[name] = js_map @@ -297,7 +305,11 @@ def Parse(text, message): """ if not isinstance(text, _UNICODETYPE): text = text.decode('utf-8') try: - js = json.loads(text, object_pairs_hook=_DuplicateChecker) + if sys.version_info < (2, 7): + # object_pair_hook is not supported before python2.7 + js = json.loads(text) + else: + js = json.loads(text, object_pairs_hook=_DuplicateChecker) except ValueError as e: raise ParseError('Failed to load JSON: ' + str(e)) _ConvertFieldValuePair(js, message) @@ -419,7 +431,8 @@ def _ConvertTimestampMessage(value, message): second_value = time_value[:point_position] nano_value = time_value[point_position + 1:] date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT) - seconds = (date_object - datetime(1970, 1, 1)).total_seconds() + td = date_object - datetime(1970, 1, 1) + seconds = td.seconds + td.days * 24 * 3600 if len(nano_value) > 9: raise ParseError( 'Failed to parse Timestamp: nanos {0} more than ' diff --git a/python/tox.ini b/python/tox.ini index 1c433fa2ce..a6352ef4a4 100644 --- a/python/tox.ini +++ b/python/tox.ini @@ -2,8 +2,7 @@ envlist = # cpp implementation on py34 is currently broken due to # changes introduced by http://bugs.python.org/issue22079. - # py26 is currently broken due to the json_format - py{27,33,34}-{cpp,python} + py{26,27,33,34}-{cpp,python} [testenv] usedevelop=true diff --git a/travis.sh b/travis.sh index 6b05073709..435e7e757f 100755 --- a/travis.sh +++ b/travis.sh @@ -131,8 +131,7 @@ build_python() { cd python # Only test Python 2.6/3.x on Linux if [ $(uname -s) == "Linux" ]; then - # py26 is currently disabled due to json_format - envlist=py\{27,33,34\}-python + envlist=py\{26,27,33,34\}-python else envlist=py27-python fi