Skip to content

Commit 9d7d928

Browse files
authored
[3.6] bpo-31130: IDLE -- stop leaks in test_configdialog. (GH-3016) (#3018)
Initial patch by Victor Stinner. (cherry picked from commit 733d0f6)
1 parent b61de2d commit 9d7d928

File tree

3 files changed

+50
-38
lines changed

3 files changed

+50
-38
lines changed

Lib/idlelib/configdialog.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,7 @@ def __init__(self):
18561856

18571857
def clear(self):
18581858
"Clear lists (for tests)."
1859+
# Call after all tests in a module to avoid memory leaks.
18591860
self.untraced.clear()
18601861
self.traced.clear()
18611862

Lib/idlelib/idle_test/test_configdialog.py

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import unittest
1010
from unittest import mock
1111
from idlelib.idle_test.mock_idle import Func
12-
from tkinter import Tk, Frame, IntVar, BooleanVar, DISABLED, NORMAL
12+
from tkinter import Tk, Frame, StringVar, IntVar, BooleanVar, DISABLED, NORMAL
1313
from idlelib import config
1414
from idlelib.configdialog import idleConf, changes, tracers
1515

@@ -41,6 +41,8 @@ def tearDownModule():
4141
global root, dialog
4242
idleConf.userCfg = usercfg
4343
tracers.detach()
44+
tracers.clear()
45+
changes.clear()
4446
del dialog
4547
root.update_idletasks()
4648
root.destroy()
@@ -442,97 +444,105 @@ def test_update_help_changes(self):
442444

443445
class VarTraceTest(unittest.TestCase):
444446

447+
@classmethod
448+
def setUpClass(cls):
449+
cls.tracers = configdialog.VarTrace()
450+
cls.iv = IntVar(root)
451+
cls.bv = BooleanVar(root)
452+
453+
@classmethod
454+
def tearDownClass(cls):
455+
del cls.tracers, cls.iv, cls.bv
456+
445457
def setUp(self):
446-
changes.clear()
447-
tracers.clear()
448-
self.v1 = IntVar(root)
449-
self.v2 = BooleanVar(root)
458+
self.tracers.clear()
450459
self.called = 0
451460

452-
def tearDown(self):
453-
del self.v1, self.v2
454-
455461
def var_changed_increment(self, *params):
456462
self.called += 13
457463

458464
def var_changed_boolean(self, *params):
459465
pass
460466

461467
def test_init(self):
462-
tracers.__init__()
463-
self.assertEqual(tracers.untraced, [])
464-
self.assertEqual(tracers.traced, [])
468+
tr = self.tracers
469+
tr.__init__()
470+
self.assertEqual(tr.untraced, [])
471+
self.assertEqual(tr.traced, [])
465472

466473
def test_clear(self):
467-
tracers.untraced.append(0)
468-
tracers.traced.append(1)
469-
tracers.clear()
470-
self.assertEqual(tracers.untraced, [])
471-
self.assertEqual(tracers.traced, [])
474+
tr = self.tracers
475+
tr.untraced.append(0)
476+
tr.traced.append(1)
477+
tr.clear()
478+
self.assertEqual(tr.untraced, [])
479+
self.assertEqual(tr.traced, [])
472480

473481
def test_add(self):
474-
tr = tracers
482+
tr = self.tracers
475483
func = Func()
476484
cb = tr.make_callback = mock.Mock(return_value=func)
477485

478-
v1 = tr.add(self.v1, self.var_changed_increment)
479-
self.assertIsInstance(v1, IntVar)
480-
v2 = tr.add(self.v2, self.var_changed_boolean)
481-
self.assertIsInstance(v2, BooleanVar)
486+
iv = tr.add(self.iv, self.var_changed_increment)
487+
self.assertIs(iv, self.iv)
488+
bv = tr.add(self.bv, self.var_changed_boolean)
489+
self.assertIs(bv, self.bv)
482490

483-
v3 = IntVar(root)
484-
v3 = tr.add(v3, ('main', 'section', 'option'))
491+
sv = StringVar(root)
492+
sv2 = tr.add(sv, ('main', 'section', 'option'))
493+
self.assertIs(sv2, sv)
485494
cb.assert_called_once()
486-
cb.assert_called_with(v3, ('main', 'section', 'option'))
495+
cb.assert_called_with(sv, ('main', 'section', 'option'))
487496

488-
expected = [(v1, self.var_changed_increment),
489-
(v2, self.var_changed_boolean),
490-
(v3, func)]
497+
expected = [(iv, self.var_changed_increment),
498+
(bv, self.var_changed_boolean),
499+
(sv, func)]
491500
self.assertEqual(tr.traced, [])
492501
self.assertEqual(tr.untraced, expected)
493502

494503
del tr.make_callback
495504

496505
def test_make_callback(self):
497-
cb = tracers.make_callback(self.v1, ('main', 'section', 'option'))
506+
cb = self.tracers.make_callback(self.iv, ('main', 'section', 'option'))
498507
self.assertTrue(callable(cb))
499-
self.v1.set(42)
508+
self.iv.set(42)
500509
# Not attached, so set didn't invoke the callback.
501510
self.assertNotIn('section', changes['main'])
502511
# Invoke callback manually.
503512
cb()
504513
self.assertIn('section', changes['main'])
505514
self.assertEqual(changes['main']['section']['option'], '42')
515+
changes.clear()
506516

507517
def test_attach_detach(self):
508-
tr = tracers
509-
v1 = tr.add(self.v1, self.var_changed_increment)
510-
v2 = tr.add(self.v2, self.var_changed_boolean)
511-
expected = [(v1, self.var_changed_increment),
512-
(v2, self.var_changed_boolean)]
518+
tr = self.tracers
519+
iv = tr.add(self.iv, self.var_changed_increment)
520+
bv = tr.add(self.bv, self.var_changed_boolean)
521+
expected = [(iv, self.var_changed_increment),
522+
(bv, self.var_changed_boolean)]
513523

514524
# Attach callbacks and test call increment.
515525
tr.attach()
516526
self.assertEqual(tr.untraced, [])
517527
self.assertCountEqual(tr.traced, expected)
518-
v1.set(1)
519-
self.assertEqual(v1.get(), 1)
528+
iv.set(1)
529+
self.assertEqual(iv.get(), 1)
520530
self.assertEqual(self.called, 13)
521531

522532
# Check that only one callback is attached to a variable.
523533
# If more than one callback were attached, then var_changed_increment
524534
# would be called twice and the counter would be 2.
525535
self.called = 0
526536
tr.attach()
527-
v1.set(1)
537+
iv.set(1)
528538
self.assertEqual(self.called, 13)
529539

530540
# Detach callbacks.
531541
self.called = 0
532542
tr.detach()
533543
self.assertEqual(tr.traced, [])
534544
self.assertCountEqual(tr.untraced, expected)
535-
v1.set(1)
545+
iv.set(1)
536546
self.assertEqual(self.called, 0)
537547

538548

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
IDLE -- stop leaks in test_configdialog. Initial patch by Victor Stinner.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy