mirror of
https://github.com/openvswitch/ovs
synced 2025-10-27 15:18:06 +00:00
python: Serial JSON via Python's json lib.
There is no particularly good reason to use our own Python JSON serialization implementation when serialization can be done faster with Python's built-in JSON library. A few tests were changed due to Python's default JSON library returning slightly more precise floating point numbers. Signed-off-by: Terry Wilson <twilson@redhat.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
@@ -12,11 +12,13 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
import functools
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from six.moves import range
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ovs._json
|
import ovs._json
|
||||||
@@ -25,112 +27,24 @@ except ImportError:
|
|||||||
|
|
||||||
__pychecker__ = 'no-stringiter'
|
__pychecker__ = 'no-stringiter'
|
||||||
|
|
||||||
escapes = {ord('"'): u"\\\"",
|
|
||||||
ord("\\"): u"\\\\",
|
|
||||||
ord("\b"): u"\\b",
|
|
||||||
ord("\f"): u"\\f",
|
|
||||||
ord("\n"): u"\\n",
|
|
||||||
ord("\r"): u"\\r",
|
|
||||||
ord("\t"): u"\\t"}
|
|
||||||
for esc in range(32):
|
|
||||||
if esc not in escapes:
|
|
||||||
escapes[esc] = u"\\u%04x" % esc
|
|
||||||
|
|
||||||
SPACES_PER_LEVEL = 2
|
SPACES_PER_LEVEL = 2
|
||||||
|
dumper = functools.partial(json.dumps, separators=(",", ":"),
|
||||||
|
ensure_ascii=False)
|
||||||
class _Serializer(object):
|
|
||||||
def __init__(self, stream, pretty, sort_keys):
|
|
||||||
self.stream = stream
|
|
||||||
self.pretty = pretty
|
|
||||||
self.sort_keys = sort_keys
|
|
||||||
self.depth = 0
|
|
||||||
|
|
||||||
def __serialize_string(self, s):
|
|
||||||
self.stream.write(u'"%s"' % ''.join(escapes.get(ord(c), c) for c in s))
|
|
||||||
|
|
||||||
def __indent_line(self):
|
|
||||||
if self.pretty:
|
|
||||||
self.stream.write('\n')
|
|
||||||
self.stream.write(' ' * (SPACES_PER_LEVEL * self.depth))
|
|
||||||
|
|
||||||
def serialize(self, obj):
|
|
||||||
if obj is None:
|
|
||||||
self.stream.write(u"null")
|
|
||||||
elif obj is False:
|
|
||||||
self.stream.write(u"false")
|
|
||||||
elif obj is True:
|
|
||||||
self.stream.write(u"true")
|
|
||||||
elif isinstance(obj, six.integer_types):
|
|
||||||
self.stream.write(u"%d" % obj)
|
|
||||||
elif isinstance(obj, float):
|
|
||||||
self.stream.write("%.15g" % obj)
|
|
||||||
elif isinstance(obj, six.text_type):
|
|
||||||
# unicode() on Python 2, or str() in Python 3 (always unicode)
|
|
||||||
self.__serialize_string(obj)
|
|
||||||
elif isinstance(obj, str):
|
|
||||||
# This is for Python 2, where this comes out to unicode(str()).
|
|
||||||
# For Python 3, it's str(str()), but it's harmless.
|
|
||||||
self.__serialize_string(six.text_type(obj))
|
|
||||||
elif isinstance(obj, dict):
|
|
||||||
self.stream.write(u"{")
|
|
||||||
|
|
||||||
self.depth += 1
|
|
||||||
self.__indent_line()
|
|
||||||
|
|
||||||
if self.sort_keys:
|
|
||||||
items = sorted(obj.items())
|
|
||||||
else:
|
|
||||||
items = six.iteritems(obj)
|
|
||||||
for i, (key, value) in enumerate(items):
|
|
||||||
if i > 0:
|
|
||||||
self.stream.write(u",")
|
|
||||||
self.__indent_line()
|
|
||||||
self.__serialize_string(six.text_type(key))
|
|
||||||
self.stream.write(u":")
|
|
||||||
if self.pretty:
|
|
||||||
self.stream.write(u' ')
|
|
||||||
self.serialize(value)
|
|
||||||
|
|
||||||
self.stream.write(u"}")
|
|
||||||
self.depth -= 1
|
|
||||||
elif isinstance(obj, (list, tuple)):
|
|
||||||
self.stream.write(u"[")
|
|
||||||
self.depth += 1
|
|
||||||
|
|
||||||
if obj:
|
|
||||||
self.__indent_line()
|
|
||||||
|
|
||||||
for i, value in enumerate(obj):
|
|
||||||
if i > 0:
|
|
||||||
self.stream.write(u",")
|
|
||||||
self.__indent_line()
|
|
||||||
self.serialize(value)
|
|
||||||
|
|
||||||
self.depth -= 1
|
|
||||||
self.stream.write(u"]")
|
|
||||||
else:
|
|
||||||
raise Exception("can't serialize %s as JSON" % obj)
|
|
||||||
|
|
||||||
|
|
||||||
def to_stream(obj, stream, pretty=False, sort_keys=True):
|
def to_stream(obj, stream, pretty=False, sort_keys=True):
|
||||||
_Serializer(stream, pretty, sort_keys).serialize(obj)
|
stream.write(dumper(obj, indent=SPACES_PER_LEVEL if pretty else None,
|
||||||
|
sort_keys=sort_keys))
|
||||||
|
|
||||||
|
|
||||||
def to_file(obj, name, pretty=False, sort_keys=True):
|
def to_file(obj, name, pretty=False, sort_keys=True):
|
||||||
stream = open(name, "w")
|
with open(name, "w") as stream:
|
||||||
try:
|
|
||||||
to_stream(obj, stream, pretty, sort_keys)
|
to_stream(obj, stream, pretty, sort_keys)
|
||||||
finally:
|
|
||||||
stream.close()
|
|
||||||
|
|
||||||
|
|
||||||
def to_string(obj, pretty=False, sort_keys=True):
|
def to_string(obj, pretty=False, sort_keys=True):
|
||||||
output = six.StringIO()
|
return dumper(obj, indent=SPACES_PER_LEVEL if pretty else None,
|
||||||
to_stream(obj, output, pretty, sort_keys)
|
sort_keys=sort_keys)
|
||||||
s = output.getvalue()
|
|
||||||
output.close()
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def from_stream(stream):
|
def from_stream(stream):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
m4_define([JSON_CHECK_POSITIVE_C],
|
m4_define([JSON_CHECK_POSITIVE_C],
|
||||||
[AT_SETUP([$1])
|
[AT_SETUP([$1])
|
||||||
AT_KEYWORDS([json positive])
|
AT_KEYWORDS([json positive])
|
||||||
AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
|
AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
|
||||||
@@ -11,7 +11,7 @@ m4_define([JSON_CHECK_POSITIVE_C],
|
|||||||
# JSON_CHECK_POSITIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS,
|
# JSON_CHECK_POSITIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS,
|
||||||
# PYTHON-CHCEK, PYTHON-BIN)
|
# PYTHON-CHCEK, PYTHON-BIN)
|
||||||
#
|
#
|
||||||
m4_define([JSON_CHECK_POSITIVE_PY],
|
m4_define([JSON_CHECK_POSITIVE_PY],
|
||||||
[AT_SETUP([$1])
|
[AT_SETUP([$1])
|
||||||
AT_KEYWORDS([json positive Python])
|
AT_KEYWORDS([json positive Python])
|
||||||
AT_SKIP_IF([test $5 = no])
|
AT_SKIP_IF([test $5 = no])
|
||||||
@@ -41,6 +41,12 @@ m4_define([JSON_CHECK_POSITIVE],
|
|||||||
JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4],
|
JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4],
|
||||||
[$HAVE_PYTHON3], [$PYTHON3])])
|
[$HAVE_PYTHON3], [$PYTHON3])])
|
||||||
|
|
||||||
|
m4_define([JSON_CHECK_POSITIVE_PY23],
|
||||||
|
[JSON_CHECK_POSITIVE_PY([$1 - Python2], [$2], [$3], [$4],
|
||||||
|
[$HAVE_PYTHON], [$PYTHON])
|
||||||
|
JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4],
|
||||||
|
[$HAVE_PYTHON3], [$PYTHON3])])
|
||||||
|
|
||||||
m4_define([JSON_CHECK_NEGATIVE_C],
|
m4_define([JSON_CHECK_NEGATIVE_C],
|
||||||
[AT_SETUP([$1])
|
[AT_SETUP([$1])
|
||||||
AT_KEYWORDS([json negative])
|
AT_KEYWORDS([json negative])
|
||||||
@@ -216,10 +222,14 @@ JSON_CHECK_POSITIVE(
|
|||||||
# It seems likely that the following test will fail on some system that
|
# It seems likely that the following test will fail on some system that
|
||||||
# rounds slightly differently in arithmetic or in printf, but I'd like
|
# rounds slightly differently in arithmetic or in printf, but I'd like
|
||||||
# to keep it this way until we run into such a system.
|
# to keep it this way until we run into such a system.
|
||||||
JSON_CHECK_POSITIVE(
|
JSON_CHECK_POSITIVE_C(
|
||||||
[large integers that overflow to reals],
|
[C - large integers that overflow to reals],
|
||||||
[[[9223372036854775807000, -92233720368547758080000]]],
|
[[[9223372036854775807000, -92233720368547758080000]]],
|
||||||
[[[9.22337203685478e+21,-9.22337203685478e+22]]])
|
[[[9.22337203685478e+21,-9.22337203685478e+22]]])
|
||||||
|
JSON_CHECK_POSITIVE_PY23(
|
||||||
|
[large integers that overflow to reals],
|
||||||
|
[[[9223372036854775807000, -92233720368547758080000]]],
|
||||||
|
[[[9.223372036854776e+21,-9.223372036854776e+22]]])
|
||||||
|
|
||||||
JSON_CHECK_POSITIVE(
|
JSON_CHECK_POSITIVE(
|
||||||
[negative zero],
|
[negative zero],
|
||||||
@@ -237,10 +247,14 @@ JSON_CHECK_POSITIVE(
|
|||||||
# It seems likely that the following test will fail on some system that
|
# It seems likely that the following test will fail on some system that
|
||||||
# rounds slightly differently in arithmetic or in printf, but I'd like
|
# rounds slightly differently in arithmetic or in printf, but I'd like
|
||||||
# to keep it this way until we run into such a system.
|
# to keep it this way until we run into such a system.
|
||||||
JSON_CHECK_POSITIVE(
|
JSON_CHECK_POSITIVE_C(
|
||||||
[+/- DBL_MAX],
|
[C - +/- DBL_MAX],
|
||||||
[[[1.7976931348623157e+308, -1.7976931348623157e+308]]],
|
[[[1.7976931348623157e+308, -1.7976931348623157e+308]]],
|
||||||
[[[1.79769313486232e+308,-1.79769313486232e+308]]])
|
[[[1.79769313486232e+308,-1.79769313486232e+308]]])
|
||||||
|
JSON_CHECK_POSITIVE_PY23(
|
||||||
|
[+/- DBL_MAX],
|
||||||
|
[[[1.7976931348623157e+308, -1.7976931348623157e+308]]],
|
||||||
|
[[[1.7976931348623157e+308,-1.7976931348623157e+308]]])
|
||||||
|
|
||||||
JSON_CHECK_POSITIVE(
|
JSON_CHECK_POSITIVE(
|
||||||
[negative reals],
|
[negative reals],
|
||||||
|
|||||||
Reference in New Issue
Block a user