diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index ee02fbd16af0c4e..b3674eec97dd5ca 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -598,6 +598,23 @@ def test_snapshot_group_by_traceback(self): self.assertRaises(ValueError, snapshot.statistics, 'traceback', cumulative=True) + def test_compare_to_does_not_mutate_group(self): + # gh-158232: _compare_grouped_stats() used to pop from old_group, + # silently draining the caller's dict. + tb_a = traceback(('f.py', 1)) + tb_b = traceback(('f.py', 2)) + tb_c = traceback(('f.py', 3)) + + old = {tb_a: tracemalloc.Statistic(tb_a, 100, 2), + tb_b: tracemalloc.Statistic(tb_b, 50, 1)} + new = {tb_a: tracemalloc.Statistic(tb_a, 200, 3), + tb_c: tracemalloc.Statistic(tb_c, 10, 1)} + old_copy = dict(old) + + tracemalloc._compare_grouped_stats(old, new) + + self.assertEqual(old, old_copy) + def test_snapshot_group_by_cumulative(self): snapshot, snapshot2 = create_snapshots() tb_0 = traceback_filename('') diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py index cec99c59700fe05..426981ebe97b4de 100644 --- a/Lib/tracemalloc.py +++ b/Lib/tracemalloc.py @@ -119,6 +119,7 @@ def _sort_key(self): def _compare_grouped_stats(old_group, new_group): statistics = [] + old_group = dict(old_group) for traceback, stat in new_group.items(): previous = old_group.pop(traceback, None) if previous is not None: @@ -478,7 +479,7 @@ def _group_by(self, key_type, cumulative): if key_type not in ('traceback', 'filename', 'lineno'): raise ValueError("unknown key_type: %r" % (key_type,)) if cumulative and key_type not in ('lineno', 'filename'): - raise ValueError("cumulative mode cannot by used " + raise ValueError("cumulative mode cannot be used " "with key type %r" % key_type) stats = {}