GH-141686: Break cycles created by JSONEncoder.iterencode (GH-141687) · python/cpython@4cfa695

GitHub

@@ -264,17 +264,6 @@ def floatstr(o, allow_nan=self.allow_nan,

264264265265def_make_iterencode(markers, _default, _encoder, _indent, _floatstr,

266266_key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,

267-## HACK: hand-optimized bytecode; turn globals into locals

268-ValueError=ValueError,

269-dict=dict,

270-float=float,

271-id=id,

272-int=int,

273-isinstance=isinstance,

274-list=list,

275-str=str,

276-tuple=tuple,

277-_intstr=int.__repr__,

278267 ):

279268280269def_iterencode_list(lst, _current_indent_level):

@@ -311,7 +300,7 @@ def _iterencode_list(lst, _current_indent_level):

311300# Subclasses of int/float may override __repr__, but we still

312301# want to encode them as integers/floats in JSON. One example

313302# within the standard library is IntEnum.

314-yieldbuf+_intstr(value)

303+yieldbuf+int.__repr__(value)

315304elifisinstance(value, float):

316305# see comment above for int

317306yieldbuf+_floatstr(value)

@@ -374,7 +363,7 @@ def _iterencode_dict(dct, _current_indent_level):

374363key='null'

375364elifisinstance(key, int):

376365# see comment for int/float in _make_iterencode

377-key=_intstr(key)

366+key=int.__repr__(key)

378367elif_skipkeys:

379368continue

380369else:

@@ -399,7 +388,7 @@ def _iterencode_dict(dct, _current_indent_level):

399388yield'false'

400389elifisinstance(value, int):

401390# see comment for int/float in _make_iterencode

402-yield_intstr(value)

391+yieldint.__repr__(value)

403392elifisinstance(value, float):

404393# see comment for int/float in _make_iterencode

405394yield_floatstr(value)

@@ -434,7 +423,7 @@ def _iterencode(o, _current_indent_level):

434423yield'false'

435424elifisinstance(o, int):

436425# see comment for int/float in _make_iterencode

437-yield_intstr(o)

426+yieldint.__repr__(o)

438427elifisinstance(o, float):

439428# see comment for int/float in _make_iterencode

440429yield_floatstr(o)

@@ -458,4 +447,13 @@ def _iterencode(o, _current_indent_level):

458447raise

459448ifmarkersisnotNone:

460449delmarkers[markerid]

461-return_iterencode

450+451+def_iterencode_once(o, _current_indent_level):

452+nonlocal_iterencode, _iterencode_dict, _iterencode_list

453+try:

454+yieldfrom_iterencode(o, _current_indent_level)

455+finally:

456+# Break reference cycles due to mutually recursive closures:

457+del_iterencode, _iterencode_dict, _iterencode_list

458+459+return_iterencode_once