Skip to content

Commit 39cdd81

Browse files
committed
Added closed_tempfile for testing filename handling
1 parent 3cdf590 commit 39cdd81

File tree

8 files changed

+101
-131
lines changed

8 files changed

+101
-131
lines changed

lib/matplotlib/testing/__init__.py

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import inspect
55
import warnings
66
from contextlib import contextmanager
7+
import shutil
8+
import tempfile
79

810
import matplotlib
911
from matplotlib.cbook import is_string_like, iterable
@@ -164,3 +166,21 @@ def setup():
164166
rcdefaults() # Start with all defaults
165167

166168
set_font_settings_for_testing()
169+
170+
171+
@contextmanager
172+
def closed_tempfile(suffix='', text=None):
173+
"""
174+
Context manager which yields the path to a closed temporary file with the
175+
suffix `suffix`. The file will be deleted on exiting the context. An
176+
additional argument `text` can be provided to have the file contain `text`.
177+
"""
178+
with tempfile.NamedTemporaryFile(
179+
'w+t', suffix=suffix, delete=False
180+
) as test_file:
181+
file_name = test_file.name
182+
if text is not None:
183+
test_file.write(text)
184+
test_file.flush()
185+
yield file_name
186+
shutil.rmtree(file_name, ignore_errors=True)

lib/matplotlib/tests/test_animation.py

+10-43
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import matplotlib as mpl
1313
from matplotlib import pyplot as plt
1414
from matplotlib import animation
15-
from ..testing import xfail, skip
15+
from ..testing import xfail, skip, closed_tempfile
1616
from ..testing.decorators import cleanup
1717

1818

@@ -134,20 +134,9 @@ def animate(i):
134134
line.set_data(x, y)
135135
return line,
136136

137-
# Use NamedTemporaryFile: will be automatically deleted
138-
F = tempfile.NamedTemporaryFile(suffix='.' + extension)
139-
F.close()
140-
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
141-
try:
142-
anim.save(F.name, fps=30, writer=writer, bitrate=500)
143-
except UnicodeDecodeError:
144-
xfail("There can be errors in the numpy import stack, "
145-
"see issues #1891 and #2679")
146-
finally:
147-
try:
148-
os.remove(F.name)
149-
except Exception:
150-
pass
137+
with closed_tempfile(suffix='.' + extension) as fname:
138+
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
139+
anim.save(fname, fps=30, writer=writer, bitrate=500)
151140

152141

153142
@cleanup
@@ -178,20 +167,9 @@ def animate(i):
178167
line.set_data(x, y)
179168
return line,
180169

181-
# Use NamedTemporaryFile: will be automatically deleted
182-
F = tempfile.NamedTemporaryFile(suffix='.' + extension)
183-
F.close()
184-
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
185-
try:
186-
anim.save(FakeFSPathClass(F.name), fps=30, writer=writer, bitrate=500)
187-
except UnicodeDecodeError:
188-
xfail("There can be errors in the numpy import stack, "
189-
"see issues #1891 and #2679")
190-
finally:
191-
try:
192-
os.remove(F.name)
193-
except Exception:
194-
pass
170+
with closed_tempfile(suffix='.' + extension) as fname:
171+
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
172+
anim.save(FakeFSPathClass(fname), fps=30, writer=writer, bitrate=500)
195173

196174

197175
@cleanup
@@ -219,20 +197,9 @@ def animate(i):
219197
line.set_data(x, y)
220198
return line,
221199

222-
# Use NamedTemporaryFile: will be automatically deleted
223-
F = tempfile.NamedTemporaryFile(suffix='.' + extension)
224-
F.close()
225-
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
226-
try:
227-
anim.save(Path(F.name), fps=30, writer=writer, bitrate=500)
228-
except UnicodeDecodeError:
229-
xfail("There can be errors in the numpy import stack, "
230-
"see issues #1891 and #2679")
231-
finally:
232-
try:
233-
os.remove(F.name)
234-
except Exception:
235-
pass
200+
with closed_tempfile(suffix='.' + extension) as fname:
201+
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=5)
202+
anim.save(Path(fname), fps=30, writer=writer, bitrate=500)
236203

