Removed the Requirement to Install Python and NodeJS (Now Bundled with Borealis)
This commit is contained in:
58
Dependencies/Python/Lib/test/test_json/__init__.py
vendored
Normal file
58
Dependencies/Python/Lib/test/test_json/__init__.py
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
import os
|
||||
import json
|
||||
import doctest
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
from test.support import import_helper
|
||||
|
||||
|
||||
# import json with and without accelerations
|
||||
cjson = import_helper.import_fresh_module('json', fresh=['_json'])
|
||||
pyjson = import_helper.import_fresh_module('json', blocked=['_json'])
|
||||
# JSONDecodeError is cached inside the _json module
|
||||
cjson.JSONDecodeError = cjson.decoder.JSONDecodeError = json.JSONDecodeError
|
||||
|
||||
# create two base classes that will be used by the other tests
|
||||
class PyTest(unittest.TestCase):
|
||||
json = pyjson
|
||||
loads = staticmethod(pyjson.loads)
|
||||
dumps = staticmethod(pyjson.dumps)
|
||||
JSONDecodeError = staticmethod(pyjson.JSONDecodeError)
|
||||
|
||||
@unittest.skipUnless(cjson, 'requires _json')
|
||||
class CTest(unittest.TestCase):
|
||||
if cjson is not None:
|
||||
json = cjson
|
||||
loads = staticmethod(cjson.loads)
|
||||
dumps = staticmethod(cjson.dumps)
|
||||
JSONDecodeError = staticmethod(cjson.JSONDecodeError)
|
||||
|
||||
# test PyTest and CTest checking if the functions come from the right module
|
||||
class TestPyTest(PyTest):
|
||||
def test_pyjson(self):
|
||||
self.assertEqual(self.json.scanner.make_scanner.__module__,
|
||||
'json.scanner')
|
||||
self.assertEqual(self.json.decoder.scanstring.__module__,
|
||||
'json.decoder')
|
||||
self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__,
|
||||
'json.encoder')
|
||||
|
||||
class TestCTest(CTest):
|
||||
def test_cjson(self):
|
||||
self.assertEqual(self.json.scanner.make_scanner.__module__, '_json')
|
||||
self.assertEqual(self.json.decoder.scanstring.__module__, '_json')
|
||||
self.assertEqual(self.json.encoder.c_make_encoder.__module__, '_json')
|
||||
self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__,
|
||||
'_json')
|
||||
|
||||
|
||||
def load_tests(loader, _, pattern):
|
||||
suite = unittest.TestSuite()
|
||||
for mod in (json, json.encoder, json.decoder):
|
||||
suite.addTest(doctest.DocTestSuite(mod))
|
||||
suite.addTest(TestPyTest('test_pyjson'))
|
||||
suite.addTest(TestCTest('test_cjson'))
|
||||
|
||||
pkg_dir = os.path.dirname(__file__)
|
||||
return support.load_package_tests(pkg_dir, loader, suite, pattern)
|
4
Dependencies/Python/Lib/test/test_json/__main__.py
vendored
Normal file
4
Dependencies/Python/Lib/test/test_json/__main__.py
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import unittest
|
||||
from test.test_json import load_tests
|
||||
|
||||
unittest.main()
|
135
Dependencies/Python/Lib/test/test_json/test_decode.py
vendored
Normal file
135
Dependencies/Python/Lib/test/test_json/test_decode.py
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
import decimal
|
||||
from io import StringIO
|
||||
from collections import OrderedDict
|
||||
from test.test_json import PyTest, CTest
|
||||
from test import support
|
||||
|
||||
|
||||
class TestDecode:
|
||||
def test_decimal(self):
|
||||
rval = self.loads('1.1', parse_float=decimal.Decimal)
|
||||
self.assertIsInstance(rval, decimal.Decimal)
|
||||
self.assertEqual(rval, decimal.Decimal('1.1'))
|
||||
|
||||
def test_float(self):
|
||||
rval = self.loads('1', parse_int=float)
|
||||
self.assertIsInstance(rval, float)
|
||||
self.assertEqual(rval, 1.0)
|
||||
|
||||
def test_nonascii_digits_rejected(self):
|
||||
# JSON specifies only ascii digits, see gh-125687
|
||||
for num in ["1\uff10", "0.\uff10", "0e\uff10"]:
|
||||
with self.assertRaises(self.JSONDecodeError):
|
||||
self.loads(num)
|
||||
|
||||
def test_bytes(self):
|
||||
self.assertEqual(self.loads(b"1"), 1)
|
||||
|
||||
def test_parse_constant(self):
|
||||
for constant, expected in [
|
||||
("Infinity", "INFINITY"),
|
||||
("-Infinity", "-INFINITY"),
|
||||
("NaN", "NAN"),
|
||||
]:
|
||||
self.assertEqual(
|
||||
self.loads(constant, parse_constant=str.upper), expected
|
||||
)
|
||||
|
||||
def test_constant_invalid_case(self):
|
||||
for constant in [
|
||||
"nan", "NAN", "naN", "infinity", "INFINITY", "inFiniTy"
|
||||
]:
|
||||
with self.assertRaises(self.JSONDecodeError):
|
||||
self.loads(constant)
|
||||
|
||||
def test_empty_objects(self):
|
||||
self.assertEqual(self.loads('{}'), {})
|
||||
self.assertEqual(self.loads('[]'), [])
|
||||
self.assertEqual(self.loads('""'), "")
|
||||
|
||||
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)]
|
||||
self.assertEqual(self.loads(s), eval(s))
|
||||
self.assertEqual(self.loads(s, object_pairs_hook=lambda x: x), p)
|
||||
self.assertEqual(self.json.load(StringIO(s),
|
||||
object_pairs_hook=lambda x: x), p)
|
||||
od = self.loads(s, object_pairs_hook=OrderedDict)
|
||||
self.assertEqual(od, OrderedDict(p))
|
||||
self.assertEqual(type(od), OrderedDict)
|
||||
# the object_pairs_hook takes priority over the object_hook
|
||||
self.assertEqual(self.loads(s, object_pairs_hook=OrderedDict,
|
||||
object_hook=lambda x: None),
|
||||
OrderedDict(p))
|
||||
# check that empty object literals work (see #17368)
|
||||
self.assertEqual(self.loads('{}', object_pairs_hook=OrderedDict),
|
||||
OrderedDict())
|
||||
self.assertEqual(self.loads('{"empty": {}}',
|
||||
object_pairs_hook=OrderedDict),
|
||||
OrderedDict([('empty', OrderedDict())]))
|
||||
|
||||
def test_decoder_optimizations(self):
|
||||
# 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 = self.loads('{ "key" : "value" , "k":"v" }')
|
||||
self.assertEqual(rval, {"key":"value", "k":"v"})
|
||||
|
||||
def check_keys_reuse(self, source, loads):
|
||||
rval = loads(source)
|
||||
(a, b), (c, d) = sorted(rval[0]), sorted(rval[1])
|
||||
self.assertIs(a, c)
|
||||
self.assertIs(b, d)
|
||||
|
||||
def test_keys_reuse(self):
|
||||
s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]'
|
||||
self.check_keys_reuse(s, self.loads)
|
||||
decoder = self.json.decoder.JSONDecoder()
|
||||
self.check_keys_reuse(s, decoder.decode)
|
||||
self.assertFalse(decoder.memo)
|
||||
|
||||
def test_extra_data(self):
|
||||
s = '[1, 2, 3]5'
|
||||
msg = 'Extra data'
|
||||
self.assertRaisesRegex(self.JSONDecodeError, msg, self.loads, s)
|
||||
|
||||
def test_invalid_escape(self):
|
||||
s = '["abc\\y"]'
|
||||
msg = 'escape'
|
||||
self.assertRaisesRegex(self.JSONDecodeError, msg, self.loads, s)
|
||||
|
||||
def test_invalid_input_type(self):
|
||||
msg = 'the JSON object must be str'
|
||||
for value in [1, 3.14, [], {}, None]:
|
||||
self.assertRaisesRegex(TypeError, msg, self.loads, value)
|
||||
|
||||
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 = ''.encode('utf-8-sig').decode('utf-8')
|
||||
bom_in_str = f'"{bom}"'
|
||||
self.assertEqual(self.loads(bom_in_str), '\ufeff')
|
||||
self.assertEqual(self.json.load(StringIO(bom_in_str)), '\ufeff')
|
||||
|
||||
def test_negative_index(self):
|
||||
d = self.json.JSONDecoder()
|
||||
self.assertRaises(ValueError, d.raw_decode, 'a'*42, -50000)
|
||||
|
||||
def test_limit_int(self):
|
||||
maxdigits = 5000
|
||||
with support.adjust_int_max_str_digits(maxdigits):
|
||||
self.loads('1' * maxdigits)
|
||||
with self.assertRaises(ValueError):
|
||||
self.loads('1' * (maxdigits + 1))
|
||||
|
||||
|
||||
class TestPyDecode(TestDecode, PyTest): pass
|
||||
class TestCDecode(TestDecode, CTest): pass
|
23
Dependencies/Python/Lib/test/test_json/test_default.py
vendored
Normal file
23
Dependencies/Python/Lib/test/test_json/test_default.py
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import collections
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class TestDefault:
|
||||
def test_default(self):
|
||||
self.assertEqual(
|
||||
self.dumps(type, default=repr),
|
||||
self.dumps(repr(type)))
|
||||
|
||||
def test_ordereddict(self):
|
||||
od = collections.OrderedDict(a=1, b=2, c=3, d=4)
|
||||
od.move_to_end('b')
|
||||
self.assertEqual(
|
||||
self.dumps(od),
|
||||
'{"a": 1, "c": 3, "d": 4, "b": 2}')
|
||||
self.assertEqual(
|
||||
self.dumps(od, sort_keys=True),
|
||||
'{"a": 1, "b": 2, "c": 3, "d": 4}')
|
||||
|
||||
|
||||
class TestPyDefault(TestDefault, PyTest): pass
|
||||
class TestCDefault(TestDefault, CTest): pass
|
78
Dependencies/Python/Lib/test/test_json/test_dump.py
vendored
Normal file
78
Dependencies/Python/Lib/test/test_json/test_dump.py
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
from io import StringIO
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
from test.support import bigmemtest, _1G
|
||||
|
||||
class TestDump:
|
||||
def test_dump(self):
|
||||
sio = StringIO()
|
||||
self.json.dump({}, sio)
|
||||
self.assertEqual(sio.getvalue(), '{}')
|
||||
|
||||
def test_dumps(self):
|
||||
self.assertEqual(self.dumps({}), '{}')
|
||||
|
||||
def test_dump_skipkeys(self):
|
||||
v = {b'invalid_key': False, 'valid_key': True}
|
||||
with self.assertRaises(TypeError):
|
||||
self.json.dumps(v)
|
||||
|
||||
s = self.json.dumps(v, skipkeys=True)
|
||||
o = self.json.loads(s)
|
||||
self.assertIn('valid_key', o)
|
||||
self.assertNotIn(b'invalid_key', o)
|
||||
|
||||
def test_encode_truefalse(self):
|
||||
self.assertEqual(self.dumps(
|
||||
{True: False, False: True}, sort_keys=True),
|
||||
'{"false": true, "true": false}')
|
||||
self.assertEqual(self.dumps(
|
||||
{2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True),
|
||||
'{"false": 1, "2": 3.0, "4.0": 5, "6": true}')
|
||||
|
||||
# Issue 16228: Crash on encoding resized list
|
||||
def test_encode_mutated(self):
|
||||
a = [object()] * 10
|
||||
def crasher(obj):
|
||||
del a[-1]
|
||||
self.assertEqual(self.dumps(a, default=crasher),
|
||||
'[null, null, null, null, null]')
|
||||
|
||||
# Issue 24094
|
||||
def test_encode_evil_dict(self):
|
||||
class D(dict):
|
||||
def keys(self):
|
||||
return L
|
||||
|
||||
class X:
|
||||
def __hash__(self):
|
||||
del L[0]
|
||||
return 1337
|
||||
|
||||
def __lt__(self, o):
|
||||
return 0
|
||||
|
||||
L = [X() for i in range(1122)]
|
||||
d = D()
|
||||
d[1337] = "true.dat"
|
||||
self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}')
|
||||
|
||||
|
||||
class TestPyDump(TestDump, PyTest): pass
|
||||
|
||||
class TestCDump(TestDump, CTest):
|
||||
|
||||
# The size requirement here is hopefully over-estimated (actual
|
||||
# memory consumption depending on implementation details, and also
|
||||
# system memory management, since this may allocate a lot of
|
||||
# small objects).
|
||||
|
||||
@bigmemtest(size=_1G, memuse=1)
|
||||
def test_large_list(self, size):
|
||||
N = int(30 * 1024 * 1024 * (size / _1G))
|
||||
l = [1] * N
|
||||
encoded = self.dumps(l)
|
||||
self.assertEqual(len(encoded), N * 3)
|
||||
self.assertEqual(encoded[:1], "[")
|
||||
self.assertEqual(encoded[-2:], "1]")
|
||||
self.assertEqual(encoded[1:-2], "1, " * (N - 1))
|
47
Dependencies/Python/Lib/test/test_json/test_encode_basestring_ascii.py
vendored
Normal file
47
Dependencies/Python/Lib/test/test_json/test_encode_basestring_ascii.py
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
from collections import OrderedDict
|
||||
from test.test_json import PyTest, CTest
|
||||
from test.support import bigaddrspacetest
|
||||
|
||||
|
||||
CASES = [
|
||||
('/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"'),
|
||||
('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'),
|
||||
('controls', '"controls"'),
|
||||
('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'),
|
||||
('{"object with 1 member":["array with 1 element"]}', '"{\\"object with 1 member\\":[\\"array with 1 element\\"]}"'),
|
||||
(' s p a c e d ', '" s p a c e d "'),
|
||||
('\U0001d120', '"\\ud834\\udd20"'),
|
||||
('\u03b1\u03a9', '"\\u03b1\\u03a9"'),
|
||||
("`1~!@#$%^&*()_+-={':[,]}|;.</>?", '"`1~!@#$%^&*()_+-={\':[,]}|;.</>?"'),
|
||||
('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'),
|
||||
('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'),
|
||||
]
|
||||
|
||||
class TestEncodeBasestringAscii:
|
||||
def test_encode_basestring_ascii(self):
|
||||
fname = self.json.encoder.encode_basestring_ascii.__name__
|
||||
for input_string, expect in CASES:
|
||||
result = self.json.encoder.encode_basestring_ascii(input_string)
|
||||
self.assertEqual(result, expect,
|
||||
f'{result!r} != {expect!r} for {fname}({input_string!r})')
|
||||
|
||||
def test_ordered_dict(self):
|
||||
# See issue 6105
|
||||
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
|
||||
s = self.dumps(OrderedDict(items))
|
||||
self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}')
|
||||
|
||||
def test_sorted_dict(self):
|
||||
items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]
|
||||
s = self.dumps(dict(items), sort_keys=True)
|
||||
self.assertEqual(s, '{"five": 5, "four": 4, "one": 1, "three": 3, "two": 2}')
|
||||
|
||||
|
||||
class TestPyEncodeBasestringAscii(TestEncodeBasestringAscii, PyTest): pass
|
||||
class TestCEncodeBasestringAscii(TestEncodeBasestringAscii, CTest):
|
||||
@bigaddrspacetest
|
||||
def test_overflow(self):
|
||||
size = (2**32)//6 + 1
|
||||
s = "\x00"*size
|
||||
with self.assertRaises(OverflowError):
|
||||
self.json.encoder.encode_basestring_ascii(s)
|
120
Dependencies/Python/Lib/test/test_json/test_enum.py
vendored
Normal file
120
Dependencies/Python/Lib/test/test_json/test_enum.py
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
from enum import Enum, IntEnum
|
||||
from math import isnan
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
SMALL = 1
|
||||
BIG = 1<<32
|
||||
HUGE = 1<<64
|
||||
REALLY_HUGE = 1<<96
|
||||
|
||||
class BigNum(IntEnum):
|
||||
small = SMALL
|
||||
big = BIG
|
||||
huge = HUGE
|
||||
really_huge = REALLY_HUGE
|
||||
|
||||
E = 2.718281
|
||||
PI = 3.141593
|
||||
TAU = 2 * PI
|
||||
|
||||
class FloatNum(float, Enum):
|
||||
e = E
|
||||
pi = PI
|
||||
tau = TAU
|
||||
|
||||
INF = float('inf')
|
||||
NEG_INF = float('-inf')
|
||||
NAN = float('nan')
|
||||
|
||||
class WierdNum(float, Enum):
|
||||
inf = INF
|
||||
neg_inf = NEG_INF
|
||||
nan = NAN
|
||||
|
||||
class TestEnum:
|
||||
|
||||
def test_floats(self):
|
||||
for enum in FloatNum:
|
||||
self.assertEqual(self.dumps(enum), repr(enum.value))
|
||||
self.assertEqual(float(self.dumps(enum)), enum)
|
||||
self.assertEqual(self.loads(self.dumps(enum)), enum)
|
||||
|
||||
def test_weird_floats(self):
|
||||
for enum, expected in zip(WierdNum, ('Infinity', '-Infinity', 'NaN')):
|
||||
self.assertEqual(self.dumps(enum), expected)
|
||||
if not isnan(enum):
|
||||
self.assertEqual(float(self.dumps(enum)), enum)
|
||||
self.assertEqual(self.loads(self.dumps(enum)), enum)
|
||||
else:
|
||||
self.assertTrue(isnan(float(self.dumps(enum))))
|
||||
self.assertTrue(isnan(self.loads(self.dumps(enum))))
|
||||
|
||||
def test_ints(self):
|
||||
for enum in BigNum:
|
||||
self.assertEqual(self.dumps(enum), str(enum.value))
|
||||
self.assertEqual(int(self.dumps(enum)), enum)
|
||||
self.assertEqual(self.loads(self.dumps(enum)), enum)
|
||||
|
||||
def test_list(self):
|
||||
self.assertEqual(self.dumps(list(BigNum)),
|
||||
str([SMALL, BIG, HUGE, REALLY_HUGE]))
|
||||
self.assertEqual(self.loads(self.dumps(list(BigNum))),
|
||||
list(BigNum))
|
||||
self.assertEqual(self.dumps(list(FloatNum)),
|
||||
str([E, PI, TAU]))
|
||||
self.assertEqual(self.loads(self.dumps(list(FloatNum))),
|
||||
list(FloatNum))
|
||||
self.assertEqual(self.dumps(list(WierdNum)),
|
||||
'[Infinity, -Infinity, NaN]')
|
||||
self.assertEqual(self.loads(self.dumps(list(WierdNum)))[:2],
|
||||
list(WierdNum)[:2])
|
||||
self.assertTrue(isnan(self.loads(self.dumps(list(WierdNum)))[2]))
|
||||
|
||||
def test_dict_keys(self):
|
||||
s, b, h, r = BigNum
|
||||
e, p, t = FloatNum
|
||||
i, j, n = WierdNum
|
||||
d = {
|
||||
s:'tiny', b:'large', h:'larger', r:'largest',
|
||||
e:"Euler's number", p:'pi', t:'tau',
|
||||
i:'Infinity', j:'-Infinity', n:'NaN',
|
||||
}
|
||||
nd = self.loads(self.dumps(d))
|
||||
self.assertEqual(nd[str(SMALL)], 'tiny')
|
||||
self.assertEqual(nd[str(BIG)], 'large')
|
||||
self.assertEqual(nd[str(HUGE)], 'larger')
|
||||
self.assertEqual(nd[str(REALLY_HUGE)], 'largest')
|
||||
self.assertEqual(nd[repr(E)], "Euler's number")
|
||||
self.assertEqual(nd[repr(PI)], 'pi')
|
||||
self.assertEqual(nd[repr(TAU)], 'tau')
|
||||
self.assertEqual(nd['Infinity'], 'Infinity')
|
||||
self.assertEqual(nd['-Infinity'], '-Infinity')
|
||||
self.assertEqual(nd['NaN'], 'NaN')
|
||||
|
||||
def test_dict_values(self):
|
||||
d = dict(
|
||||
tiny=BigNum.small,
|
||||
large=BigNum.big,
|
||||
larger=BigNum.huge,
|
||||
largest=BigNum.really_huge,
|
||||
e=FloatNum.e,
|
||||
pi=FloatNum.pi,
|
||||
tau=FloatNum.tau,
|
||||
i=WierdNum.inf,
|
||||
j=WierdNum.neg_inf,
|
||||
n=WierdNum.nan,
|
||||
)
|
||||
nd = self.loads(self.dumps(d))
|
||||
self.assertEqual(nd['tiny'], SMALL)
|
||||
self.assertEqual(nd['large'], BIG)
|
||||
self.assertEqual(nd['larger'], HUGE)
|
||||
self.assertEqual(nd['largest'], REALLY_HUGE)
|
||||
self.assertEqual(nd['e'], E)
|
||||
self.assertEqual(nd['pi'], PI)
|
||||
self.assertEqual(nd['tau'], TAU)
|
||||
self.assertEqual(nd['i'], INF)
|
||||
self.assertEqual(nd['j'], NEG_INF)
|
||||
self.assertTrue(isnan(nd['n']))
|
||||
|
||||
class TestPyEnum(TestEnum, PyTest): pass
|
||||
class TestCEnum(TestEnum, CTest): pass
|
221
Dependencies/Python/Lib/test/test_json/test_fail.py
vendored
Normal file
221
Dependencies/Python/Lib/test/test_json/test_fail.py
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
# 2007-10-05
|
||||
JSONDOCS = [
|
||||
# https://json.org/JSON_checker/test/fail1.json
|
||||
'"A JSON payload should be an object or array, not a string."',
|
||||
# https://json.org/JSON_checker/test/fail2.json
|
||||
'["Unclosed array"',
|
||||
# https://json.org/JSON_checker/test/fail3.json
|
||||
'{unquoted_key: "keys must be quoted"}',
|
||||
# https://json.org/JSON_checker/test/fail4.json
|
||||
'["extra comma",]',
|
||||
# https://json.org/JSON_checker/test/fail5.json
|
||||
'["double extra comma",,]',
|
||||
# https://json.org/JSON_checker/test/fail6.json
|
||||
'[ , "<-- missing value"]',
|
||||
# https://json.org/JSON_checker/test/fail7.json
|
||||
'["Comma after the close"],',
|
||||
# https://json.org/JSON_checker/test/fail8.json
|
||||
'["Extra close"]]',
|
||||
# https://json.org/JSON_checker/test/fail9.json
|
||||
'{"Extra comma": true,}',
|
||||
# https://json.org/JSON_checker/test/fail10.json
|
||||
'{"Extra value after close": true} "misplaced quoted value"',
|
||||
# https://json.org/JSON_checker/test/fail11.json
|
||||
'{"Illegal expression": 1 + 2}',
|
||||
# https://json.org/JSON_checker/test/fail12.json
|
||||
'{"Illegal invocation": alert()}',
|
||||
# https://json.org/JSON_checker/test/fail13.json
|
||||
'{"Numbers cannot have leading zeroes": 013}',
|
||||
# https://json.org/JSON_checker/test/fail14.json
|
||||
'{"Numbers cannot be hex": 0x14}',
|
||||
# https://json.org/JSON_checker/test/fail15.json
|
||||
'["Illegal backslash escape: \\x15"]',
|
||||
# https://json.org/JSON_checker/test/fail16.json
|
||||
'[\\naked]',
|
||||
# https://json.org/JSON_checker/test/fail17.json
|
||||
'["Illegal backslash escape: \\017"]',
|
||||
# https://json.org/JSON_checker/test/fail18.json
|
||||
'[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]',
|
||||
# https://json.org/JSON_checker/test/fail19.json
|
||||
'{"Missing colon" null}',
|
||||
# https://json.org/JSON_checker/test/fail20.json
|
||||
'{"Double colon":: null}',
|
||||
# https://json.org/JSON_checker/test/fail21.json
|
||||
'{"Comma instead of colon", null}',
|
||||
# https://json.org/JSON_checker/test/fail22.json
|
||||
'["Colon instead of comma": false]',
|
||||
# https://json.org/JSON_checker/test/fail23.json
|
||||
'["Bad value", truth]',
|
||||
# https://json.org/JSON_checker/test/fail24.json
|
||||
"['single quote']",
|
||||
# https://json.org/JSON_checker/test/fail25.json
|
||||
'["\ttab\tcharacter\tin\tstring\t"]',
|
||||
# https://json.org/JSON_checker/test/fail26.json
|
||||
'["tab\\ character\\ in\\ string\\ "]',
|
||||
# https://json.org/JSON_checker/test/fail27.json
|
||||
'["line\nbreak"]',
|
||||
# https://json.org/JSON_checker/test/fail28.json
|
||||
'["line\\\nbreak"]',
|
||||
# https://json.org/JSON_checker/test/fail29.json
|
||||
'[0e]',
|
||||
# https://json.org/JSON_checker/test/fail30.json
|
||||
'[0e+]',
|
||||
# https://json.org/JSON_checker/test/fail31.json
|
||||
'[0e+-1]',
|
||||
# https://json.org/JSON_checker/test/fail32.json
|
||||
'{"Comma instead if closing brace": true,',
|
||||
# https://json.org/JSON_checker/test/fail33.json
|
||||
'["mismatch"}',
|
||||
# https://code.google.com/archive/p/simplejson/issues/3
|
||||
'["A\u001FZ control characters in string"]',
|
||||
]
|
||||
|
||||
SKIPS = {
|
||||
1: "why not have a string payload?",
|
||||
18: "spec doesn't specify any nesting limitations",
|
||||
}
|
||||
|
||||
class TestFail:
|
||||
def test_failures(self):
|
||||
for idx, doc in enumerate(JSONDOCS):
|
||||
idx = idx + 1
|
||||
if idx in SKIPS:
|
||||
self.loads(doc)
|
||||
continue
|
||||
try:
|
||||
self.loads(doc)
|
||||
except self.JSONDecodeError:
|
||||
pass
|
||||
else:
|
||||
self.fail(f"Expected failure for fail{idx}.json: {doc!r}")
|
||||
|
||||
def test_non_string_keys_dict(self):
|
||||
data = {'a' : 1, (1, 2) : 2}
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
'keys must be str, int, float, bool or None, not tuple'):
|
||||
self.dumps(data)
|
||||
|
||||
def test_not_serializable(self):
|
||||
import sys
|
||||
with self.assertRaisesRegex(TypeError,
|
||||
'Object of type module is not JSON serializable'):
|
||||
self.dumps(sys)
|
||||
|
||||
def test_truncated_input(self):
|
||||
test_cases = [
|
||||
('', 'Expecting value', 0),
|
||||
('[', 'Expecting value', 1),
|
||||
('[42', "Expecting ',' delimiter", 3),
|
||||
('[42,', 'Expecting value', 4),
|
||||
('["', 'Unterminated string starting at', 1),
|
||||
('["spam', 'Unterminated string starting at', 1),
|
||||
('["spam"', "Expecting ',' delimiter", 7),
|
||||
('["spam",', 'Expecting value', 8),
|
||||
('{', 'Expecting property name enclosed in double quotes', 1),
|
||||
('{"', 'Unterminated string starting at', 1),
|
||||
('{"spam', 'Unterminated string starting at', 1),
|
||||
('{"spam"', "Expecting ':' delimiter", 7),
|
||||
('{"spam":', 'Expecting value', 8),
|
||||
('{"spam":42', "Expecting ',' delimiter", 10),
|
||||
('{"spam":42,', 'Expecting property name enclosed in double quotes', 11),
|
||||
]
|
||||
test_cases += [
|
||||
('"', 'Unterminated string starting at', 0),
|
||||
('"spam', 'Unterminated string starting at', 0),
|
||||
]
|
||||
for data, msg, idx in test_cases:
|
||||
with self.assertRaises(self.JSONDecodeError) as cm:
|
||||
self.loads(data)
|
||||
err = cm.exception
|
||||
self.assertEqual(err.msg, msg)
|
||||
self.assertEqual(err.pos, idx)
|
||||
self.assertEqual(err.lineno, 1)
|
||||
self.assertEqual(err.colno, idx + 1)
|
||||
self.assertEqual(str(err),
|
||||
'%s: line 1 column %d (char %d)' %
|
||||
(msg, idx + 1, idx))
|
||||
|
||||
def test_unexpected_data(self):
|
||||
test_cases = [
|
||||
('[,', 'Expecting value', 1),
|
||||
('{"spam":[}', 'Expecting value', 9),
|
||||
('[42:', "Expecting ',' delimiter", 3),
|
||||
('[42 "spam"', "Expecting ',' delimiter", 4),
|
||||
('[42,]', "Illegal trailing comma before end of array", 3),
|
||||
('{"spam":[42}', "Expecting ',' delimiter", 11),
|
||||
('["]', 'Unterminated string starting at', 1),
|
||||
('["spam":', "Expecting ',' delimiter", 7),
|
||||
('["spam",]', "Illegal trailing comma before end of array", 7),
|
||||
('{:', 'Expecting property name enclosed in double quotes', 1),
|
||||
('{,', 'Expecting property name enclosed in double quotes', 1),
|
||||
('{42', 'Expecting property name enclosed in double quotes', 1),
|
||||
('[{]', 'Expecting property name enclosed in double quotes', 2),
|
||||
('{"spam",', "Expecting ':' delimiter", 7),
|
||||
('{"spam"}', "Expecting ':' delimiter", 7),
|
||||
('[{"spam"]', "Expecting ':' delimiter", 8),
|
||||
('{"spam":}', 'Expecting value', 8),
|
||||
('[{"spam":]', 'Expecting value', 9),
|
||||
('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
|
||||
('[{"spam":42]', "Expecting ',' delimiter", 11),
|
||||
('{"spam":42,}', "Illegal trailing comma before end of object", 10),
|
||||
('{"spam":42 , }', "Illegal trailing comma before end of object", 11),
|
||||
('[123 , ]', "Illegal trailing comma before end of array", 6),
|
||||
]
|
||||
for data, msg, idx in test_cases:
|
||||
with self.assertRaises(self.JSONDecodeError) as cm:
|
||||
self.loads(data)
|
||||
err = cm.exception
|
||||
self.assertEqual(err.msg, msg)
|
||||
self.assertEqual(err.pos, idx)
|
||||
self.assertEqual(err.lineno, 1)
|
||||
self.assertEqual(err.colno, idx + 1)
|
||||
self.assertEqual(str(err),
|
||||
'%s: line 1 column %d (char %d)' %
|
||||
(msg, idx + 1, idx))
|
||||
|
||||
def test_extra_data(self):
|
||||
test_cases = [
|
||||
('[]]', 'Extra data', 2),
|
||||
('{}}', 'Extra data', 2),
|
||||
('[],[]', 'Extra data', 2),
|
||||
('{},{}', 'Extra data', 2),
|
||||
]
|
||||
test_cases += [
|
||||
('42,"spam"', 'Extra data', 2),
|
||||
('"spam",42', 'Extra data', 6),
|
||||
]
|
||||
for data, msg, idx in test_cases:
|
||||
with self.assertRaises(self.JSONDecodeError) as cm:
|
||||
self.loads(data)
|
||||
err = cm.exception
|
||||
self.assertEqual(err.msg, msg)
|
||||
self.assertEqual(err.pos, idx)
|
||||
self.assertEqual(err.lineno, 1)
|
||||
self.assertEqual(err.colno, idx + 1)
|
||||
self.assertEqual(str(err),
|
||||
'%s: line 1 column %d (char %d)' %
|
||||
(msg, idx + 1, idx))
|
||||
|
||||
def test_linecol(self):
|
||||
test_cases = [
|
||||
('!', 1, 1, 0),
|
||||
(' !', 1, 2, 1),
|
||||
('\n!', 2, 1, 1),
|
||||
('\n \n\n !', 4, 6, 10),
|
||||
]
|
||||
for data, line, col, idx in test_cases:
|
||||
with self.assertRaises(self.JSONDecodeError) as cm:
|
||||
self.loads(data)
|
||||
err = cm.exception
|
||||
self.assertEqual(err.msg, 'Expecting value')
|
||||
self.assertEqual(err.pos, idx)
|
||||
self.assertEqual(err.lineno, line)
|
||||
self.assertEqual(err.colno, col)
|
||||
self.assertEqual(str(err),
|
||||
'Expecting value: line %s column %d (char %d)' %
|
||||
(line, col, idx))
|
||||
|
||||
class TestPyFail(TestFail, PyTest): pass
|
||||
class TestCFail(TestFail, CTest): pass
|
34
Dependencies/Python/Lib/test/test_json/test_float.py
vendored
Normal file
34
Dependencies/Python/Lib/test/test_json/test_float.py
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
import math
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class TestFloat:
|
||||
def test_floats(self):
|
||||
for num in [1617161771.7650001, math.pi, math.pi**100, math.pi**-100, 3.1]:
|
||||
self.assertEqual(float(self.dumps(num)), num)
|
||||
self.assertEqual(self.loads(self.dumps(num)), num)
|
||||
|
||||
def test_ints(self):
|
||||
for num in [1, 1<<32, 1<<64]:
|
||||
self.assertEqual(self.dumps(num), str(num))
|
||||
self.assertEqual(int(self.dumps(num)), num)
|
||||
|
||||
def test_out_of_range(self):
|
||||
self.assertEqual(self.loads('[23456789012E666]'), [float('inf')])
|
||||
self.assertEqual(self.loads('[-23456789012E666]'), [float('-inf')])
|
||||
|
||||
def test_allow_nan(self):
|
||||
for val in (float('inf'), float('-inf'), float('nan')):
|
||||
out = self.dumps([val])
|
||||
if val == val: # inf
|
||||
self.assertEqual(self.loads(out), [val])
|
||||
else: # nan
|
||||
res = self.loads(out)
|
||||
self.assertEqual(len(res), 1)
|
||||
self.assertNotEqual(res[0], res[0])
|
||||
msg = f'Out of range float values are not JSON compliant: {val}'
|
||||
self.assertRaisesRegex(ValueError, msg, self.dumps, [val], allow_nan=False)
|
||||
|
||||
|
||||
class TestPyFloat(TestFloat, PyTest): pass
|
||||
class TestCFloat(TestFloat, CTest): pass
|
67
Dependencies/Python/Lib/test/test_json/test_indent.py
vendored
Normal file
67
Dependencies/Python/Lib/test/test_json/test_indent.py
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
import textwrap
|
||||
from io import StringIO
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class TestIndent:
|
||||
def test_indent(self):
|
||||
h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth',
|
||||
{'nifty': 87}, {'field': 'yes', 'morefield': False} ]
|
||||
|
||||
expect = textwrap.dedent("""\
|
||||
[
|
||||
\t[
|
||||
\t\t"blorpie"
|
||||
\t],
|
||||
\t[
|
||||
\t\t"whoops"
|
||||
\t],
|
||||
\t[],
|
||||
\t"d-shtaeou",
|
||||
\t"d-nthiouh",
|
||||
\t"i-vhbjkhnth",
|
||||
\t{
|
||||
\t\t"nifty": 87
|
||||
\t},
|
||||
\t{
|
||||
\t\t"field": "yes",
|
||||
\t\t"morefield": false
|
||||
\t}
|
||||
]""")
|
||||
|
||||
d1 = self.dumps(h)
|
||||
d2 = self.dumps(h, indent=2, sort_keys=True, separators=(',', ': '))
|
||||
d3 = self.dumps(h, indent='\t', sort_keys=True, separators=(',', ': '))
|
||||
d4 = self.dumps(h, indent=2, sort_keys=True)
|
||||
d5 = self.dumps(h, indent='\t', sort_keys=True)
|
||||
|
||||
h1 = self.loads(d1)
|
||||
h2 = self.loads(d2)
|
||||
h3 = self.loads(d3)
|
||||
|
||||
self.assertEqual(h1, h)
|
||||
self.assertEqual(h2, h)
|
||||
self.assertEqual(h3, h)
|
||||
self.assertEqual(d2, expect.expandtabs(2))
|
||||
self.assertEqual(d3, expect)
|
||||
self.assertEqual(d4, d2)
|
||||
self.assertEqual(d5, d3)
|
||||
|
||||
def test_indent0(self):
|
||||
h = {3: 1}
|
||||
def check(indent, expected):
|
||||
d1 = self.dumps(h, indent=indent)
|
||||
self.assertEqual(d1, expected)
|
||||
|
||||
sio = StringIO()
|
||||
self.json.dump(h, sio, indent=indent)
|
||||
self.assertEqual(sio.getvalue(), expected)
|
||||
|
||||
# indent=0 should emit newlines
|
||||
check(0, '{\n"3": 1\n}')
|
||||
# indent=None is more compact
|
||||
check(None, '{"3": 1}')
|
||||
|
||||
|
||||
class TestPyIndent(TestIndent, PyTest): pass
|
||||
class TestCIndent(TestIndent, CTest): pass
|
75
Dependencies/Python/Lib/test/test_json/test_pass1.py
vendored
Normal file
75
Dependencies/Python/Lib/test/test_json/test_pass1.py
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
# from https://json.org/JSON_checker/test/pass1.json
|
||||
JSON = r'''
|
||||
[
|
||||
"JSON Test Pattern pass1",
|
||||
{"object with 1 member":["array with 1 element"]},
|
||||
{},
|
||||
[],
|
||||
-42,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
{
|
||||
"integer": 1234567890,
|
||||
"real": -9876.543210,
|
||||
"e": 0.123456789e-12,
|
||||
"E": 1.234567890E+34,
|
||||
"": 23456789012E66,
|
||||
"zero": 0,
|
||||
"one": 1,
|
||||
"space": " ",
|
||||
"quote": "\"",
|
||||
"backslash": "\\",
|
||||
"controls": "\b\f\n\r\t",
|
||||
"slash": "/ & \/",
|
||||
"alpha": "abcdefghijklmnopqrstuvwyz",
|
||||
"ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
|
||||
"digit": "0123456789",
|
||||
"0123456789": "digit",
|
||||
"special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
|
||||
"hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
|
||||
"true": true,
|
||||
"false": false,
|
||||
"null": null,
|
||||
"array":[ ],
|
||||
"object":{ },
|
||||
"address": "50 St. James Street",
|
||||
"url": "http://www.JSON.org/",
|
||||
"comment": "// /* <!-- --",
|
||||
"# -- --> */": " ",
|
||||
" s p a c e d " :[1,2 , 3
|
||||
|
||||
,
|
||||
|
||||
4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
|
||||
"jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
|
||||
"quotes": "" \u0022 %22 0x22 034 "",
|
||||
"\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
|
||||
: "A key can be any string"
|
||||
},
|
||||
0.5 ,98.6
|
||||
,
|
||||
99.44
|
||||
,
|
||||
|
||||
1066,
|
||||
1e1,
|
||||
0.1e1,
|
||||
1e-1,
|
||||
1e00,2e+00,2e-00
|
||||
,"rosebud"]
|
||||
'''
|
||||
|
||||
class TestPass1:
|
||||
def test_parse(self):
|
||||
# test in/out equivalence and parsing
|
||||
res = self.loads(JSON)
|
||||
out = self.dumps(res)
|
||||
self.assertEqual(res, self.loads(out))
|
||||
|
||||
|
||||
class TestPyPass1(TestPass1, PyTest): pass
|
||||
class TestCPass1(TestPass1, CTest): pass
|
18
Dependencies/Python/Lib/test/test_json/test_pass2.py
vendored
Normal file
18
Dependencies/Python/Lib/test/test_json/test_pass2.py
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
# from https://json.org/JSON_checker/test/pass2.json
|
||||
JSON = r'''
|
||||
[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
|
||||
'''
|
||||
|
||||
class TestPass2:
|
||||
def test_parse(self):
|
||||
# test in/out equivalence and parsing
|
||||
res = self.loads(JSON)
|
||||
out = self.dumps(res)
|
||||
self.assertEqual(res, self.loads(out))
|
||||
|
||||
|
||||
class TestPyPass2(TestPass2, PyTest): pass
|
||||
class TestCPass2(TestPass2, CTest): pass
|
24
Dependencies/Python/Lib/test/test_json/test_pass3.py
vendored
Normal file
24
Dependencies/Python/Lib/test/test_json/test_pass3.py
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
# from https://json.org/JSON_checker/test/pass3.json
|
||||
JSON = r'''
|
||||
{
|
||||
"JSON Test Pattern pass3": {
|
||||
"The outermost value": "must be an object or array.",
|
||||
"In this test": "It is an object."
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
class TestPass3:
|
||||
def test_parse(self):
|
||||
# test in/out equivalence and parsing
|
||||
res = self.loads(JSON)
|
||||
out = self.dumps(res)
|
||||
self.assertEqual(res, self.loads(out))
|
||||
|
||||
|
||||
class TestPyPass3(TestPass3, PyTest): pass
|
||||
class TestCPass3(TestPass3, CTest): pass
|
107
Dependencies/Python/Lib/test/test_json/test_recursion.py
vendored
Normal file
107
Dependencies/Python/Lib/test/test_json/test_recursion.py
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
from test import support
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class JSONTestObject:
|
||||
pass
|
||||
|
||||
|
||||
class TestRecursion:
|
||||
def test_listrecursion(self):
|
||||
x = []
|
||||
x.append(x)
|
||||
try:
|
||||
self.dumps(x)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self.fail("didn't raise ValueError on list recursion")
|
||||
x = []
|
||||
y = [x]
|
||||
x.append(y)
|
||||
try:
|
||||
self.dumps(x)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self.fail("didn't raise ValueError on alternating list recursion")
|
||||
y = []
|
||||
x = [y, y]
|
||||
# ensure that the marker is cleared
|
||||
self.dumps(x)
|
||||
|
||||
def test_dictrecursion(self):
|
||||
x = {}
|
||||
x["test"] = x
|
||||
try:
|
||||
self.dumps(x)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self.fail("didn't raise ValueError on dict recursion")
|
||||
x = {}
|
||||
y = {"a": x, "b": x}
|
||||
# ensure that the marker is cleared
|
||||
self.dumps(x)
|
||||
|
||||
def test_defaultrecursion(self):
|
||||
class RecursiveJSONEncoder(self.json.JSONEncoder):
|
||||
recurse = False
|
||||
def default(self, o):
|
||||
if o is JSONTestObject:
|
||||
if self.recurse:
|
||||
return [JSONTestObject]
|
||||
else:
|
||||
return 'JSONTestObject'
|
||||
return self.json.JSONEncoder.default(o)
|
||||
|
||||
enc = RecursiveJSONEncoder()
|
||||
self.assertEqual(enc.encode(JSONTestObject), '"JSONTestObject"')
|
||||
enc.recurse = True
|
||||
try:
|
||||
enc.encode(JSONTestObject)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self.fail("didn't raise ValueError on default recursion")
|
||||
|
||||
|
||||
def test_highly_nested_objects_decoding(self):
|
||||
# test that loading highly-nested objects doesn't segfault when C
|
||||
# accelerations are used. See #12017
|
||||
with self.assertRaises(RecursionError):
|
||||
with support.infinite_recursion():
|
||||
self.loads('{"a":' * 100000 + '1' + '}' * 100000)
|
||||
with self.assertRaises(RecursionError):
|
||||
with support.infinite_recursion():
|
||||
self.loads('{"a":' * 100000 + '[1]' + '}' * 100000)
|
||||
with self.assertRaises(RecursionError):
|
||||
with support.infinite_recursion():
|
||||
self.loads('[' * 100000 + '1' + ']' * 100000)
|
||||
|
||||
def test_highly_nested_objects_encoding(self):
|
||||
# See #12051
|
||||
l, d = [], {}
|
||||
for x in range(100000):
|
||||
l, d = [l], {'k':d}
|
||||
with self.assertRaises(RecursionError):
|
||||
with support.infinite_recursion(5000):
|
||||
self.dumps(l)
|
||||
with self.assertRaises(RecursionError):
|
||||
with support.infinite_recursion(5000):
|
||||
self.dumps(d)
|
||||
|
||||
def test_endless_recursion(self):
|
||||
# See #12051
|
||||
class EndlessJSONEncoder(self.json.JSONEncoder):
|
||||
def default(self, o):
|
||||
"""If check_circular is False, this will keep adding another list."""
|
||||
return [o]
|
||||
|
||||
with self.assertRaises(RecursionError):
|
||||
with support.infinite_recursion(1000):
|
||||
EndlessJSONEncoder(check_circular=False).encode(5j)
|
||||
|
||||
|
||||
class TestPyRecursion(TestRecursion, PyTest): pass
|
||||
class TestCRecursion(TestRecursion, CTest): pass
|
151
Dependencies/Python/Lib/test/test_json/test_scanstring.py
vendored
Normal file
151
Dependencies/Python/Lib/test/test_json/test_scanstring.py
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
import sys
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class TestScanstring:
|
||||
def test_scanstring(self):
|
||||
scanstring = self.json.decoder.scanstring
|
||||
self.assertEqual(
|
||||
scanstring('"z\U0001d120x"', 1, True),
|
||||
('z\U0001d120x', 5))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('"\\u007b"', 1, True),
|
||||
('{', 8))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('"A JSON payload should be an object or array, not a string."', 1, True),
|
||||
('A JSON payload should be an object or array, not a string.', 60))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["Unclosed array"', 2, True),
|
||||
('Unclosed array', 17))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["extra comma",]', 2, True),
|
||||
('extra comma', 14))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["double extra comma",,]', 2, True),
|
||||
('double extra comma', 21))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["Comma after the close"],', 2, True),
|
||||
('Comma after the close', 24))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["Extra close"]]', 2, True),
|
||||
('Extra close', 14))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Extra comma": true,}', 2, True),
|
||||
('Extra comma', 14))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Extra value after close": true} "misplaced quoted value"', 2, True),
|
||||
('Extra value after close', 26))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Illegal expression": 1 + 2}', 2, True),
|
||||
('Illegal expression', 21))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Illegal invocation": alert()}', 2, True),
|
||||
('Illegal invocation', 21))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Numbers cannot have leading zeroes": 013}', 2, True),
|
||||
('Numbers cannot have leading zeroes', 37))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Numbers cannot be hex": 0x14}', 2, True),
|
||||
('Numbers cannot be hex', 24))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', 21, True),
|
||||
('Too deep', 30))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Missing colon" null}', 2, True),
|
||||
('Missing colon', 16))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Double colon":: null}', 2, True),
|
||||
('Double colon', 15))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('{"Comma instead of colon", null}', 2, True),
|
||||
('Comma instead of colon', 25))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["Colon instead of comma": false]', 2, True),
|
||||
('Colon instead of comma', 25))
|
||||
|
||||
self.assertEqual(
|
||||
scanstring('["Bad value", truth]', 2, True),
|
||||
('Bad value', 12))
|
||||
|
||||
def test_surrogates(self):
|
||||
scanstring = self.json.decoder.scanstring
|
||||
def assertScan(given, expect):
|
||||
self.assertEqual(scanstring(given, 1, True),
|
||||
(expect, len(given)))
|
||||
|
||||
assertScan('"z\\ud834\\u0079x"', 'z\ud834yx')
|
||||
assertScan('"z\\ud834\\udd20x"', 'z\U0001d120x')
|
||||
assertScan('"z\\ud834\\ud834\\udd20x"', 'z\ud834\U0001d120x')
|
||||
assertScan('"z\\ud834x"', 'z\ud834x')
|
||||
assertScan('"z\\ud834\udd20x12345"', 'z\ud834\udd20x12345')
|
||||
assertScan('"z\\udd20x"', 'z\udd20x')
|
||||
assertScan('"z\ud834\udd20x"', 'z\ud834\udd20x')
|
||||
assertScan('"z\ud834\\udd20x"', 'z\ud834\udd20x')
|
||||
assertScan('"z\ud834x"', 'z\ud834x')
|
||||
|
||||
def test_bad_escapes(self):
|
||||
scanstring = self.json.decoder.scanstring
|
||||
bad_escapes = [
|
||||
'"\\"',
|
||||
'"\\x"',
|
||||
'"\\u"',
|
||||
'"\\u0"',
|
||||
'"\\u01"',
|
||||
'"\\u012"',
|
||||
'"\\uz012"',
|
||||
'"\\u0z12"',
|
||||
'"\\u01z2"',
|
||||
'"\\u012z"',
|
||||
'"\\u0x12"',
|
||||
'"\\u0X12"',
|
||||
'"\\u{0}"'.format("\uff10" * 4),
|
||||
'"\\u 123"',
|
||||
'"\\u-123"',
|
||||
'"\\u+123"',
|
||||
'"\\u1_23"',
|
||||
'"\\ud834\\"',
|
||||
'"\\ud834\\u"',
|
||||
'"\\ud834\\ud"',
|
||||
'"\\ud834\\udd"',
|
||||
'"\\ud834\\udd2"',
|
||||
'"\\ud834\\uzdd2"',
|
||||
'"\\ud834\\udzd2"',
|
||||
'"\\ud834\\uddz2"',
|
||||
'"\\ud834\\udd2z"',
|
||||
'"\\ud834\\u0x20"',
|
||||
'"\\ud834\\u0X20"',
|
||||
'"\\ud834\\u{0}"'.format("\uff10" * 4),
|
||||
'"\\ud834\\u 123"',
|
||||
'"\\ud834\\u-123"',
|
||||
'"\\ud834\\u+123"',
|
||||
'"\\ud834\\u1_23"',
|
||||
]
|
||||
for s in bad_escapes:
|
||||
with self.assertRaises(self.JSONDecodeError, msg=s):
|
||||
scanstring(s, 1, True)
|
||||
|
||||
def test_overflow(self):
|
||||
with self.assertRaises(OverflowError):
|
||||
self.json.decoder.scanstring(b"xxx", sys.maxsize+1)
|
||||
|
||||
|
||||
class TestPyScanstring(TestScanstring, PyTest): pass
|
||||
class TestCScanstring(TestScanstring, CTest): pass
|
50
Dependencies/Python/Lib/test/test_json/test_separators.py
vendored
Normal file
50
Dependencies/Python/Lib/test/test_json/test_separators.py
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
import textwrap
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class TestSeparators:
|
||||
def test_separators(self):
|
||||
h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth',
|
||||
{'nifty': 87}, {'field': 'yes', 'morefield': False} ]
|
||||
|
||||
expect = textwrap.dedent("""\
|
||||
[
|
||||
[
|
||||
"blorpie"
|
||||
] ,
|
||||
[
|
||||
"whoops"
|
||||
] ,
|
||||
[] ,
|
||||
"d-shtaeou" ,
|
||||
"d-nthiouh" ,
|
||||
"i-vhbjkhnth" ,
|
||||
{
|
||||
"nifty" : 87
|
||||
} ,
|
||||
{
|
||||
"field" : "yes" ,
|
||||
"morefield" : false
|
||||
}
|
||||
]""")
|
||||
|
||||
|
||||
d1 = self.dumps(h)
|
||||
d2 = self.dumps(h, indent=2, sort_keys=True, separators=(' ,', ' : '))
|
||||
|
||||
h1 = self.loads(d1)
|
||||
h2 = self.loads(d2)
|
||||
|
||||
self.assertEqual(h1, h)
|
||||
self.assertEqual(h2, h)
|
||||
self.assertEqual(d2, expect)
|
||||
|
||||
def test_illegal_separators(self):
|
||||
h = {1: 2, 3: 4}
|
||||
self.assertRaises(TypeError, self.dumps, h, separators=(b', ', ': '))
|
||||
self.assertRaises(TypeError, self.dumps, h, separators=(', ', b': '))
|
||||
self.assertRaises(TypeError, self.dumps, h, separators=(b', ', b': '))
|
||||
|
||||
|
||||
class TestPySeparators(TestSeparators, PyTest): pass
|
||||
class TestCSeparators(TestSeparators, CTest): pass
|
82
Dependencies/Python/Lib/test/test_json/test_speedups.py
vendored
Normal file
82
Dependencies/Python/Lib/test/test_json/test_speedups.py
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
from test.test_json import CTest
|
||||
|
||||
|
||||
class BadBool:
|
||||
def __bool__(self):
|
||||
1/0
|
||||
|
||||
|
||||
class TestSpeedups(CTest):
|
||||
def test_scanstring(self):
|
||||
self.assertEqual(self.json.decoder.scanstring.__module__, "_json")
|
||||
self.assertIs(self.json.decoder.scanstring, self.json.decoder.c_scanstring)
|
||||
|
||||
def test_encode_basestring_ascii(self):
|
||||
self.assertEqual(self.json.encoder.encode_basestring_ascii.__module__,
|
||||
"_json")
|
||||
self.assertIs(self.json.encoder.encode_basestring_ascii,
|
||||
self.json.encoder.c_encode_basestring_ascii)
|
||||
|
||||
|
||||
class TestDecode(CTest):
|
||||
def test_make_scanner(self):
|
||||
self.assertRaises(AttributeError, self.json.scanner.c_make_scanner, 1)
|
||||
|
||||
def test_bad_bool_args(self):
|
||||
def test(value):
|
||||
self.json.decoder.JSONDecoder(strict=BadBool()).decode(value)
|
||||
self.assertRaises(ZeroDivisionError, test, '""')
|
||||
self.assertRaises(ZeroDivisionError, test, '{}')
|
||||
|
||||
|
||||
class TestEncode(CTest):
|
||||
def test_make_encoder(self):
|
||||
# bpo-6986: The interpreter shouldn't crash in case c_make_encoder()
|
||||
# receives invalid arguments.
|
||||
self.assertRaises(TypeError, self.json.encoder.c_make_encoder,
|
||||
(True, False),
|
||||
b"\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75",
|
||||
None)
|
||||
|
||||
def test_bad_str_encoder(self):
|
||||
# Issue #31505: There shouldn't be an assertion failure in case
|
||||
# c_make_encoder() receives a bad encoder() argument.
|
||||
def bad_encoder1(*args):
|
||||
return None
|
||||
enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj),
|
||||
bad_encoder1, None, ': ', ', ',
|
||||
False, False, False)
|
||||
with self.assertRaises(TypeError):
|
||||
enc('spam', 4)
|
||||
with self.assertRaises(TypeError):
|
||||
enc({'spam': 42}, 4)
|
||||
|
||||
def bad_encoder2(*args):
|
||||
1/0
|
||||
enc = self.json.encoder.c_make_encoder(None, lambda obj: str(obj),
|
||||
bad_encoder2, None, ': ', ', ',
|
||||
False, False, False)
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
enc('spam', 4)
|
||||
|
||||
def test_bad_markers_argument_to_encoder(self):
|
||||
# https://bugs.python.org/issue45269
|
||||
with self.assertRaisesRegex(
|
||||
TypeError,
|
||||
r'make_encoder\(\) argument 1 must be dict or None, not int',
|
||||
):
|
||||
self.json.encoder.c_make_encoder(1, None, None, None, ': ', ', ',
|
||||
False, False, False)
|
||||
|
||||
def test_bad_bool_args(self):
|
||||
def test(name):
|
||||
self.json.encoder.JSONEncoder(**{name: BadBool()}).encode({'a': 1})
|
||||
self.assertRaises(ZeroDivisionError, test, 'skipkeys')
|
||||
self.assertRaises(ZeroDivisionError, test, 'ensure_ascii')
|
||||
self.assertRaises(ZeroDivisionError, test, 'check_circular')
|
||||
self.assertRaises(ZeroDivisionError, test, 'allow_nan')
|
||||
self.assertRaises(ZeroDivisionError, test, 'sort_keys')
|
||||
|
||||
def test_unsortable_keys(self):
|
||||
with self.assertRaises(TypeError):
|
||||
self.json.encoder.JSONEncoder(sort_keys=True).encode({'a': 1, 1: 'a'})
|
232
Dependencies/Python/Lib/test/test_json/test_tool.py
vendored
Normal file
232
Dependencies/Python/Lib/test/test_json/test_tool.py
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import textwrap
|
||||
import unittest
|
||||
import subprocess
|
||||
|
||||
from test import support
|
||||
from test.support import os_helper
|
||||
from test.support.script_helper import assert_python_ok
|
||||
|
||||
|
||||
@support.requires_subprocess()
|
||||
class TestTool(unittest.TestCase):
|
||||
data = """
|
||||
|
||||
[["blorpie"],[ "whoops" ] , [
|
||||
],\t"d-shtaeou",\r"d-nthiouh",
|
||||
"i-vhbjkhnth", {"nifty":87}, {"morefield" :\tfalse,"field"
|
||||
:"yes"} ]
|
||||
"""
|
||||
|
||||
expect_without_sort_keys = textwrap.dedent("""\
|
||||
[
|
||||
[
|
||||
"blorpie"
|
||||
],
|
||||
[
|
||||
"whoops"
|
||||
],
|
||||
[],
|
||||
"d-shtaeou",
|
||||
"d-nthiouh",
|
||||
"i-vhbjkhnth",
|
||||
{
|
||||
"nifty": 87
|
||||
},
|
||||
{
|
||||
"field": "yes",
|
||||
"morefield": false
|
||||
}
|
||||
]
|
||||
""")
|
||||
|
||||
expect = textwrap.dedent("""\
|
||||
[
|
||||
[
|
||||
"blorpie"
|
||||
],
|
||||
[
|
||||
"whoops"
|
||||
],
|
||||
[],
|
||||
"d-shtaeou",
|
||||
"d-nthiouh",
|
||||
"i-vhbjkhnth",
|
||||
{
|
||||
"nifty": 87
|
||||
},
|
||||
{
|
||||
"morefield": false,
|
||||
"field": "yes"
|
||||
}
|
||||
]
|
||||
""")
|
||||
|
||||
jsonlines_raw = textwrap.dedent("""\
|
||||
{"ingredients":["frog", "water", "chocolate", "glucose"]}
|
||||
{"ingredients":["chocolate","steel bolts"]}
|
||||
""")
|
||||
|
||||
jsonlines_expect = textwrap.dedent("""\
|
||||
{
|
||||
"ingredients": [
|
||||
"frog",
|
||||
"water",
|
||||
"chocolate",
|
||||
"glucose"
|
||||
]
|
||||
}
|
||||
{
|
||||
"ingredients": [
|
||||
"chocolate",
|
||||
"steel bolts"
|
||||
]
|
||||
}
|
||||
""")
|
||||
|
||||
def test_stdin_stdout(self):
|
||||
args = sys.executable, '-m', 'json.tool'
|
||||
process = subprocess.run(args, input=self.data, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, self.expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def _create_infile(self, data=None):
|
||||
infile = os_helper.TESTFN
|
||||
with open(infile, "w", encoding="utf-8") as fp:
|
||||
self.addCleanup(os.remove, infile)
|
||||
fp.write(data or self.data)
|
||||
return infile
|
||||
|
||||
def test_infile_stdout(self):
|
||||
infile = self._create_infile()
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', infile)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out.splitlines(), self.expect.encode().splitlines())
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_non_ascii_infile(self):
|
||||
data = '{"msg": "\u3053\u3093\u306b\u3061\u306f"}'
|
||||
expect = textwrap.dedent('''\
|
||||
{
|
||||
"msg": "\\u3053\\u3093\\u306b\\u3061\\u306f"
|
||||
}
|
||||
''').encode()
|
||||
|
||||
infile = self._create_infile(data)
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', infile)
|
||||
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out.splitlines(), expect.splitlines())
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_infile_outfile(self):
|
||||
infile = self._create_infile()
|
||||
outfile = os_helper.TESTFN + '.out'
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', infile, outfile)
|
||||
self.addCleanup(os.remove, outfile)
|
||||
with open(outfile, "r", encoding="utf-8") as fp:
|
||||
self.assertEqual(fp.read(), self.expect)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out, b'')
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_writing_in_place(self):
|
||||
infile = self._create_infile()
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', infile, infile)
|
||||
with open(infile, "r", encoding="utf-8") as fp:
|
||||
self.assertEqual(fp.read(), self.expect)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out, b'')
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_jsonlines(self):
|
||||
args = sys.executable, '-m', 'json.tool', '--json-lines'
|
||||
process = subprocess.run(args, input=self.jsonlines_raw, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, self.jsonlines_expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_help_flag(self):
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', '-h')
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertTrue(out.startswith(b'usage: '))
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_sort_keys_flag(self):
|
||||
infile = self._create_infile()
|
||||
rc, out, err = assert_python_ok('-m', 'json.tool', '--sort-keys', infile)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertEqual(out.splitlines(),
|
||||
self.expect_without_sort_keys.encode().splitlines())
|
||||
self.assertEqual(err, b'')
|
||||
|
||||
def test_indent(self):
|
||||
input_ = '[1, 2]'
|
||||
expect = textwrap.dedent('''\
|
||||
[
|
||||
1,
|
||||
2
|
||||
]
|
||||
''')
|
||||
args = sys.executable, '-m', 'json.tool', '--indent', '2'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_no_indent(self):
|
||||
input_ = '[1,\n2]'
|
||||
expect = '[1, 2]\n'
|
||||
args = sys.executable, '-m', 'json.tool', '--no-indent'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_tab(self):
|
||||
input_ = '[1, 2]'
|
||||
expect = '[\n\t1,\n\t2\n]\n'
|
||||
args = sys.executable, '-m', 'json.tool', '--tab'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_compact(self):
|
||||
input_ = '[ 1 ,\n 2]'
|
||||
expect = '[1,2]\n'
|
||||
args = sys.executable, '-m', 'json.tool', '--compact'
|
||||
process = subprocess.run(args, input=input_, capture_output=True, text=True, check=True)
|
||||
self.assertEqual(process.stdout, expect)
|
||||
self.assertEqual(process.stderr, '')
|
||||
|
||||
def test_no_ensure_ascii_flag(self):
|
||||
infile = self._create_infile('{"key":"💩"}')
|
||||
outfile = os_helper.TESTFN + '.out'
|
||||
self.addCleanup(os.remove, outfile)
|
||||
assert_python_ok('-m', 'json.tool', '--no-ensure-ascii', infile, outfile)
|
||||
with open(outfile, "rb") as f:
|
||||
lines = f.read().splitlines()
|
||||
# asserting utf-8 encoded output file
|
||||
expected = [b'{', b' "key": "\xf0\x9f\x92\xa9"', b"}"]
|
||||
self.assertEqual(lines, expected)
|
||||
|
||||
def test_ensure_ascii_default(self):
|
||||
infile = self._create_infile('{"key":"💩"}')
|
||||
outfile = os_helper.TESTFN + '.out'
|
||||
self.addCleanup(os.remove, outfile)
|
||||
assert_python_ok('-m', 'json.tool', infile, outfile)
|
||||
with open(outfile, "rb") as f:
|
||||
lines = f.read().splitlines()
|
||||
# asserting an ascii encoded output file
|
||||
expected = [b'{', rb' "key": "\ud83d\udca9"', b"}"]
|
||||
self.assertEqual(lines, expected)
|
||||
|
||||
@unittest.skipIf(sys.platform =="win32", "The test is failed with ValueError on Windows")
|
||||
def test_broken_pipe_error(self):
|
||||
cmd = [sys.executable, '-m', 'json.tool']
|
||||
proc = subprocess.Popen(cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE)
|
||||
# bpo-39828: Closing before json.tool attempts to write into stdout.
|
||||
proc.stdout.close()
|
||||
proc.communicate(b'"{}"')
|
||||
self.assertEqual(proc.returncode, errno.EPIPE)
|
103
Dependencies/Python/Lib/test/test_json/test_unicode.py
vendored
Normal file
103
Dependencies/Python/Lib/test/test_json/test_unicode.py
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
import codecs
|
||||
from collections import OrderedDict
|
||||
from test.test_json import PyTest, CTest
|
||||
|
||||
|
||||
class TestUnicode:
|
||||
# test_encoding1 and test_encoding2 from 2.x are irrelevant (only str
|
||||
# is supported as input, not bytes).
|
||||
|
||||
def test_encoding3(self):
|
||||
u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
|
||||
j = self.dumps(u)
|
||||
self.assertEqual(j, '"\\u03b1\\u03a9"')
|
||||
|
||||
def test_encoding4(self):
|
||||
u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
|
||||
j = self.dumps([u])
|
||||
self.assertEqual(j, '["\\u03b1\\u03a9"]')
|
||||
|
||||
def test_encoding5(self):
|
||||
u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
|
||||
j = self.dumps(u, ensure_ascii=False)
|
||||
self.assertEqual(j, f'"{u}"')
|
||||
|
||||
def test_encoding6(self):
|
||||
u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
|
||||
j = self.dumps([u], ensure_ascii=False)
|
||||
self.assertEqual(j, f'["{u}"]')
|
||||
|
||||
def test_encoding7(self):
|
||||
u = '\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}'
|
||||
j = self.dumps(u + "\n", ensure_ascii=False)
|
||||
self.assertEqual(j, f'"{u}\\n"')
|
||||
|
||||
def test_big_unicode_encode(self):
|
||||
u = '\U0001d120'
|
||||
self.assertEqual(self.dumps(u), '"\\ud834\\udd20"')
|
||||
self.assertEqual(self.dumps(u, ensure_ascii=False), '"\U0001d120"')
|
||||
|
||||
def test_big_unicode_decode(self):
|
||||
u = 'z\U0001d120x'
|
||||
self.assertEqual(self.loads(f'"{u}"'), u)
|
||||
self.assertEqual(self.loads('"z\\ud834\\udd20x"'), u)
|
||||
|
||||
def test_unicode_decode(self):
|
||||
for i in range(0, 0xd7ff):
|
||||
u = chr(i)
|
||||
s = f'"\\u{i:04x}"'
|
||||
self.assertEqual(self.loads(s), u)
|
||||
|
||||
def test_unicode_preservation(self):
|
||||
self.assertEqual(type(self.loads('""')), str)
|
||||
self.assertEqual(type(self.loads('"a"')), str)
|
||||
self.assertEqual(type(self.loads('["a"]')[0]), str)
|
||||
|
||||
def test_bytes_encode(self):
|
||||
self.assertRaises(TypeError, self.dumps, b"hi")
|
||||
self.assertRaises(TypeError, self.dumps, [b"hi"])
|
||||
|
||||
def test_bytes_decode(self):
|
||||
for encoding, bom in [
|
||||
('utf-8', codecs.BOM_UTF8),
|
||||
('utf-16be', codecs.BOM_UTF16_BE),
|
||||
('utf-16le', codecs.BOM_UTF16_LE),
|
||||
('utf-32be', codecs.BOM_UTF32_BE),
|
||||
('utf-32le', codecs.BOM_UTF32_LE),
|
||||
]:
|
||||
data = ["a\xb5\u20ac\U0001d120"]
|
||||
encoded = self.dumps(data).encode(encoding)
|
||||
self.assertEqual(self.loads(bom + encoded), data)
|
||||
self.assertEqual(self.loads(encoded), data)
|
||||
self.assertRaises(UnicodeDecodeError, self.loads, b'["\x80"]')
|
||||
# RFC-7159 and ECMA-404 extend JSON to allow documents that
|
||||
# consist of only a string, which can present a special case
|
||||
# not covered by the encoding detection patterns specified in
|
||||
# RFC-4627 for utf-16-le (XX 00 XX 00).
|
||||
self.assertEqual(self.loads('"\u2600"'.encode('utf-16-le')),
|
||||
'\u2600')
|
||||
# Encoding detection for small (<4) bytes objects
|
||||
# is implemented as a special case. RFC-7159 and ECMA-404
|
||||
# allow single codepoint JSON documents which are only two
|
||||
# bytes in utf-16 encodings w/o BOM.
|
||||
self.assertEqual(self.loads(b'5\x00'), 5)
|
||||
self.assertEqual(self.loads(b'\x007'), 7)
|
||||
self.assertEqual(self.loads(b'57'), 57)
|
||||
|
||||
def test_object_pairs_hook_with_unicode(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)]
|
||||
self.assertEqual(self.loads(s), eval(s))
|
||||
self.assertEqual(self.loads(s, object_pairs_hook = lambda x: x), p)
|
||||
od = self.loads(s, object_pairs_hook = OrderedDict)
|
||||
self.assertEqual(od, OrderedDict(p))
|
||||
self.assertEqual(type(od), OrderedDict)
|
||||
# the object_pairs_hook takes priority over the object_hook
|
||||
self.assertEqual(self.loads(s, object_pairs_hook = OrderedDict,
|
||||
object_hook = lambda x: None),
|
||||
OrderedDict(p))
|
||||
|
||||
|
||||
class TestPyUnicode(TestUnicode, PyTest): pass
|
||||
class TestCUnicode(TestUnicode, CTest): pass
|
Reference in New Issue
Block a user