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

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

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
9E81
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 = 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