8000 Merge pull request #7330 from QuLogic/fix-svg-close · matplotlib/matplotlib@92da7f6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 92da7f6

Browse files
authored
Merge pull request #7330 from QuLogic/fix-svg-close
[MRG] Fix several SVG closing issues
2 parents 1b666c5 + 1810f1f commit 92da7f6

File tree

3 files changed

+61
-41
lines changed

3 files changed

+61
-41
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,13 @@ def __init__(self, fig, rect,
582582
right=rcParams['ytick.right'] and rcParams['ytick.major.right'],
583583
which='major')
584584

585+
def __getstate__(self):
586+
# The renderer should be re-created by the figure, and then cached at
587+
# that point.
588+
state = super(_AxesBase, self).__getstate__()
589+
state['_cachedRenderer'] = None
590+
return state
591+
585592
def __setstate__(self, state):
586593
self.__dict__ = state
587594
# put the _remove_method back on all artists contained within the axes

lib/matplotlib/backends/backend_svg.py

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,49 +1189,64 @@ class FigureCanvasSVG(FigureCanvasBase):
11891189

11901190
def print_svg(self, filename, *args, **kwargs):
11911191
if is_string_like(filename):
1192-
fh_to_close = svgwriter = io.open(filename, 'w', encoding='utf-8')
1193-
elif is_writable_file_like(filename):
1194-
if not isinstance(filename, io.TextIOBase):
1195-
if six.PY3:
1196-
svgwriter = io.TextIOWrapper(filename, 'utf-8')
1197-
else:
1198-
svgwriter = codecs.getwriter('utf-8')(filename)
1192+
with io.open(filename, 'w', encoding='utf-8') as svgwriter:
1193+
return self._print_svg(filename, svgwriter, **kwargs)
1194+
1195+
if not is_writable_file_like(filename):
1196+
raise ValueError("filename must be a path or a file-like object")
1197+
1198+
svgwriter = filename
1199+
filename = getattr(svgwriter, 'name', '')
1200+
if not isinstance(filename, six.string_types):
1201+
filename = ''
1202+
1203+
if not isinstance(svgwriter, io.TextIOBase):
1204+
if six.PY3:
1205+
svgwriter = io.TextIOWrapper(svgwriter, 'utf-8')
11991206
else:
1200-
svgwriter = filename
1201-
fh_to_close = None
1207+
svgwriter = codecs.getwriter('utf-8')(svgwriter)
1208+
detach = True
12021209
else:
1203-
raise ValueError("filename must be a path or a file-like object")
1204-
return self._print_svg(filename, svgwriter, fh_to_close, **kwargs)
1210+
detach = False
1211+
1212+
result = self._print_svg(filename, svgwriter, **kwargs)
1213+
1214+
# Detach underlying stream from wrapper so that it remains open in the
1215+
# caller.
1216+
if detach:
1217+
if six.PY3:
1218+
svgwriter.detach()
1219+
else:
1220+
svgwriter.reset()
1221+
svgwriter.stream = io.BytesIO()
1222+
1223+
return result
12051224

12061225
def print_svgz(self, filename, *args, **kwargs):
12071226
if is_string_like(filename):
1208-
fh_to_close = gzipwriter = gzip.GzipFile(filename, 'w')
1209-
svgwriter = io.TextIOWrapper(gzipwriter, 'utf-8')
1227+
options = dict(filename=filename)
12101228
elif is_writable_file_like(filename):
1211-
fh_to_close = gzipwriter = gzip.GzipFile(fileobj=filename, mode='w')
1212-
svgwriter = io.TextIOWrapper(gzipwriter, 'utf-8')
1229+
options = dict(fileobj=filename)
12131230
else:
12141231
raise ValueError("filename must be a path or a file-like object")
1215-
return self._print_svg(filename, svgwriter, fh_to_close)
1216-
1217-
def _print_svg(self, filename, svgwriter, fh_to_close=None, **kwargs):
1218-
try:
1219-
image_dpi = kwargs.pop("dpi", 72)
1220-
self.figure.set_dpi(72.0)
1221-
width, height = self.figure.get_size_inches()
1222-
w, h = width*72, height*72
1223-
1224-
_bbox_inches_restore = kwargs.pop("bbox_inches_restore", None)
1225-
renderer = MixedModeRenderer(
1226-
self.figure,
1227-
width, height, image_dpi, RendererSVG(w, h, svgwriter, filename, image_dpi),
1228-
bbox_inches_restore=_bbox_inches_restore)
1229-
1230-
self.figure.draw(renderer)
1231-
renderer.finalize()
1232-
finally:
1233-
if fh_to_close is not None:
1234-
svgwriter.close()
1232+
1233+
with gzip.GzipFile(mode='w', **options) as gzipwriter:
1234+
return self.print_svg(gzipwriter)
1235+
1236+
def _print_svg(self, filename, svgwriter, **kwargs):
1237+
image_dpi = kwargs.pop("dpi", 72)
1238+
self.figure.set_dpi(72.0)
1239+
width, height = self.figure.get_size_inches()
1240+
w, h = width*72, height*72
1241+
1242+
_bbox_inches_restore = 9E88 kwargs.pop("bbox_inches_restore", None)
1243+
renderer = MixedModeRenderer(
1244+
self.figure,
1245+
width, height, image_dpi, RendererSVG(w, h, svgwriter, filename, image_dpi),
1246+
bbox_inches_restore=_bbox_inches_restore)
1247+
1248+
self.figure.draw(renderer)
1249+
renderer.finalize()
12351250

12361251
def get_default_filetype(self):
12371252
return 'svg'

lib/matplotlib/table.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,6 @@ def __init__(self, ax, loc=None, bbox=None, **kwargs):
278278

279279
self.set_clip_on(False)
280280

281-
self._cachedRenderer = None
282-
283281
def add_cell(self, row, col, *args, **kwargs):
284282
""" Add a cell to the table. """
285283
xy = (0, 0)
@@ -310,10 +308,9 @@ def draw(self, renderer):
310308
# Need a renderer to do hit tests on mouseevent; assume the last one
311309
# will do
312310
if renderer is None:
313-
renderer = self._cachedRenderer
311+
renderer = self.figure._cachedRenderer
314312
if renderer is None:
315313
raise RuntimeError('No renderer defined')
316-
self._cachedRenderer = renderer
317314

318315
if not self.get_visible():
319316
return
@@ -350,8 +347,9 @@ def contains(self, mouseevent):
350347

351348
# TODO: Return index of the cell containing the cursor so that the user
352349
# doesn't have to bind to each one individually.
353-
if self._cachedRenderer is not None:
354-
boxes = [self._cells[pos].get_window_extent(self._cachedRenderer)
350+
renderer = self.figure._cachedRenderer
351+
if renderer is not None:
352+
boxes = [self._cells[pos].get_window_extent(renderer)
355353
for pos in six.iterkeys(self._cells)
356354
if pos[0] >= 0 and pos[1] >= 0]
357355
bbox = Bbox.union(boxes)

0 commit comments

Comments
 (0)
0