From df4aee248b2dcc04cb412676cb2b3d84e67d0df3 Mon Sep 17 00:00:00 2001 From: xXPBSXx <20614131+xXPBSXx@users.noreply.github.com> Date: Wed, 28 Oct 2026 18:47:03 +0100 Subject: [PATCH] fix(tools): report deeply nested progress snapshots as usage errors Co-Authored-By: Claude Sonnet 5.5 --- tools/progress.py | 2 +- tools/tests/test_progress.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/progress.py b/tools/progress.py index 86acb4bec0..70ae1eebcf 100644 --- a/tools/progress.py +++ b/tools/progress.py @@ -585,7 +585,7 @@ def main(argv=None): for path in args.compare: try: snapshots.append(json.loads(path.read_text(encoding="utf-8-sig"))) - except (OSError, ValueError) as error: + except (OSError, ValueError, RecursionError) as error: parser.error(f"{path}: {error}") for path, snapshot in zip(args.compare, snapshots): try: diff --git a/tools/tests/test_progress.py b/tools/tests/test_progress.py index f83da0a8bf..6479a8e0c0 100644 --- a/tools/tests/test_progress.py +++ b/tools/tests/test_progress.py @@ -59,6 +59,22 @@ class ProgressSnapshotTests(unittest.TestCase): self.assertIn(message, stderr.getvalue()) self.assertNotIn("Traceback", stderr.getvalue()) + def test_deeply_nested_snapshots_are_usage_errors(self): + for position in (0, 1): + with self.subTest(position=position), tempfile.TemporaryDirectory() as directory: + paths = [Path(directory) / "base snapshot.json", Path(directory) / "head snapshot.json"] + for path in paths: + path.write_text(json.dumps(self.snapshot()), encoding="utf-8") + paths[position].write_text("[" * 100000 + "]" * 100000, encoding="utf-8") + stdout, stderr = io.StringIO(), io.StringIO() + with patch("sys.stdout", stdout), patch("sys.stderr", stderr): + with self.assertRaises(SystemExit) as raised: + progress.main(["--compare", *map(str, paths)]) + self.assertEqual(raised.exception.code, 2) + self.assertEqual(stdout.getvalue(), "") + self.assertIn(str(paths[position]), stderr.getvalue()) + self.assertIn("recursion", stderr.getvalue()) + def test_non_object_snapshots_are_usage_errors(self): for snapshot in (None, [], "progress", 7, True): with self.subTest(snapshot=snapshot):