From 565f82ac4906a76f53acf2443c1850e99c833e6c 2014-07-07 04:53:14 From: MinRK Date: 2014-07-07 04:53:14 Subject: [PATCH] Backport PR #6077: allow unicode keys in dicts in json_clean non-ascii keys would raise UnicodeEncodeError in json_clean on Python 2 --- diff --git a/IPython/utils/jsonutil.py b/IPython/utils/jsonutil.py index b16f14d..f618550 100644 --- a/IPython/utils/jsonutil.py +++ b/IPython/utils/jsonutil.py @@ -1,16 +1,8 @@ -"""Utilities to manipulate JSON objects. -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING.txt, distributed as part of this software. -#----------------------------------------------------------------------------- +"""Utilities to manipulate JSON objects.""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -# stdlib import math import re import types @@ -197,18 +189,6 @@ def json_clean(obj): encoded as JSON. Note that this function does not *encode* its inputs, it simply sanitizes it so that there will be no encoding errors later. - Examples - -------- - >>> json_clean(4) - 4 - >>> json_clean(list(range(10))) - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - >>> sorted(json_clean(dict(x=1, y=2)).items()) - [('x', 1), ('y', 2)] - >>> sorted(json_clean(dict(x=1, y=2, z=[1,2,3])).items()) - [('x', 1), ('y', 2), ('z', [1, 2, 3])] - >>> json_clean(True) - True """ # types that are 'atomic' and ok in json as-is. atomic_ok = (unicode_type, type(None)) @@ -247,14 +227,14 @@ def json_clean(obj): # key collisions after stringification. This can happen with keys like # True and 'true' or 1 and '1', which collide in JSON. nkeys = len(obj) - nkeys_collapsed = len(set(map(str, obj))) + nkeys_collapsed = len(set(map(unicode_type, obj))) if nkeys != nkeys_collapsed: - raise ValueError('dict can not be safely converted to JSON: ' + raise ValueError('dict cannot be safely converted to JSON: ' 'key collision would lead to dropped values') # If all OK, proceed by making the new dict that will be json-safe out = {} for k,v in iteritems(obj): - out[str(k)] = json_clean(v) + out[unicode_type(k)] = json_clean(v) return out # If we get here, we don't know how to handle the object, so we just get diff --git a/IPython/utils/tests/test_jsonutil.py b/IPython/utils/tests/test_jsonutil.py index 398a981..6c84778 100644 --- a/IPython/utils/tests/test_jsonutil.py +++ b/IPython/utils/tests/test_jsonutil.py @@ -1,31 +1,20 @@ -"""Test suite for our JSON utilities. -""" -#----------------------------------------------------------------------------- -# Copyright (C) 2010-2011 The IPython Development Team -# -# Distributed under the terms of the BSD License. The full license is in -# the file COPYING.txt, distributed as part of this software. -#----------------------------------------------------------------------------- - -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- -# stdlib +# coding: utf-8 +"""Test suite for our JSON utilities.""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + import datetime import json from base64 import decodestring -# third party import nose.tools as nt -# our own from IPython.utils import jsonutil, tz from ..jsonutil import json_clean, encode_images from ..py3compat import unicode_to_str, str_to_bytes, iteritems -#----------------------------------------------------------------------------- -# Test functions -#----------------------------------------------------------------------------- + class Int(int): def __str__(self): return 'Int(%i)' % self @@ -148,4 +137,8 @@ def test_exception(): ] for d in bad_dicts: nt.assert_raises(ValueError, json_clean, d) - + +def test_unicode_dict(): + data = {u'üniço∂e': u'üniço∂e'} + clean = jsonutil.json_clean(data) + nt.assert_equal(data, clean)