11from test .test_json import CTest
2+ from test .support import gc_collect
23
34
45class BadBool :
56 def __bool__ (self ):
6- 1 / 0
7+ 1 / 0
78
89
910class TestSpeedups (CTest ):
1011 def test_scanstring (self ):
1112 self .assertEqual (self .json .decoder .scanstring .__module__ , "_json" )
12- self .assertIs (self .json .decoder .scanstring , self .json .decoder .c_scanstring )
13+ self .assertIs (
14+ self .json .decoder .scanstring , self .json .decoder .c_scanstring
15+ )
1316
1417 def test_encode_basestring_ascii (self ):
15- self .assertEqual (self .json .encoder .encode_basestring_ascii .__module__ ,
16- "_json" )
17- self .assertIs (self .json .encoder .encode_basestring_ascii ,
18- self .json .encoder .c_encode_basestring_ascii )
18+ self .assertEqual (
19+ self .json .encoder .encode_basestring_ascii .__module__ , "_json"
20+ )
21+ self .assertIs (
22+ self .json .encoder .encode_basestring_ascii ,
23+ self .json .encoder .c_encode_basestring_ascii ,
24+ )
1925
2026
2127class TestDecode (CTest ):
@@ -25,119 +31,170 @@ def test_make_scanner(self):
2531 def test_bad_bool_args (self ):
2632 def test (value ):
2733 self .json .decoder .JSONDecoder (strict = BadBool ()).decode (value )
34+
2835 self .assertRaises (ZeroDivisionError , test , '""' )
29- self .assertRaises (ZeroDivisionError , test , '{}' )
36+ self .assertRaises (ZeroDivisionError , test , "{}" )
3037
3138
3239class TestEncode (CTest ):
3340 def test_make_encoder (self ):
3441 # bpo-6986: The interpreter shouldn't crash in case c_make_encoder()
3542 # receives invalid arguments.
36- self .assertRaises (TypeError , self .json .encoder .c_make_encoder ,
43+ self .assertRaises (
44+ TypeError ,
45+ self .json .encoder .c_make_encoder ,
3746 (True , False ),
38- b"\xCD \x7D \x3D \x4E \x12 \x4C \xF9 \x79 \xD7 \x52 \xBA \x82 \xF2 \x27 \x4A \x7D \xA0 \xCA \x75 " ,
39- None )
47+ b"\xcd \x7d \x3d \x4e \x12 \x4c \xf9 \x79 \xd7 \x52 \xba \x82 \xf2 \x27 \x4a \x7d \xa0 \xca \x75 " ,
48+ None ,
49+ )
4050
4151 def test_bad_str_encoder (self ):
4252 # Issue #31505: There shouldn't be an assertion failure in case
4353 # c_make_encoder() receives a bad encoder() argument.
4454 def bad_encoder1 (* args ):
4555 return None
46- enc = self .json .encoder .c_make_encoder (None , lambda obj : str (obj ),
47- bad_encoder1 , None , ': ' , ', ' ,
48- False , False , False )
56+
57+ enc = self .json .encoder .c_make_encoder (
58+ None ,
59+ lambda obj : str (obj ),
60+ bad_encoder1 ,
61+ None ,
62+ ": " ,
63+ ", " ,
64+ False ,
65+ False ,
66+ False ,
67+ )
4968 with self .assertRaises (TypeError ):
50- enc (' spam' , 4 )
69+ enc (" spam" , 4 )
5170 with self .assertRaises (TypeError ):
52- enc ({' spam' : 42 }, 4 )
71+ enc ({" spam" : 42 }, 4 )
5372
5473 def bad_encoder2 (* args ):
55- 1 / 0
56- enc = self .json .encoder .c_make_encoder (None , lambda obj : str (obj ),
57- bad_encoder2 , None , ': ' , ', ' ,
58- False , False , False )
74+ 1 / 0
75+
76+ enc = self .json .encoder .c_make_encoder (
77+ None ,
78+ lambda obj : str (obj ),
79+ bad_encoder2 ,
80+ None ,
81+ ": " ,
82+ ", " ,
83+ False ,
84+ False ,
85+ False ,
86+ )
5987 with self .assertRaises (ZeroDivisionError ):
60- enc (' spam' , 4 )
88+ enc (" spam" , 4 )
6189
6290 def test_bad_markers_argument_to_encoder (self ):
6391 # https://bugs.python.org/issue45269
6492 with self .assertRaisesRegex (
6593 TypeError ,
66- r' make_encoder\(\) argument 1 must be dict or None, not int' ,
94+ r" make_encoder\(\) argument 1 must be dict or None, not int" ,
6795 ):
68- self .json .encoder .c_make_encoder (1 , None , None , None , ': ' , ', ' ,
69- False , False , False )
96+ self .json .encoder .c_make_encoder (
97+ 1 , None , None , None , ": " , ", " , False , False , False
98+ )
7099
71100 def test_bad_bool_args (self ):
72101 def test (name ):
73- self .json .encoder .JSONEncoder (** {name : BadBool ()}).encode ({'a' : 1 })
74- self .assertRaises (ZeroDivisionError , test , 'skipkeys' )
75- self .assertRaises (ZeroDivisionError , test , 'ensure_ascii' )
76- self .assertRaises (ZeroDivisionError , test , 'check_circular' )
77- self .assertRaises (ZeroDivisionError , test , 'allow_nan' )
78- self .assertRaises (ZeroDivisionError , test , 'sort_keys' )
102+ self .json .encoder .JSONEncoder (** {name : BadBool ()}).encode ({"a" : 1 })
103+
104+ self .assertRaises (ZeroDivisionError , test , "skipkeys" )
105+ self .assertRaises (ZeroDivisionError , test , "ensure_ascii" )
106+ self .assertRaises (ZeroDivisionError , test , "check_circular" )
107+ self .assertRaises (ZeroDivisionError , test , "allow_nan" )
108+ self .assertRaises (ZeroDivisionError , test , "sort_keys" )
79109
80110 def test_unsortable_keys (self ):
81111 with self .assertRaises (TypeError ):
82- self .json .encoder .JSONEncoder (sort_keys = True ).encode ({'a' : 1 , 1 : 'a' })
112+ self .json .encoder .JSONEncoder (sort_keys = True ).encode (
113+ {"a" : 1 , 1 : "a" }
114+ )
83115
84116 def test_current_indent_level (self ):
85117 enc = self .json .encoder .c_make_encoder (
86118 markers = None ,
87119 default = str ,
88120 encoder = self .json .encoder .c_encode_basestring ,
89- indent = ' \t ' ,
90- key_separator = ': ' ,
91- item_separator = ', ' ,
121+ indent = " \t " ,
122+ key_separator = ": " ,
123+ item_separator = ", " ,
92124 sort_keys = False ,
93125 skipkeys = False ,
94- allow_nan = False )
95- expected = (
96- '[\n '
97- '\t "spam", \n '
98- '\t {\n '
99- '\t \t "ham": "eggs"\n '
100- '\t }\n '
101- ']' )
102- self .assertEqual (enc (['spam' , {'ham' : 'eggs' }], 0 )[0 ], expected )
103- self .assertEqual (enc (['spam' , {'ham' : 'eggs' }], - 3 )[0 ], expected )
126+ allow_nan = False ,
127+ )
128+ expected = '[\n \t "spam", \n \t {\n \t \t "ham": "eggs"\n \t }\n ]'
129+ self .assertEqual (enc (["spam" , {"ham" : "eggs" }], 0 )[0 ], expected )
130+ self .assertEqual (enc (["spam" , {"ham" : "eggs" }], - 3 )[0 ], expected )
104131 expected2 = (
105- ' [\n '
132+ " [\n "
106133 '\t \t \t \t "spam", \n '
107- ' \t \t \t \t {\n '
134+ " \t \t \t \t {\n "
108135 '\t \t \t \t \t "ham": "eggs"\n '
109- '\t \t \t \t }\n '
110- '\t \t \t ]' )
111- self .assertEqual (enc (['spam' , {'ham' : 'eggs' }], 3 )[0 ], expected2 )
112- self .assertRaises (TypeError , enc , ['spam' , {'ham' : 'eggs' }], 3.0 )
113- self .assertRaises (TypeError , enc , ['spam' , {'ham' : 'eggs' }])
114-
115- def test_mutate_items_during_encode (self ):
116- c_make_encoder = getattr (self .json .encoder , 'c_make_encoder' , None )
117- if c_make_encoder is None :
118- self .skipTest ("c_make_encoder not available" )
136+ "\t \t \t \t }\n "
137+ "\t \t \t ]"
138+ )
139+ self .assertEqual (enc (["spam" , {"ham" : "eggs" }], 3 )[0 ], expected2 )
140+ self .assertRaises (TypeError , enc , ["spam" , {"ham" : "eggs" }], 3.0 )
141+ self .assertRaises (TypeError , enc , ["spam" , {"ham" : "eggs" }])
119142
120- cache = []
143+ def test_mutate_dict_items_during_encode (self ):
144+ items = None
121145
122146 class BadDict (dict ):
123147 def items (self ):
124- entries = [( "boom" , object ())]
125- cache . append ( entries )
126- return entries
148+ nonlocal items
149+ items = [( "boom" , object ())]
150+ return items
127151
128152 def encode_str (obj ):
129- if cache :
130- cache .pop ().clear ()
153+ nonlocal items
154+ if items is not None :
155+ items .clear ()
156+ items = None
157+ gc_collect ()
131158 return '"x"'
132159
133- encoder = c_make_encoder (
134- None , lambda o : "null" ,
135- encode_str , None ,
136- ": " , ", " , False ,
137- False , True
160+ encoder = self .json .encoder .c_make_encoder (
161+ None ,
162+ lambda o : "null" ,
163+ encode_str ,
164+ None ,
165+ ": " ,
166+ ", " ,
167+ False ,
168+ False ,
169+ True ,
138170 )
139171
140172 try :
141173 encoder (BadDict (real = 1 ), 0 )
142174 except (ValueError , RuntimeError ):
143175 pass
176+
177+ def test_mutate_list_during_encode (self ):
178+ lst = [object () for _ in range (10 )]
179+
180+ def default (obj ):
181+ lst .clear ()
182+ gc_collect ()
183+ return None
184+
185+ encoder = self .json .encoder .c_make_encoder (
186+ None ,
187+ default ,
188+ self .json .encoder .c_encode_basestring ,
189+ None ,
190+ ": " ,
191+ ", " ,
192+ False ,
193+ False ,
194+ True ,
195+ )
196+
197+ try :
198+ encoder (lst , 0 )
199+ except (ValueError , RuntimeError ):
200+ pass
0 commit comments