Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update test_json from 3.13.5
  • Loading branch information
ShaharNaveh committed Jul 20, 2025
commit db7406ac8d3bf4e9210ff4dc966336ec464cb3b1
6 changes: 1 addition & 5 deletions Lib/test/test_json/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@


# import json with and without accelerations
# XXX RUSTPYTHON: we don't import _json as fresh since the fresh module isn't placed
# into the sys.modules cache, and therefore the vm can't recognize the _json.Scanner class
cjson = import_helper.import_fresh_module('json') #, fresh=['_json'])
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
Expand Down Expand Up @@ -41,8 +39,6 @@ def test_pyjson(self):
'json.encoder')

class TestCTest(CTest):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_cjson(self):
self.assertEqual(self.json.scanner.make_scanner.__module__, '_json')
self.assertEqual(self.json.decoder.scanstring.__module__, '_json')
Expand Down
51 changes: 40 additions & 11 deletions Lib/test/test_json/test_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,46 @@
from io import StringIO
from collections import OrderedDict
from test.test_json import PyTest, CTest

import unittest
from test import support


class TestDecode:
def test_decimal(self):
rval = self.loads('1.1', parse_float=decimal.Decimal)
self.assertTrue(isinstance(rval, 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.assertTrue(isinstance(rval, 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('[]'), [])
Expand Down Expand Up @@ -89,18 +114,22 @@ def test_string_with_utf8_bom(self):
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'))
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
# TODO: RUSTPYTHON
class TestCDecode(TestDecode, CTest): # pass
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_keys_reuse(self):
return super().test_keys_reuse()
class TestCDecode(TestDecode, CTest): pass
11 changes: 11 additions & 0 deletions Lib/test/test_json/test_default.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import collections
from test.test_json import PyTest, CTest


Expand All @@ -7,6 +8,16 @@ def test_default(self):
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
8 changes: 8 additions & 0 deletions Lib/test/test_json/test_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ def test_dump_skipkeys(self):
self.assertIn('valid_key', o)
self.assertNotIn(b'invalid_key', o)

def test_dump_skipkeys_indent_empty(self):
v = {b'invalid_key': False}
self.assertEqual(self.json.dumps(v, skipkeys=True, indent=4), '{}')

def test_skipkeys_indent(self):
v = {b'invalid_key': False, 'valid_key': True}
self.assertEqual(self.json.dumps(v, skipkeys=True, indent=4), '{\n "valid_key": true\n}')

def test_encode_truefalse(self):
self.assertEqual(self.dumps(
{True: False, False: True}, sort_keys=True),
Expand Down
3 changes: 1 addition & 2 deletions Lib/test/test_json/test_encode_basestring_ascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ def test_encode_basestring_ascii(self):
for input_string, expect in CASES:
result = self.json.encoder.encode_basestring_ascii(input_string)
self.assertEqual(result, expect,
'{0!r} != {1!r} for {2}({3!r})'.format(
result, expect, fname, input_string))
f'{result!r} != {expect!r} for {fname}({input_string!r})')

def test_ordered_dict(self):
# See issue 6105
Expand Down
85 changes: 40 additions & 45 deletions Lib/test/test_json/test_fail.py
Original file line number Diff line number Diff line change
@@ -1,75 +1,74 @@
import unittest
from test.test_json import PyTest, CTest

# 2007-10-05
JSONDOCS = [
# http://json.org/JSON_checker/test/fail1.json
# https://json.org/JSON_checker/test/fail1.json
'"A JSON payload should be an object or array, not a string."',
# http://json.org/JSON_checker/test/fail2.json
# https://json.org/JSON_checker/test/fail2.json
'["Unclosed array"',
# http://json.org/JSON_checker/test/fail3.json
# https://json.org/JSON_checker/test/fail3.json
'{unquoted_key: "keys must be quoted"}',
# http://json.org/JSON_checker/test/fail4.json
# https://json.org/JSON_checker/test/fail4.json
'["extra comma",]',
# http://json.org/JSON_checker/test/fail5.json
# https://json.org/JSON_checker/test/fail5.json
'["double extra comma",,]',
# http://json.org/JSON_checker/test/fail6.json
# https://json.org/JSON_checker/test/fail6.json
'[ , "<-- missing value"]',
# http://json.org/JSON_checker/test/fail7.json
# https://json.org/JSON_checker/test/fail7.json
'["Comma after the close"],',
# http://json.org/JSON_checker/test/fail8.json
# https://json.org/JSON_checker/test/fail8.json
'["Extra close"]]',
# http://json.org/JSON_checker/test/fail9.json
# https://json.org/JSON_checker/test/fail9.json
'{"Extra comma": true,}',
# http://json.org/JSON_checker/test/fail10.json
# https://json.org/JSON_checker/test/fail10.json
'{"Extra value after close": true} "misplaced quoted value"',
# http://json.org/JSON_checker/test/fail11.json
# https://json.org/JSON_checker/test/fail11.json
'{"Illegal expression": 1 + 2}',
# http://json.org/JSON_checker/test/fail12.json
# https://json.org/JSON_checker/test/fail12.json
'{"Illegal invocation": alert()}',
# http://json.org/JSON_checker/test/fail13.json
# https://json.org/JSON_checker/test/fail13.json
'{"Numbers cannot have leading zeroes": 013}',
# http://json.org/JSON_checker/test/fail14.json
# https://json.org/JSON_checker/test/fail14.json
'{"Numbers cannot be hex": 0x14}',
# http://json.org/JSON_checker/test/fail15.json
# https://json.org/JSON_checker/test/fail15.json
'["Illegal backslash escape: \\x15"]',
# http://json.org/JSON_checker/test/fail16.json
# https://json.org/JSON_checker/test/fail16.json
'[\\naked]',
# http://json.org/JSON_checker/test/fail17.json
# https://json.org/JSON_checker/test/fail17.json
'["Illegal backslash escape: \\017"]',
# http://json.org/JSON_checker/test/fail18.json
# https://json.org/JSON_checker/test/fail18.json
'[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]',
# http://json.org/JSON_checker/test/fail19.json
# https://json.org/JSON_checker/test/fail19.json
'{"Missing colon" null}',
# http://json.org/JSON_checker/test/fail20.json
# https://json.org/JSON_checker/test/fail20.json
'{"Double colon":: null}',
# http://json.org/JSON_checker/test/fail21.json
# https://json.org/JSON_checker/test/fail21.json
'{"Comma instead of colon", null}',
# http://json.org/JSON_checker/test/fail22.json
# https://json.org/JSON_checker/test/fail22.json
'["Colon instead of comma": false]',
# http://json.org/JSON_checker/test/fail23.json
# https://json.org/JSON_checker/test/fail23.json
'["Bad value", truth]',
# http://json.org/JSON_checker/test/fail24.json
# https://json.org/JSON_checker/test/fail24.json
"['single quote']",
# http://json.org/JSON_checker/test/fail25.json
# https://json.org/JSON_checker/test/fail25.json
'["\ttab\tcharacter\tin\tstring\t"]',
# http://json.org/JSON_checker/test/fail26.json
# https://json.org/JSON_checker/test/fail26.json
'["tab\\ character\\ in\\ string\\ "]',
# http://json.org/JSON_checker/test/fail27.json
# https://json.org/JSON_checker/test/fail27.json
'["line\nbreak"]',
# http://json.org/JSON_checker/test/fail28.json
# https://json.org/JSON_checker/test/fail28.json
'["line\\\nbreak"]',
# http://json.org/JSON_checker/test/fail29.json
# https://json.org/JSON_checker/test/fail29.json
'[0e]',
# http://json.org/JSON_checker/test/fail30.json
# https://json.org/JSON_checker/test/fail30.json
'[0e+]',
# http://json.org/JSON_checker/test/fail31.json
# https://json.org/JSON_checker/test/fail31.json
'[0e+-1]',
# http://json.org/JSON_checker/test/fail32.json
# https://json.org/JSON_checker/test/fail32.json
'{"Comma instead if closing brace": true,',
# http://json.org/JSON_checker/test/fail33.json
# https://json.org/JSON_checker/test/fail33.json
'["mismatch"}',
# http://code.google.com/p/simplejson/issues/detail?id=3
# https://code.google.com/archive/p/simplejson/issues/3
'["A\u001FZ control characters in string"]',
]

Expand All @@ -90,7 +89,7 @@ def test_failures(self):
except self.JSONDecodeError:
pass
else:
self.fail("Expected failure for fail{0}.json: {1!r}".format(idx, doc))
self.fail(f"Expected failure for fail{idx}.json: {doc!r}")

def test_non_string_keys_dict(self):
data = {'a' : 1, (1, 2) : 2}
Expand Down Expand Up @@ -144,11 +143,11 @@ def test_unexpected_data(self):
('{"spam":[}', 'Expecting value', 9),
('[42:', "Expecting ',' delimiter", 3),
('[42 "spam"', "Expecting ',' delimiter", 4),
('[42,]', 'Expecting value', 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",]', 'Expecting value', 8),
('["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),
Expand All @@ -160,7 +159,9 @@ def test_unexpected_data(self):
('[{"spam":]', 'Expecting value', 9),
('{"spam":42 "ham"', "Expecting ',' delimiter", 11),
('[{"spam":42]', "Expecting ',' delimiter", 11),
('{"spam":42,}', 'Expecting property name enclosed in double quotes', 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:
Expand Down Expand Up @@ -218,9 +219,3 @@ def test_linecol(self):

class TestPyFail(TestFail, PyTest): pass
class TestCFail(TestFail, CTest): pass
# TODO: RUSTPYTHON
class TestCFail(TestFail, CTest):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_failures(self):
super().test_failures()
3 changes: 2 additions & 1 deletion Lib/test/test_json/test_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ def test_allow_nan(self):
res = self.loads(out)
self.assertEqual(len(res), 1)
self.assertNotEqual(res[0], res[0])
self.assertRaises(ValueError, self.dumps, [val], allow_nan=False)
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
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_pass1.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from test.test_json import PyTest, CTest


# from http://json.org/JSON_checker/test/pass1.json
# from https://json.org/JSON_checker/test/pass1.json
JSON = r'''
[
"JSON Test Pattern pass1",
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_pass2.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from test.test_json import PyTest, CTest


# from http://json.org/JSON_checker/test/pass2.json
# from https://json.org/JSON_checker/test/pass2.json
JSON = r'''
[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
'''
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_pass3.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from test.test_json import PyTest, CTest


# from http://json.org/JSON_checker/test/pass3.json
# from https://json.org/JSON_checker/test/pass3.json
JSON = r'''
{
"JSON Test Pattern pass3": {
Expand Down
7 changes: 4 additions & 3 deletions Lib/test/test_json/test_recursion.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,17 @@ def test_highly_nested_objects_decoding(self):
with support.infinite_recursion():
self.loads('[' * 100000 + '1' + ']' * 100000)

@support.requires_resource('cpu')
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():
with support.infinite_recursion(5000):
self.dumps(l)
with self.assertRaises(RecursionError):
with support.infinite_recursion():
with support.infinite_recursion(5000):
self.dumps(d)

def test_endless_recursion(self):
Expand All @@ -99,7 +100,7 @@ def default(self, o):
return [o]

with self.assertRaises(RecursionError):
with support.infinite_recursion():
with support.infinite_recursion(1000):
EndlessJSONEncoder(check_circular=False).encode(5j)


Expand Down
Loading