Aurelien Larcher
2021-01-08 b5a8497ec9558d0061024ac4b49f445bbe7d1094
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
From 78062e07bc7c3b47ffdcdec786b259dda376370c Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
 <31488909+miss-islington@users.noreply.github.com>
Date: Wed, 16 Dec 2020 14:01:14 -0800
Subject: [PATCH] bpo-37961: Fix regression in tracemalloc.Traceback.__repr__
 (GH-23805)
 
Regression in 8d59eb1b66c51b2b918da9881c57d07d08df43b7.
(cherry picked from commit 051b9818671625d125dee8198e0d2af5ad4c85b8)
 
Co-authored-by: Daniel Hahler <git@thequod.de>
---
 Lib/test/test_tracemalloc.py                  | 20 +++++++++++++++++++
 Lib/tracemalloc.py                            |  2 +-
 .../2020-12-16-16-16-33.bpo-37961.jrESEq.rst  |  1 +
 3 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 Misc/NEWS.d/next/Library/2020-12-16-16-16-33.bpo-37961.jrESEq.rst
 
diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py
index c5ae4e6d653bf..b10d1798c2977 100644
--- a/Lib/test/test_tracemalloc.py
+++ b/Lib/test/test_tracemalloc.py
@@ -84,6 +84,25 @@ def traceback_filename(filename):
     return traceback_lineno(filename, 0)
 
 
+class TestTraceback(unittest.TestCase):
+    def test_repr(self):
+        def get_repr(*args) -> str:
+            return repr(tracemalloc.Traceback(*args))
+
+        self.assertEqual(get_repr(()), "<Traceback ()>")
+        self.assertEqual(get_repr((), 0), "<Traceback () total_nframe=0>")
+
+        frames = (("f1", 1), ("f2", 2))
+        exp_repr_frames = (
+            "(<Frame filename='f2' lineno=2>,"
+            " <Frame filename='f1' lineno=1>)"
+        )
+        self.assertEqual(get_repr(frames),
+                         f"<Traceback {exp_repr_frames}>")
+        self.assertEqual(get_repr(frames, 2),
+                         f"<Traceback {exp_repr_frames} total_nframe=2>")
+
+
 class TestTracemallocEnabled(unittest.TestCase):
     def setUp(self):
         if tracemalloc.is_tracing():
@@ -1064,6 +1083,7 @@ def test_stop_untrack(self):
 
 def test_main():
     support.run_unittest(
+        TestTraceback,
         TestTracemallocEnabled,
         TestSnapshot,
         TestFilters,
diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py
index 69b4170ec8246..cec99c59700fe 100644
--- a/Lib/tracemalloc.py
+++ b/Lib/tracemalloc.py
@@ -226,7 +226,7 @@ def __str__(self):
         return str(self[0])
 
     def __repr__(self):
-        s = "<Traceback %r" % tuple(self)
+        s = f"<Traceback {tuple(self)}"
         if self._total_nframe is None:
             s += ">"
         else:
diff --git a/Misc/NEWS.d/next/Library/2020-12-16-16-16-33.bpo-37961.jrESEq.rst b/Misc/NEWS.d/next/Library/2020-12-16-16-16-33.bpo-37961.jrESEq.rst
new file mode 100644
index 0000000000000..5b363ad22d6e3
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-12-16-16-16-33.bpo-37961.jrESEq.rst
@@ -0,0 +1 @@
+Fix crash in :func:`tracemalloc.Traceback.__repr__` (regressed in Python 3.9).
\ No newline at end of file