Esempio n. 1
0
    def test_json_encoder_numbers(self):
        self.encoder_test(0, '0')
        self.encoder_test(1, '1')
        self.encoder_test(-123456, '-123456')

        self.encoder_test(2.2, '2.2')
        self.encoder_test(1.2345678, '1.2345678')
        self.encoder_test(-1.23456e-123, '-1.23456e-123')

        # 9007199254740992 is the largest possible integer in JavaScript
        self.encoder_test(9007199254740992, '9007199254740992')

        # std module just returns a string representation for
        # all valid python numbers (even for non-jscript representable numbers)
        with assert_raises(ValueError, error_re='out of range'):
            self.encoder_test( 9007199254740992 + 1, None)
        with assert_raises(ValueError, error_re='out of range'):
            self.encoder_test(-9007199254740992 - 1, None)
        with assert_raises(ValueError, error_re='NaN is not supported'):
            self.encoder_test(float('NaN'), None)

        # std module does not support Decimals
        # note: Decimal(1.17) != Decimal("1.17"), for testing need initialization from a string
        self.encoder_test(Decimal("1.17"), '"1.17"', False, False)

        lst = [Decimal(str(random.random()*100000)) for _ in range(256)]
        out = '[{}]'.format(','.join('"{}"'.format(str(d)) for d in lst))
        self.encoder_test(lst, out, False, False)

        # complex numbers are not JSON serializable
        with assert_raises(TypeError, error_re='not JSON serializable'):
            self.encoder_test(1+2j, None)
Esempio n. 2
0
    def test_json_default(self):
        class Foo:
            pass

        class Bar:
            pass

        class Spam:
            pass

        class Encoder(self.encoder):
            def default(self, obj):
                if isinstance(obj, Foo):
                    return ['Foo', 'Foo']
                if isinstance(obj, Spam):
                    1/0
                return super().default(obj)

        assert Encoder().dumps([Foo(), Foo()]) == '[["Foo","Foo"],["Foo","Foo"]]'

        with assert_raises(TypeError, error_re='is not JSON seri'):
            Encoder().dumps(Bar())

        # let's check that the exceptions propagate fine
        with assert_raises(ZeroDivisionError):
            Encoder().dumps([Spam()])
        with assert_raises(ZeroDivisionError):
            Encoder().dumpb({Spam(): 1})
Esempio n. 3
0
    def test_json_encoder_dict(self):
        self.encoder_test({}, '{}')
        self.encoder_test({'foo':1, 'bar':2}, ('{"foo":1,"bar":2}', '{"bar":2,"foo":1}'))
        self.encoder_test({'foo':[1,2], 'bar':[3,4]}, ('{"foo":[1,2],"bar":[3,4]}',
                                                       '{"bar":[3,4],"foo":[1,2]}'))

        # shold match std encoder, but conversion back converts to lists not tuples
        self.encoder_test({'foo':(1,2), 'bar':(3,4)}, ('{"foo":[1,2],"bar":[3,4]}',
                                                       '{"bar":[3,4],"foo":[1,2]}'), False, True)

        # std encoder does not support sets
        self.encoder_test({'foo':{1,2}, 'bar':{3,4}}, ('{"foo":[1,2],"bar":[3,4]}',
                                                       '{"bar":[3,4],"foo":[1,2]}'), False, False)

        # std encoder does nto support OrderedDicts
        d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
        ordered_d = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
        self.encoder_test( ordered_d, '{"apple":4,"banana":3,"orange":2,"pear":1}', False, False)

        # JSON spec does not support keys which are not a string or a number
        with assert_raises(TypeError, error_re='is not a valid dictionary key'):
            self.encoder_test({1:1}, '{1:1}')
        with assert_raises(TypeError, error_re='is not a valid dictionary key'):
            self.encoder_test({(1,2):'a'}, '{[1,2]:"a"}')

        class DerivedDict(dict):
            pass
        self.encoder_test(DerivedDict({'foo':1, 'bar':2}), ('{"foo":1,"bar":2}',
                                                            '{"bar":2,"foo":1}'))
Esempio n. 4
0
    def test_json_default(self):
        class Foo:
            pass

        class Bar:
            pass

        class Spam:
            pass

        class Encoder(self.encoder):
            def default(self, obj):
                if isinstance(obj, Foo):
                    return ['Foo', 'Foo']
                if isinstance(obj, Spam):
                    1 / 0
                return super().default(obj)

        assert Encoder().dumps([Foo(),
                                Foo()]) == '[["Foo","Foo"],["Foo","Foo"]]'

        with assert_raises(TypeError, error_re='is not JSON seri'):
            Encoder().dumps(Bar())

        # let's check that the exceptions propagate fine
        with assert_raises(ZeroDivisionError):
            Encoder().dumps([Spam()])
        with assert_raises(ZeroDivisionError):
            Encoder().dumpb({Spam(): 1})
