File: test_decode.py

package info (click to toggle)
python-sdjson 0.5.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 560 kB
  • sloc: python: 1,566; makefile: 6; sh: 6
file content (130 lines) | stat: -rw-r--r-- 3,805 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# stdlib
import decimal
import re
from collections import OrderedDict
from io import StringIO
from typing import Callable

# 3rd party
import pytest
from coincidence.selectors import not_pypy
from domdf_python_tools.compat import PYPY

# this package
import sdjson


def test_decimal() -> None:
	rval = sdjson.loads("1.1", parse_float=decimal.Decimal)
	assert isinstance(rval, decimal.Decimal)
	assert rval == decimal.Decimal("1.1")


def test_float() -> None:
	rval = sdjson.loads('1', parse_int=float)
	assert isinstance(rval, float)
	assert rval == 1.0


def test_empty_objects() -> None:
	assert sdjson.loads("{}") == {}
	assert sdjson.loads("[]") == []
	assert sdjson.loads('""') == ''


def test_object_pairs_hook() -> None:
	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 sdjson.loads(s, object_pairs_hook=lambda x: x) == p
	assert sdjson.load(StringIO(s), object_pairs_hook=lambda x: x) == p
	od = sdjson.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 sdjson.loads(s, object_pairs_hook=OrderedDict, object_hook=lambda x: None) == OrderedDict(p)
	# check that empty object literals work (see #17368)
	assert sdjson.loads("{}", object_pairs_hook=OrderedDict) == OrderedDict()
	assert sdjson.loads('{"empty": {}}', object_pairs_hook=OrderedDict) == OrderedDict([("empty", OrderedDict())])


def test_decoder_optimizations() -> None:
	# 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 = sdjson.loads('{   "key"    :    "value"    ,  "k":"v"    }')
	assert rval == {"key": "value", 'k': 'v'}


def check_keys_reuse(source: str, loads: Callable) -> None:
	rval = loads(source)
	(a, b), (c, d) = sorted(rval[0]), sorted(rval[1])
	assert a == c
	assert b == d


@not_pypy(reason="Strange behaviour with PyPy")
def test_keys_reuse():
	s = '[{"a_key": 1, "b_é": 2}, {"a_key": 3, "b_é": 4}]'
	check_keys_reuse(s, sdjson.loads)
	decoder = sdjson.JSONDecoder()
	check_keys_reuse(s, decoder.decode)
	assert not decoder.memo


def test_extra_data():
	s = "[1, 2, 3]5"
	msg = "Extra data"
	with pytest.raises(sdjson.JSONDecodeError, match=msg):
		sdjson.loads(s)


def test_invalid_escape() -> None:
	s = '["abc\\y"]'
	msg = "escape"
	with pytest.raises(sdjson.JSONDecodeError, match=msg):
		sdjson.loads(s)


def test_invalid_input_type() -> None:
	msg = "the JSON object must be str"

	for value in [1, 3.14, [], {}, None]:
		with pytest.raises(TypeError, match=msg):
			sdjson.loads(value)  # type: ignore[arg-type]


def test_string_with_utf8_bom() -> None:

	# stdlib
	import sys

	# see #18958
	bom_json = "[1,2,3]".encode("utf-8-sig").decode("utf-8")
	with pytest.raises(sdjson.JSONDecodeError) as e:
		sdjson.loads(bom_json)
	# TODO:
	if sys.version_info.major >= 3 and sys.version_info.minor == 7:
		assert "BOM" in str(e)

	with pytest.raises(sdjson.JSONDecodeError) as e:
		sdjson.load(StringIO(bom_json))
	# TODO:
	if sys.version_info.major >= 3 and sys.version_info.minor == 7:
		assert "BOM" in str(e)

	# 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"))
	assert sdjson.loads(bom_in_str) == '\ufeff'
	assert sdjson.load(StringIO(bom_in_str)) == '\ufeff'


def test_negative_index() -> None:
	d = sdjson.JSONDecoder()

	if PYPY:
		match = re.escape("Expecting value: line 1 column -49999 (char -50000)")
	else:
		match = "idx cannot be negative"

	with pytest.raises(ValueError, match=match):
		d.raw_decode('a' * 42, -50000)