hyperjson 0.2.4

A hyper-fast Python module for reading/writing JSON data
Documentation
import pytest
import decimal
import hyperjson
from collections import OrderedDict
from io import StringIO

"""
These are official json tests copied from
https://github.com/python/cpython/blob/cfa797c0681b7fef47cf93955fd06b54ddd09a7f/Lib/test/test_json/test_decode.py
and converted to pytest.
If you change them, consider sending a pull request to the upstream repo, too.
"""


def test_decimal():
    rval = hyperjson.loads('1.1', parse_float=decimal.Decimal)
    assert isinstance(rval, decimal.Decimal) == True
    assert pytest.approx(rval, rel=decimal.Decimal("5e-6")
                         ) == decimal.Decimal('1.1')


def test_float():
    rval = hyperjson.loads('1', parse_int=float)
    assert isinstance(rval, float)
    assert rval == 1.0


def test_empty_objects():
    assert hyperjson.loads('{}') == {}
    assert hyperjson.loads('[]') == []
    assert hyperjson.loads('""') == ""


@pytest.mark.skip(reason="object_pairs_hook not implemented yet")
def test_object_pairs_hook(self):
    s = '{"xkd":1, "kcw":2, "art":3, "hxm":4, "qrt":5, "pad":6, "hoy":7}'
    p = [("xkd", 1), ("kcw", 2), ("art", 3), ("hxm", 4),
         ("qrt", 5), ("pad", 6), ("hoy", 7)]
    assert hyperjson.loads(s) == eval(s)
    assert hyperjson.loads(s, object_pairs_hook=lambda x: x) == p
    assert hyperjson.load(StringIO(s), object_pairs_hook=lambda x: x) == p
    od = hyperjson.loads(s, object_pairs_hook=OrderedDict)
    assert od == OrderedDict(p)
    assert type(od) == OrderedDict
    # the object_pairs_hook takes priority over the object_hook
    assert hyperjson.loads(s, object_pairs_hook=OrderedDict,
                           object_hook=lambda x: None) == OrderedDict(p)
    # check that empty object literals work (see #17368)
    assert hyperjson.loads(
        '{}', object_pairs_hook=OrderedDict) == OrderedDict()
    assert hyperjson.loads('{"empty": {}}', object_pairs_hook=OrderedDict) == OrderedDict(
        [('empty', OrderedDict())])


def test_decoder_optimizations():
    # Several optimizations were made that skip over calls to
    # the whitespace regex, so this test is designed to try and
    # exercise the uncommon cases. The array cases are already covered.
    rval = hyperjson.loads('{   "key"    :    "value"    ,  "k":"v"    }')
    assert rval == {"key": "value", "k": "v"}


def test_keys_reuse():
    s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]'
    rval = hyperjson.loads(s)
    (a, b), (c, d) = sorted(rval[0]), sorted(rval[1])
    assert a == c
    assert b == d


@pytest.mark.skip(reason="Error type not implemented yet")
def test_extra_data(self):
    s = '[1, 2, 3]5'
    msg = 'Extra data'
    self.assertRaisesRegex(self.JSONDecodeError, msg, hyperjson.loads, s)


@pytest.mark.skip(reason="Error type not implemented yet")
def test_invalid_escape(self):
    s = '["abc\\y"]'
    msg = 'escape'
    self.assertRaisesRegex(self.JSONDecodeError, msg, hyperjson.loads, s)


@pytest.mark.skip(reason="Error type not implemented yet")
def test_invalid_input_type(self):
    msg = 'the JSON object must be str'
    for value in [1, 3.14, [], {}, None]:
        self.assertRaisesRegex(TypeError, msg, hyperjson.loads, value)


@pytest.mark.skip(reason="Error type not implemented yet")
def test_string_with_utf8_bom(self):
    # see #18958
    bom_json = "[1,2,3]".encode('utf-8-sig').decode('utf-8')
    with self.assertRaises(self.JSONDecodeError) as cm:
        self.loads(bom_json)
    self.assertIn('BOM', str(cm.exception))
    with self.assertRaises(self.JSONDecodeError) as cm:
        self.json.load(StringIO(bom_json))
    self.assertIn('BOM', str(cm.exception))
    # make sure that the BOM is not detected in the middle of a string
    bom_in_str = '"{}"'.format(''.encode('utf-8-sig').decode('utf-8'))
    self.assertEqual(self.loads(bom_in_str), '\ufeff')
    self.assertEqual(self.json.load(StringIO(bom_in_str)), '\ufeff')