Esempio n. 5
0
    def test_json_encoder_custom_methods(self):
        class FooJson:
            def __mm_json__(self):
                return '{"foo":{"baz":"©","spam":"\x1b"}}'

        # none of these are suported by std encoder
        ex_result = '{"foo":{"baz":"\\u00a9","spam":"\\u001b"}}'
        self.encoder_test(FooJson(), ex_result, False, False)
        self.encoder_test({'bar': FooJson()}, '{"bar":' + ex_result + '}',
                          False, False)

        class FooJsonb:
            def __mm_json__(self):
                return b'"foo"'

        # none of these are suported by std encoder
        self.encoder_test(FooJsonb(), '"foo"', False, False)
        self.encoder_test({'bar': FooJsonb()}, '{"bar":"foo"}', False, False)

        class FooJsonPlus:
            def __mm_json__(self):
                raise NotImplementedError

            def __mm_serialize__(self):
                return 'foo'

        # none of these are suported by std encoder
        self.encoder_test(FooJsonPlus(), '"foo"', False, False)
        self.encoder_test({'bar': FooJsonPlus()}, '{"bar":"foo"}', False,
                          False)

        class Foo:
            def __mm_serialize__(self):
                return 'foo'

        # none of these are suported by std encoder
        self.encoder_test(Foo(), '"foo"', False, False)
        self.encoder_test({Foo(): 'bar'}, '{"foo":"bar"}', False, False)
        self.encoder_test({'bar': Foo()}, '{"bar":"foo"}', False, False)

        class FooNotImpl(str):
            def __mm_serialize__(self):
                raise NotImplementedError

        # none of these are suported by std encoder
        self.encoder_test(FooNotImpl('foo'), '"foo"', False, False)
        self.encoder_test({FooNotImpl('foo'): 'bar'}, '{"foo":"bar"}', False,
                          False)
        self.encoder_test({'bar': FooNotImpl('foo')}, '{"bar":"foo"}', False,
                          False)

        class Spam:
            def __mm_serialize__(self):
                1 / 0

        with assert_raises(ZeroDivisionError):
            self.dumps({'1': Spam()})

        with assert_raises(ZeroDivisionError):
            self.dumps({Spam(): 1})
Esempio n. 6
0
    def test_json_encoder_numbers(self):
        self.encoder_test(0, '0')
        self.encoder_test(1, '1')
        self.encoder_test(-123456, '-123456')

        self.encoder_test(2.2, '2.2')
        self.encoder_test(1.2345678, '1.2345678')
        self.encoder_test(-1.23456e-123, '-1.23456e-123')

        # 9007199254740992 is the largest possible integer in JavaScript
        self.encoder_test(9007199254740992, '9007199254740992')

        # std module just returns a string representation for
        # all valid python numbers (even for non-jscript representable numbers)
        with assert_raises(ValueError, error_re='out of range'):
            self.encoder_test(9007199254740992 + 1, None)
        with assert_raises(ValueError, error_re='out of range'):
            self.encoder_test(-9007199254740992 - 1, None)
        with assert_raises(ValueError, error_re='NaN is not supported'):
            self.encoder_test(float('NaN'), None)

        # std module does not support Decimals
        # note: Decimal(1.17) != Decimal("1.17"), for testing need initialization from a string
        self.encoder_test(Decimal("1.17"), '"1.17"', False, False)

        lst = [Decimal(str(random.random() * 100000)) for _ in range(256)]
        out = '[{}]'.format(','.join('"{}"'.format(str(d)) for d in lst))
        self.encoder_test(lst, out, False, False)

        # complex numbers are not JSON serializable
        with assert_raises(TypeError, error_re='not JSON serializable'):
            self.encoder_test(1 + 2j, None)
Esempio n. 7
0
    def test_json_encoder_custom_methods(self):
        class FooJson:
            def __mm_json__(self):
                return '{"foo":{"baz":"©","spam":"\x1b"}}'

        # none of these are suported by std encoder
        ex_result = '{"foo":{"baz":"\\u00a9","spam":"\\u001b"}}'
        self.encoder_test(FooJson(), ex_result, False, False)
        self.encoder_test({'bar':FooJson()}, '{"bar":' + ex_result + '}', False, False)

        class FooJsonb:
            def __mm_json__(self):
                return b'"foo"'

        # none of these are suported by std encoder
        self.encoder_test(FooJsonb(), '"foo"', False, False)
        self.encoder_test({'bar':FooJsonb()}, '{"bar":"foo"}', False, False)

        class FooJsonPlus:
            def __mm_json__(self):
                raise NotImplementedError

            def __mm_serialize__(self):
                return 'foo'

        # none of these are suported by std encoder
        self.encoder_test(FooJsonPlus(), '"foo"', False, False)
        self.encoder_test({'bar':FooJsonPlus()}, '{"bar":"foo"}', False, False)

        class Foo:
            def __mm_serialize__(self):
                return 'foo'

        # none of these are suported by std encoder
        self.encoder_test(Foo(), '"foo"', False, False)
        self.encoder_test({Foo():'bar'}, '{"foo":"bar"}', False, False)
        self.encoder_test({'bar':Foo()}, '{"bar":"foo"}', False, False)

        class FooNotImpl(str):
            def __mm_serialize__(self):
                raise NotImplementedError

        # none of these are suported by std encoder
        self.encoder_test(FooNotImpl('foo'), '"foo"', False, False)
        self.encoder_test({FooNotImpl('foo'):'bar'}, '{"foo":"bar"}', False, False)
        self.encoder_test({'bar':FooNotImpl('foo')}, '{"bar":"foo"}', False, False)

        class Spam:
            def __mm_serialize__(self):
                1/0

        with assert_raises(ZeroDivisionError):
            self.dumps({'1': Spam()})

        with assert_raises(ZeroDivisionError):
            self.dumps({Spam(): 1})
Esempio n. 8
0
    def test_json_encoder_dict(self):
        self.encoder_test({}, '{}')
        self.encoder_test({
            'foo': 1,
            'bar': 2
        }, ('{"foo":1,"bar":2}', '{"bar":2,"foo":1}'))
        self.encoder_test({
            'foo': [1, 2],
            'bar': [3, 4]
        }, ('{"foo":[1,2],"bar":[3,4]}', '{"bar":[3,4],"foo":[1,2]}'))

        # shold match std encoder, but conversion back converts to lists not tuples
        self.encoder_test({
            'foo': (1, 2),
            'bar': (3, 4)
        }, ('{"foo":[1,2],"bar":[3,4]}', '{"bar":[3,4],"foo":[1,2]}'), False,
                          True)

        # std encoder does not support sets
        self.encoder_test({
            'foo': {1, 2},
            'bar': {3, 4}
        }, ('{"foo":[1,2],"bar":[3,4]}', '{"bar":[3,4],"foo":[1,2]}'), False,
                          False)

        # std encoder does nto support OrderedDicts
        d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
        ordered_d = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
        self.encoder_test(ordered_d,
                          '{"apple":4,"banana":3,"orange":2,"pear":1}', False,
                          False)

        # JSON spec does not support keys which are not a string or a number
        with assert_raises(TypeError,
                           error_re='is not a valid dictionary key'):
            self.encoder_test({1: 1}, '{1:1}')
        with assert_raises(TypeError,
                           error_re='is not a valid dictionary key'):
            self.encoder_test({(1, 2): 'a'}, '{[1,2]:"a"}')

        class DerivedDict(dict):
            pass

        self.encoder_test(DerivedDict({
            'foo': 1,
            'bar': 2
        }), ('{"foo":1,"bar":2}', '{"bar":2,"foo":1}'))
Esempio n. 9
0
    def test_json_encoder_lists(self):
        self.encoder_test([], '[]')
        self.encoder_test(['abc', True], '["abc",true]')
        self.encoder_test(['abc', [], [True]], '["abc",[],[true]]')

        # a tuple is converted to the same string as a "similar" list, so no conversion back
        # (but should match the default encoder)
        self.encoder_test((), '[]', False, True)
        self.encoder_test((1, ), '[1]', False, True)
        self.encoder_test((1, 2, [1, 2, 3]), '[1,2,[1,2,3]]', False, True)
        self.encoder_test(('a', 'b', ('c', 1)), '["a","b",["c",1]]', False,
                          True)

        self.encoder_test((99, 100, 999, 1000, 9999, 10000, 99999, 100000),
                          '[99,100,999,1000,9999,10000,99999,100000]', False,
                          True)

        # std module does not support sets
        self.encoder_test({1, 2, 3}, '[1,2,3]', False, False)

        # test max recursion level checks
        with assert_raises(
                ValueError,
                error_re='Exceeded maximum allowed recursion level'):
            self.dumps([[[1, 2], 3], 4], max_nested_level=1)
        with assert_raises(
                ValueError,
                error_re='Exceeded maximum allowed recursion level'):
            self.dumps([[[1, 2], 3], 4], max_nested_level=2)
        # this should work
        assert (self.dumps([[[1, 2], 3], 4],
                           max_nested_level=3) == '[[[1,2],3],4]')
        # create infinite recursion
        a = [1]
        a[0] = a
        with assert_raises(
                ValueError,
                error_re='Exceeded maximum allowed recursion level'):
            self.dumps(a)

        # by design type "bytes" is not serializable and should raise a TypeError
        with assert_raises(TypeError, error_re='not JSON serializable'):
            self.encoder_test(bytes([1, 2, 3]), None)

        # by design type "bytearray" is not serializable and should raise a TypeError
        with assert_raises(TypeError, error_re='not JSON serializable'):
            self.encoder_test(bytearray([1, 2, 3]), '[1,2,3]', False, False)
Esempio n. 10
0
    def test_json_encoder_lists(self):
        self.encoder_test([],                '[]')
        self.encoder_test(['abc',True],      '["abc",true]')
        self.encoder_test(['abc',[],[True]], '["abc",[],[true]]')

        # a tuple is converted to the same string as a "similar" list, so no conversion back
        # (but should match the default encoder)
        self.encoder_test((), '[]',                               False, True)
        self.encoder_test((1,), '[1]',                            False, True)
        self.encoder_test((1,2,[1,2,3]), '[1,2,[1,2,3]]',         False, True)
        self.encoder_test(('a','b',('c',1)), '["a","b",["c",1]]', False, True)

        self.encoder_test((99,100,999,1000,9999,10000,99999,100000),
                          '[99,100,999,1000,9999,10000,99999,100000]', False, True)

        # std module does not support sets
        self.encoder_test({1,2,3}, '[1,2,3]', False, False)

        # test max recursion level checks
        with assert_raises(ValueError, error_re='Exceeded maximum allowed recursion level'):
            self.dumps([[[1,2],3],4], max_nested_level=1)
        with assert_raises(ValueError, error_re='Exceeded maximum allowed recursion level'):
            self.dumps([[[1,2],3],4], max_nested_level=2)
        # this should work
        assert(self.dumps([[[1,2],3],4], max_nested_level=3) == '[[[1,2],3],4]')
        # create infinite recursion
        a=[1]
        a[0]=a
        with assert_raises(ValueError, error_re='Exceeded maximum allowed recursion level'):
            self.dumps(a)

        # by design type "bytes" is not serializable and should raise a TypeError
        with assert_raises(TypeError, error_re='not JSON serializable'):
            self.encoder_test(bytes([1,2,3]), None)

        # by design type "bytearray" is not serializable and should raise a TypeError
        with assert_raises(TypeError, error_re='not JSON serializable'):
            self.encoder_test(bytearray([1,2,3]), '[1,2,3]', False, False)
Esempio n. 11
0
    def test_json_hook(self):
        class Spam:
            pass

        class Encoder(self.encoder):
            def encode_hook(self, obj):
                if isinstance(obj, list):
                    return {str(i): el for i, el in enumerate(obj)}
                if isinstance(obj, int):
                    return '*' + str(obj)
                if isinstance(obj, Spam):
                    1/0
                return obj

        assert Encoder().dumps([1.11]) == '{"0":1.11}'
        assert Encoder().dumps([1])    == '{"0":"*1"}'

        with assert_raises(ZeroDivisionError):
            Encoder().dumps([Spam()])
Esempio n. 12
0
    def test_json_hook(self):
        class Spam:
            pass

        class Encoder(self.encoder):
            def encode_hook(self, obj):
                if isinstance(obj, list):
                    return {str(i): el for i, el in enumerate(obj)}
                if isinstance(obj, int):
                    return '*' + str(obj)
                if isinstance(obj, Spam):
                    1 / 0
                return obj

        assert Encoder().dumps([1.11]) == '{"0":1.11}'
        assert Encoder().dumps([1]) == '{"0":"*1"}'

        with assert_raises(ZeroDivisionError):
            Encoder().dumps([Spam()])