[Python-checkins] [3.6] bpo-31130: IDLE -- stop leaks in test_configdialog. (GH-3016) (#3018)

Terry Jan Reedy webhook-mailer at python.org
Mon Aug 7 15:20:09 EDT 2017


https://github.com/python/cpython/commit/9d7d928b5853b921ed27f1e535dfe8174169854c
commit: 9d7d928b5853b921ed27f1e535dfe8174169854c
branch: 3.6
author: Terry Jan Reedy <tjreedy at udel.edu>
committer: GitHub <noreply at github.com>
date: 2017-08-07T15:20:03-04:00
summary:

[3.6] bpo-31130: IDLE -- stop leaks in test_configdialog. (GH-3016) (#3018)

Initial patch by Victor Stinner.
(cherry picked from commit 733d0f6)

files:
A Misc/NEWS.d/next/IDLE/2017-08-07-14-02-56.bpo-31130.FbsC7f.rst
M Lib/idlelib/configdialog.py
M Lib/idlelib/idle_test/test_configdialog.py

diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py
index 6d8a03b1c00..e634d5f3599 100644
--- a/Lib/idlelib/configdialog.py
+++ b/Lib/idlelib/configdialog.py
@@ -1856,6 +1856,7 @@ def __init__(self):
 
     def clear(self):
         "Clear lists (for tests)."
+        # Call after all tests in a module to avoid memory leaks.
         self.untraced.clear()
         self.traced.clear()
 
diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py
index caeb2b56787..cd78482150c 100644
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -9,7 +9,7 @@
 import unittest
 from unittest import mock
 from idlelib.idle_test.mock_idle import Func
-from tkinter import Tk, Frame, IntVar, BooleanVar, DISABLED, NORMAL
+from tkinter import Tk, Frame, StringVar, IntVar, BooleanVar, DISABLED, NORMAL
 from idlelib import config
 from idlelib.configdialog import idleConf, changes, tracers
 
@@ -41,6 +41,8 @@ def tearDownModule():
     global root, dialog
     idleConf.userCfg = usercfg
     tracers.detach()
+    tracers.clear()
+    changes.clear()
     del dialog
     root.update_idletasks()
     root.destroy()
@@ -442,16 +444,20 @@ def test_update_help_changes(self):
 
 class VarTraceTest(unittest.TestCase):
 
+    @classmethod
+    def setUpClass(cls):
+        cls.tracers = configdialog.VarTrace()
+        cls.iv = IntVar(root)
+        cls.bv = BooleanVar(root)
+
+    @classmethod
+    def tearDownClass(cls):
+        del cls.tracers, cls.iv, cls.bv
+
     def setUp(self):
-        changes.clear()
-        tracers.clear()
-        self.v1 = IntVar(root)
-        self.v2 = BooleanVar(root)
+        self.tracers.clear()
         self.called = 0
 
-    def tearDown(self):
-        del self.v1, self.v2
-
     def var_changed_increment(self, *params):
         self.called += 13
 
@@ -459,64 +465,68 @@ def var_changed_boolean(self, *params):
         pass
 
     def test_init(self):
-        tracers.__init__()
-        self.assertEqual(tracers.untraced, [])
-        self.assertEqual(tracers.traced, [])
+        tr = self.tracers
+        tr.__init__()
+        self.assertEqual(tr.untraced, [])
+        self.assertEqual(tr.traced, [])
 
     def test_clear(self):
-        tracers.untraced.append(0)
-        tracers.traced.append(1)
-        tracers.clear()
-        self.assertEqual(tracers.untraced, [])
-        self.assertEqual(tracers.traced, [])
+        tr = self.tracers
+        tr.untraced.append(0)
+        tr.traced.append(1)
+        tr.clear()
+        self.assertEqual(tr.untraced, [])
+        self.assertEqual(tr.traced, [])
 
     def test_add(self):
-        tr = tracers
+        tr = self.tracers
         func = Func()
         cb = tr.make_callback = mock.Mock(return_value=func)
 
-        v1 = tr.add(self.v1, self.var_changed_increment)
-        self.assertIsInstance(v1, IntVar)
-        v2 = tr.add(self.v2, self.var_changed_boolean)
-        self.assertIsInstance(v2, BooleanVar)
+        iv = tr.add(self.iv, self.var_changed_increment)
+        self.assertIs(iv, self.iv)
+        bv = tr.add(self.bv, self.var_changed_boolean)
+        self.assertIs(bv, self.bv)
 
-        v3 = IntVar(root)
-        v3 = tr.add(v3, ('main', 'section', 'option'))
+        sv = StringVar(root)
+        sv2 = tr.add(sv, ('main', 'section', 'option'))
+        self.assertIs(sv2, sv)
         cb.assert_called_once()
-        cb.assert_called_with(v3, ('main', 'section', 'option'))
+        cb.assert_called_with(sv, ('main', 'section', 'option'))
 
-        expected = [(v1, self.var_changed_increment),
-                    (v2, self.var_changed_boolean),
-                    (v3, func)]
+        expected = [(iv, self.var_changed_increment),
+                    (bv, self.var_changed_boolean),
+                    (sv, func)]
         self.assertEqual(tr.traced, [])
         self.assertEqual(tr.untraced, expected)
 
         del tr.make_callback
 
     def test_make_callback(self):
-        cb = tracers.make_callback(self.v1, ('main', 'section', 'option'))
+        cb = self.tracers.make_callback(self.iv, ('main', 'section', 'option'))
         self.assertTrue(callable(cb))
-        self.v1.set(42)
+        self.iv.set(42)
         # Not attached, so set didn't invoke the callback.
         self.assertNotIn('section', changes['main'])
         # Invoke callback manually.
         cb()
         self.assertIn('section', changes['main'])
         self.assertEqual(changes['main']['section']['option'], '42')
+        changes.clear()
 
     def test_attach_detach(self):
-        tr = tracers
-        v1 = tr.add(self.v1, self.var_changed_increment)
-        v2 = tr.add(self.v2, self.var_changed_boolean)
-        expected = [(v1, self.var_changed_increment),
-                    (v2, self.var_changed_boolean)]
+        tr = self.tracers
+        iv = tr.add(self.iv, self.var_changed_increment)
+        bv = tr.add(self.bv, self.var_changed_boolean)
+        expected = [(iv, self.var_changed_increment),
+                    (bv, self.var_changed_boolean)]
 
         # Attach callbacks and test call increment.
         tr.attach()
         self.assertEqual(tr.untraced, [])
         self.assertCountEqual(tr.traced, expected)
-        v1.set(1)
-        self.assertEqual(v1.get(), 1)
+        iv.set(1)
+        self.assertEqual(iv.get(), 1)
         self.assertEqual(self.called, 13)
 
         # Check that only one callback is attached to a variable.
@@ -524,7 +534,7 @@ def test_attach_detach(self):
         # would be called twice and the counter would be 2.
         self.called = 0
         tr.attach()
-        v1.set(1)
+        iv.set(1)
         self.assertEqual(self.called, 13)
 
         # Detach callbacks.
@@ -532,7 +542,7 @@ def test_attach_detach(self):
         tr.detach()
         self.assertEqual(tr.traced, [])
         self.assertCountEqual(tr.untraced, expected)
-        v1.set(1)
+        iv.set(1)
         self.assertEqual(self.called, 0)
 
 
diff --git a/Misc/NEWS.d/next/IDLE/2017-08-07-14-02-56.bpo-31130.FbsC7f.rst b/Misc/NEWS.d/next/IDLE/2017-08-07-14-02-56.bpo-31130.FbsC7f.rst
new file mode 100644
index 00000000000..c57728fda22
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2017-08-07-14-02-56.bpo-31130.FbsC7f.rst
@@ -0,0 +1 @@
+IDLE -- stop leaks in test_configdialog. Initial patch by Victor Stinner.



More information about the Python-checkins mailing list