237204

238205
@cleanup

lib/matplotlib/tests/test_backend_pdf.py

+14-23
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from matplotlib import pyplot as plt
1515
from matplotlib.testing.decorators import (image_comparison, knownfailureif,
1616
cleanup)
17-
from matplotlib.testing import skip
17+
from matplotlib.testing import skip, closed_tempfile
1818

1919
if 'TRAVIS' not in os.environ:
2020
@image_comparison(baseline_images=['pdf_use14corefonts'],
@@ -57,14 +57,12 @@ def test_multipage_pagecount():
5757
@cleanup
5858
def test_multipage_keep_empty():
5959
from matplotlib.backends.backend_pdf import PdfPages
60-
from tempfile import NamedTemporaryFile
6160
# test empty pdf files
6261
# test that an empty pdf is left behind with keep_empty=True (default)
63-
with NamedTemporaryFile(delete=False) as tmp:
62+
with closed_tempfile(".pdf") as tmp:
6463
with PdfPages(tmp) as pdf:
6564
filename = pdf._file.fh.name
6665
assert os.path.exists(filename)
67-
os.remove(filename)
6866
# test if an empty pdf is deleting itself afterwards with keep_empty=False
6967
with PdfPages(filename, keep_empty=False) as pdf:
7068
pass
@@ -74,19 +72,17 @@ def test_multipage_keep_empty():
7472
ax = fig.add_subplot(111)
7573
ax.plot([1, 2, 3])
7674
# test that a non-empty pdf is left behind with keep_empty=True (default)
77-
with NamedTemporaryFile(delete=False) as tmp:
75+
with closed_tempfile(".pdf") as tmp:
7876
with PdfPages(tmp) as pdf:
7977
filename = pdf._file.fh.name
8078
pdf.savefig()
8179
assert os.path.exists(filename)
82-
os.remove(filename)
8380
# test that a non-empty pdf is left behind with keep_empty=False
84-
with NamedTemporaryFile(delete=False) as tmp:
81+
with closed_tempfile(".pdf") as tmp:
8582
with PdfPages(tmp, keep_empty=False) as pdf:
8683
filename = pdf._file.fh.name
8784
pdf.savefig()
8885
assert os.path.exists(filename)
89-
os.remove(filename)
9086

9187

9288
@cleanup
@@ -137,20 +133,17 @@ def test_grayscale_alpha():
137133

138134
@cleanup
139135
def test_pdfpages_accept_pep_519():
140-
from tempfile import NamedTemporaryFile
141-
142136
class FakeFSPathClass(object):
143137
def __init__(self, path):
144138
self._path = path
145139

146140
def __fspath__(self):
147141
return self._path
148-
tmpfile = NamedTemporaryFile(suffix='.pdf')
149-
tmpfile.close()
150-
with PdfPages(FakeFSPathClass(tmpfile.name)) as pdf:
151-
fig, ax = plt.subplots()
152-
ax.plot([1, 2], [3, 4])
153-
pdf.savefig(fig)
142+
with closed_tempfile(suffix='.pdf') as fname:
143+
with PdfPages(FakeFSPathClass(fname)) as pdf:
144+
fig, ax = plt.subplots()
145+
ax.plot([1, 2], [3, 4])
146+
pdf.savefig(fig)
154147

155148

156149
@cleanup
@@ -159,13 +152,11 @@ def test_savefig_accept_pathlib():
159152
from pathlib import Path
160153
except ImportError:
161154
skip("pathlib not installed")
162-
from tempfile import NamedTemporaryFile
163155

164156
fig, ax = plt.subplots()
165157
ax.plot([1, 2], [3, 4])
166-
tmpfile = NamedTemporaryFile(suffix='.pdf')
167-
tmpfile.close()
168-
with PdfPages(Path(tmpfile.name)) as pdf:
169-
fig, ax = plt.subplots()
170-
ax.plot([1, 2], [3, 4])
171-
pdf.savefig(fig)
158+
with closed_tempfile(suffix='.pdf') as fname:
159+
with PdfPages(Path(fname)) as pdf:
160+
fig, ax = plt.subplots()
161+
ax.plot([1, 2], [3, 4])
162+
pdf.savefig(fig)

lib/matplotlib/tests/test_cbook.py

+7-12
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from nose.tools import (assert_equal, assert_not_equal, raises, assert_true,
1515
assert_raises)
1616
from matplotlib.testing.decorators import cleanup
17-
from matplotlib.testing import skip
17+
from matplotlib.testing import skip, closed_tempfile
1818

1919
import matplotlib.cbook as cbook
2020
import matplotlib.colors as mcolors
@@ -529,19 +529,16 @@ def test_flatiter():
529529

530530
@cleanup
531531
def test_to_filehandle_accept_pep_519():
532-
from tempfile import NamedTemporaryFile
533-
534532
class FakeFSPathClass(object):
535533
def __init__(self, path):
536534
self._path = path
537535

538536
def __fspath__(self):
539537
return self._path
540538

541-
tmpfile = NamedTemporaryFile(delete=False)
542-
tmpfile.close()
543-
pep519_path = FakeFSPathClass(tmpfile.name)
544-
cbook.to_filehandle(pep519_path)
539+
with closed_tempfile() as tmpfile:
540+
pep519_path = FakeFSPathClass(tmpfile)
541+
cbook.to_filehandle(pep519_path)
545542

546543

547544
@cleanup
@@ -550,9 +547,7 @@ def test_to_filehandle_accept_pathlib():
550547
from pathlib import Path
551548
except ImportError:
552549
skip("pathlib not installed")
553-
from tempfile import NamedTemporaryFile
554550

555-
tmpfile = NamedTemporaryFile(delete=False)
556-
tmpfile.close()
557-
path = Path(tmpfile.name)
558-
cbook.to_filehandle(path)
551+
with closed_tempfile() as tmpfile:
552+
path = Path(tmpfile)
553+
cbook.to_filehandle(path)

lib/matplotlib/tests/test_figure.py

+19-32
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from matplotlib import rcParams
1010
from matplotlib.testing.decorators import image_comparison, cleanup
11-
from matplotlib.testing import skip
11+
from matplotlib.testing import skip, closed_tempfile
1212
from matplotlib.axes import Axes
1313
import matplotlib.pyplot as plt
1414
import numpy as np
@@ -209,8 +209,6 @@ def test_figaspect():
209209

210210
@cleanup
211211
def test_savefig_accept_pep_519_png():
212-
from tempfile import NamedTemporaryFile
213-
214212
class FakeFSPathClass(object):
215213
def __init__(self, path):
216214
self._path = path
@@ -221,10 +219,9 @@ def __fspath__(self):
221219
fig, ax = plt.subplots()
222220
ax.plot([1, 2], [3, 4])
223221

224-
tmpfile = NamedTemporaryFile(suffix='.png')
225-
tmpfile.close()
226-
pep519_path = FakeFSPathClass(tmpfile.name)
227-
fig.savefig(pep519_path)
222+
with closed_tempfile(suffix='.png') as fname:
223+
pep519_path = FakeFSPathClass(fname)
224+
fig.savefig(pep519_path)
228225

229226

230227
@cleanup
@@ -233,19 +230,16 @@ def test_savefig_accept_pathlib_png():
233230
from pathlib import Path
234231
except ImportError:
235232
skip("pathlib not installed")
236-
from tempfile import NamedTemporaryFile
237233

238234
fig, ax = plt.subplots()
239235
ax.plot([1, 2], [3, 4])
240-
tmpfile = NamedTemporaryFile(suffix='.png')
241-
tmpfile.close()
242-
path = Path(tmpfile.name)
243-
fig.savefig(path)
236+
with closed_tempfile(suffix='.png') as fname:
237+
path = Path(fname)
238+
fig.savefig(path)
244239

245240

246241
@cleanup
247242
def test_savefig_accept_pep_519_svg():
248-
from tempfile import NamedTemporaryFile
249243

250244
class FakeFSPathClass(object):
251245
def __init__(self, path):
@@ -256,10 +250,9 @@ def __fspath__(self):
256250

257251
fig, ax = plt.subplots()
258252
ax.plot([1, 2], [3, 4])
259-
tmpfile = NamedTemporaryFile(suffix='.svg')
260-
tmpfile.close()
261-
pep519_path = FakeFSPathClass(tmpfile.name)
262-
fig.savefig(pep519_path)
253+
with closed_tempfile(suffix='.svg') as fname:
254+
pep519_path = FakeFSPathClass(fname)
255+
fig.savefig(pep519_path)
263256

264257

265258
@cleanup
@@ -268,19 +261,16 @@ def test_savefig_accept_pathlib_svg():
268261
from pathlib import Path
269262
except ImportError:
270263
skip("pathlib not installed")
271-
from tempfile import NamedTemporaryFile
272264

273265
fig, ax = plt.subplots()
274266
ax.plot([1, 2], [3, 4])
275-
tmpfile = NamedTemporaryFile(suffix='.svg')
276-
tmpfile.close()
277-
path = Path(tmpfile.name)
278-
fig.savefig(path)
267+
with closed_tempfile(suffix='.svg') as fname:
268+
path = Path(fname)
269+
fig.savefig(path)
279270

280271

281272
@cleanup
282273
def test_savefig_accept_pep_519_pdf():
283-
from tempfile import NamedTemporaryFile
284274

285275
class FakeFSPathClass(object):
286276
def __init__(self, path):
@@ -291,10 +281,9 @@ def __fspath__(self):
291281

292282
fig, ax = plt.subplots()
293283
ax.plot([1, 2], [3, 4])
294-
tmpfile = NamedTemporaryFile(suffix='.pdf')
295-
tmpfile.close()
296-
pep519_path = FakeFSPathClass(tmpfile.name)
297-
fig.savefig(pep519_path)
284+
with closed_tempfile(suffix='.pdf') as fname:
285+
pep519_path = FakeFSPathClass(fname)
286+
fig.savefig(pep519_path)
298287

299288

300289
@cleanup
@@ -303,14 +292,12 @@ def test_savefig_accept_pathlib_pdf():
303292
from pathlib import Path
304293
except ImportError:
305294
skip("pathlib not installed")
306-
from tempfile import NamedTemporaryFile
307295

308296
fig, ax = plt.subplots()
309297
ax.plot([1, 2], [3, 4])
310-
tmpfile = NamedTemporaryFile(suffix='.pdf')
311-
tmpfile.close()
312-
path = Path(tmpfile.name)
313-
fig.savefig(path)
298+
with closed_tempfile(suffix='.pdf') as fname:
299+
path = Path(fname)
300+
fig.savefig(path)
314301

315302
if __name__ == "__main__":
316303
import nose

lib/matplotlib/tests/test_font_manager.py

+4-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from matplotlib.font_manager import (
1313
findfont, FontProperties, fontManager, json_dump, json_load, get_font,
1414
is_opentype_cff_font, fontManager as fm)
15+
from matplotlib.testing import closed_tempfile
1516
import os.path
1617

1718

@@ -36,15 +37,9 @@ def test_font_priority():
3637
def test_json_serialization():
3738
# on windows, we can't open a file twice, so save the name and unlink
3839
# manually...
39-
try:
40-
name = None
41-
with tempfile.NamedTemporaryFile(delete=False) as temp:
42-
name = temp.name
43-
json_dump(fontManager, name)
44-
copy = json_load(name)
45-
finally:
46-
if name and os.path.exists(name):
47-
os.remove(name)
40+
with closed_tempfile(".json") as temp:
41+
json_dump(fontManager, temp)
42+
copy = json_load(temp)
4843
with warnings.catch_warnings():
4944
warnings.filterwarnings('ignore', 'findfont: Font family.*not found')
5045
for prop in ({'family': 'STIXGeneral'},

0 commit comments

Comments
 (0)