Skip to content

Commit 9e4861f

Browse files
bpo-22831: Use "with" to avoid possible fd leaks in tests (part 1). (GH-10928)
1 parent b727239 commit 9e4861f

File tree

5 files changed

+254
-298
lines changed

5 files changed

+254
-298
lines changed

Lib/test/test_dbm_dumb.py

Lines changed: 69 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Original by Roger E. Masse
33
"""
44

5+
import contextlib
56
import io
67
import operator
78
import os
@@ -32,12 +33,11 @@ class DumbDBMTestCase(unittest.TestCase):
3233
}
3334

3435
def test_dumbdbm_creation(self):
35-
f = dumbdbm.open(_fname, 'c')
36-
self.assertEqual(list(f.keys()), [])
37-
for key in self._dict:
38-
f[key] = self._dict[key]
39-
self.read_helper(f)
40-
f.close()
36+
with contextlib.closing(dumbdbm.open(_fname, 'c')) as f:
37+
self.assertEqual(list(f.keys()), [])
38+
for key in self._dict:
39+
f[key] = self._dict[key]
40+
self.read_helper(f)
4141

4242
@unittest.skipUnless(hasattr(os, 'umask'), 'test needs os.umask()')
4343
def test_dumbdbm_creation_mode(self):
@@ -69,78 +69,70 @@ def test_close_twice(self):
6969

7070
def test_dumbdbm_modification(self):
7171
self.init_db()
72-
f = dumbdbm.open(_fname, 'w')
73-
self._dict[b'g'] = f[b'g'] = b"indented"
74-
self.read_helper(f)
75-
# setdefault() works as in the dict interface
76-
self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
77-
self.assertEqual(f[b'xxx'], b'foo')
78-
f.close()
72+
with contextlib.closing(dumbdbm.open(_fname, 'w')) as f:
73+
self._dict[b'g'] = f[b'g'] = b"indented"
74+
self.read_helper(f)
75+
# setdefault() works as in the dict interface
76+
self.assertEqual(f.setdefault(b'xxx', b'foo'), b'foo')
77+
self.assertEqual(f[b'xxx'], b'foo')
7978

8079
def test_dumbdbm_read(self):
8180
self.init_db()
82-
f = dumbdbm.open(_fname, 'r')
83-
self.read_helper(f)
84-
with self.assertRaisesRegex(dumbdbm.error,
85-
'The database is opened for reading only'):
86-
f[b'g'] = b'x'
87-
with self.assertRaisesRegex(dumbdbm.error,
88-
'The database is opened for reading only'):
89-
del f[b'a']
90-
# get() works as in the dict interface
91-
self.assertEqual(f.get(b'a'), self._dict[b'a'])
92-
self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
93-
self.assertIsNone(f.get(b'xxx'))
94-
with self.assertRaises(KeyError):
95-
f[b'xxx']
96-
f.close()
81+
with contextlib.closing(dumbdbm.open(_fname, 'r')) as f:
82+
self.read_helper(f)
83+
with self.assertRaisesRegex(dumbdbm.error,
84+
'The database is opened for reading only'):
85+
f[b'g'] = b'x'
86+
with self.assertRaisesRegex(dumbdbm.error,
87+
'The database is opened for reading only'):
88+
del f[b'a']
89+
# get() works as in the dict interface
90+
self.assertEqual(f.get(b'a'), self._dict[b'a'])
91+
self.assertEqual(f.get(b'xxx', b'foo'), b'foo')
92+
self.assertIsNone(f.get(b'xxx'))
93+
with self.assertRaises(KeyError):
94+
f[b'xxx']
9795

9896
def test_dumbdbm_keys(self):
9997
self.init_db()
100-
f = dumbdbm.open(_fname)
101-
keys = self.keys_helper(f)
102-
f.close()
98+
with contextlib.closing(dumbdbm.open(_fname)) as f:
99+
keys = self.keys_helper(f)
103100

104101
def test_write_contains(self):
105-
f = dumbdbm.open(_fname)
106-
f[b'1'] = b'hello'
107-
self.assertIn(b'1', f)
108-
f.close()
102+
with contextlib.closing(dumbdbm.open(_fname)) as f:
103+
f[b'1'] = b'hello'
104+
self.assertIn(b'1', f)
109105

110106
def test_write_write_read(self):
111107
# test for bug #482460
112-
f = dumbdbm.open(_fname)
113-
f[b'1'] = b'hello'
114-
f[b'1'] = b'hello2'
115-
f.close()
116-
f = dumbdbm.open(_fname)
117-
self.assertEqual(f[b'1'], b'hello2')
118-
f.close()
108+
with contextlib.closing(dumbdbm.open(_fname)) as f:
109+
f[b'1'] = b'hello'
110+
f[b'1'] = b'hello2'
111+
with contextlib.closing(dumbdbm.open(_fname)) as f:
112+
self.assertEqual(f[b'1'], b'hello2')
119113

120114
def test_str_read(self):
121115
self.init_db()
122-
f = dumbdbm.open(_fname, 'r')
123-
self.assertEqual(f['\u00fc'], self._dict['\u00fc'.encode('utf-8')])
116+
with contextlib.closing(dumbdbm.open(_fname, 'r')) as f:
117+
self.assertEqual(f['\u00fc'], self._dict['\u00fc'.encode('utf-8')])
124118

125119
def test_str_write_contains(self):
126120
self.init_db()
127-
f = dumbdbm.open(_fname)
128-
f['\u00fc'] = b'!'
129-
f['1'] = 'a'
130-
f.close()
131-
f = dumbdbm.open(_fname, 'r')
132-
self.assertIn('\u00fc', f)
133-
self.assertEqual(f['\u00fc'.encode('utf-8')],
134-
self._dict['\u00fc'.encode('utf-8')])
135-
self.assertEqual(f[b'1'], b'a')
121+
with contextlib.closing(dumbdbm.open(_fname)) as f:
122+
f['\u00fc'] = b'!'
123+
f['1'] = 'a'
124+
with contextlib.closing(dumbdbm.open(_fname, 'r')) as f:
125+
self.assertIn('\u00fc', f)
126+
self.assertEqual(f['\u00fc'.encode('utf-8')],
127+
self._dict['\u00fc'.encode('utf-8')])
128+
self.assertEqual(f[b'1'], b'a')
136129

137130
def test_line_endings(self):
138131
# test for bug #1172763: dumbdbm would die if the line endings
139132
# weren't what was expected.
140-
f = dumbdbm.open(_fname)
141-
f[b'1'] = b'hello'
142-
f[b'2'] = b'hello2'
143-
f.close()
133+
with contextlib.closing(dumbdbm.open(_fname)) as f:
134+
f[b'1'] = b'hello'
135+
f[b'2'] = b'hello2'
144136

145137
# Mangle the file by changing the line separator to Windows or Unix
146138
with io.open(_fname + '.dir', 'rb') as file:
@@ -163,10 +155,9 @@ def read_helper(self, f):
163155
self.assertEqual(self._dict[key], f[key])
164156

165157
def init_db(self):
166-
f = dumbdbm.open(_fname, 'n')
167-
for k in self._dict:
168-
f[k] = self._dict[k]
169-
f.close()
158+
with contextlib.closing(dumbdbm.open(_fname, 'n')) as f:
159+
for k in self._dict:
160+
f[k] = self._dict[k]
170161

171162
def keys_helper(self, f):
172163
keys = sorted(f.keys())
@@ -180,25 +171,23 @@ def test_random(self):
180171
import random
181172
d = {} # mirror the database
182173
for dummy in range(5):
183-
f = dumbdbm.open(_fname)
184-
for dummy in range(100):
185-
k = random.choice('abcdefghijklm')
186-
if random.random() < 0.2:
187-
if k in d:
188-
del d[k]
189-
del f[k]
190-
else:
191-
v = random.choice((b'a', b'b', b'c')) * random.randrange(10000)
192-
d[k] = v
193-
f[k] = v
194-
self.assertEqual(f[k], v)
195-
f.close()
196-
197-
f = dumbdbm.open(_fname)
198-
expected = sorted((k.encode("latin-1"), v) for k, v in d.items())
199-
got = sorted(f.items())
200-
self.assertEqual(expected, got)
201-
f.close()
174+
with contextlib.closing(dumbdbm.open(_fname)) as f:
175+
for dummy in range(100):
176+
k = random.choice('abcdefghijklm')
177+
if random.random() < 0.2:
178+
if k in d:
179+
del d[k]
180+
del f[k]
181+
else:
182+
v = random.choice((b'a', b'b', b'c')) * random.randrange(10000)
183+
d[k] = v
184+
f[k] = v
185+
self.assertEqual(f[k], v)
186+
187+
with contextlib.closing(dumbdbm.open(_fname)) as f:
188+
expected = sorted((k.encode("latin-1"), v) for k, v in d.items())
189+
got = sorted(f.items())
190+
self.assertEqual(expected, got)
202191

203192
def test_context_manager(self):
204193
with dumbdbm.open(_fname, 'c') as db:

Lib/test/test_mmap.py

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,12 @@ def test_tougher_find(self):
268268

269269
def test_find_end(self):
270270
# test the new 'end' parameter works as expected
271-
f = open(TESTFN, 'wb+')
272-
data = b'one two ones'
273-
n = len(data)
274-
f.write(data)
275-
f.flush()
276-
m = mmap.mmap(f.fileno(), n)
277-
f.close()
271+
with open(TESTFN, 'wb+') as f:
272+
data = b'one two ones'
273+
n = len(data)
274+
f.write(data)
275+
f.flush()
276+
m = mmap.mmap(f.fileno(), n)
278277

279278
self.assertEqual(m.find(b'one'), 0)
280279
self.assertEqual(m.find(b'ones'), 8)
@@ -287,13 +286,12 @@ def test_find_end(self):
287286

288287
def test_rfind(self):
289288
# test the new 'end' parameter works as expected
290-
f = open(TESTFN, 'wb+')
291-
data = b'one two ones'
292-
n = len(data)
293-
f.write(data)
294-
f.flush()
295-
m = mmap.mmap(f.fileno(), n)
296-
f.close()
289+
with open(TESTFN, 'wb+') as f:
290+
data = b'one two ones'
291+
n = len(data)
292+
f.write(data)
293+
f.flush()
294+
m = mmap.mmap(f.fileno(), n)
297295

298296
self.assertEqual(m.rfind(b'one'), 8)
299297
self.assertEqual(m.rfind(b'one '), 0)
@@ -306,30 +304,23 @@ def test_rfind(self):
306304

307305
def test_double_close(self):
308306
# make sure a double close doesn't crash on Solaris (Bug# 665913)
309-
f = open(TESTFN, 'wb+')
310-
311-
f.write(2**16 * b'a') # Arbitrary character
312-
f.close()
307+
with open(TESTFN, 'wb+') as f:
308+
f.write(2**16 * b'a') # Arbitrary character
313309

314-
f = open(TESTFN, 'rb')
315-
mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
316-
mf.close()
317-
mf.close()
318-
f.close()
310+
with open(TESTFN, 'rb') as f:
311+
mf = mmap.mmap(f.fileno(), 2**16, access=mmap.ACCESS_READ)
312+
mf.close()
313+
mf.close()
319314

320315
def test_entire_file(self):
321316
# test mapping of entire file by passing 0 for map length
322-
f = open(TESTFN, "wb+")
317+
with open(TESTFN, "wb+") as f:
318+
f.write(2**16 * b'm') # Arbitrary character
323319

324-
f.write(2**16 * b'm') # Arbitrary character
325-
f.close()
326-
327-
f = open(TESTFN, "rb+")
328-
mf = mmap.mmap(f.fileno(), 0)
329-
self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
330-
self.assertEqual(mf.read(2**16), 2**16 * b"m")
331-
mf.close()
332-
f.close()
320+
with open(TESTFN, "rb+") as f, \
321+
mmap.mmap(f.fileno(), 0) as mf:
322+
self.assertEqual(len(mf), 2**16, "Map size should equal file size.")
323+
self.assertEqual(mf.read(2**16), 2**16 * b"m")
333324

334325
def test_length_0_offset(self):
335326
# Issue #10916: test mapping of remainder of file by passing 0 for
@@ -355,16 +346,15 @@ def test_length_0_large_offset(self):
355346

356347
def test_move(self):
357348
# make move works everywhere (64-bit format problem earlier)
358-
f = open(TESTFN, 'wb+')
349+
with open(TESTFN, 'wb+') as f:
359350

360-
f.write(b"ABCDEabcde") # Arbitrary character
361-
f.flush()
351+
f.write(b"ABCDEabcde") # Arbitrary character
352+
f.flush()
362353

363-
mf = mmap.mmap(f.fileno(), 10)
364-
mf.move(5, 0, 5)
365-
self.assertEqual(mf[:], b"ABCDEABCDE", "Map move should have duplicated front 5")
366-
mf.close()
367-
f.close()
354+
mf = mmap.mmap(f.fileno(), 10)
355+
mf.move(5, 0, 5)
356+
self.assertEqual(mf[:], b"ABCDEABCDE", "Map move should have duplicated front 5")
357+
mf.close()
368358

369359
# more excessive test
370360
data = b"0123456789"
@@ -562,10 +552,9 @@ def test_prot_readonly(self):
562552
mapsize = 10
563553
with open(TESTFN, "wb") as fp:
564554
fp.write(b"a"*mapsize)
565-
f = open(TESTFN, "rb")
566-
m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
567-
self.assertRaises(TypeError, m.write, "foo")
568-
f.close()
555+
with open(TESTFN, "rb") as f:
556+
m = mmap.mmap(f.fileno(), mapsize, prot=mmap.PROT_READ)
557+
self.assertRaises(TypeError, m.write, "foo")
569558

570559
def test_error(self):
571560
self.assertIs(mmap.error, OSError)
@@ -574,9 +563,8 @@ def test_io_methods(self):
574563
data = b"0123456789"
575564
with open(TESTFN, "wb") as fp:
576565
fp.write(b"x"*len(data))
577-
f = open(TESTFN, "r+b")
578-
m = mmap.mmap(f.fileno(), len(data))
579-
f.close()
566+
with open(TESTFN, "r+b") as f:
567+
m = mmap.mmap(f.fileno(), len(data))
580568
# Test write_byte()
581569
for i in range(len(data)):
582570
self.assertEqual(m.tell(), i)

0 commit comments

Comments
 (0)