8000 Merge pull request #23515 from tacaswell/auto-backport-of-pr-23462-on… · matplotlib/matplotlib@88e7680 · GitHub
[go: up one dir, main page]

Skip to content

Commit 88e7680

Browse files
authored
Merge pull request #23515 from tacaswell/auto-backport-of-pr-23462-on-v3.5.x
Backport PR #23462: Fix AttributeError for pickle load of Figure class
2 parents fabd295 + bd0df1f commit 88e7680

File tree

2 files changed

+103
-1
lines changed

2 files changed

+103
-1
lines changed

lib/matplotlib/figure.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2919,7 +2919,8 @@ def __setstate__(self, state):
29192919
import matplotlib._pylab_helpers as pylab_helpers
29202920
allnums = plt.get_fignums()
29212921
num = max(allnums) + 1 if allnums else 1
2922-
mgr = plt._backend_mod.new_figure_manager_given_figure(num, self)
2922+
backend = plt._get_backend_mod()
2923+
mgr = backend.new_figure_manager_given_figure(num, self)
29232924
pylab_helpers.Gcf._set_new_active_manager(mgr)
29242925
plt.draw_if_interactive()
29252926

lib/matplotlib/tests/test_pickle.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
from io import BytesIO
2+
import ast
23
import pickle
34

45
import numpy as np
56
import pytest
67

78
from matplotlib import cm
89
from matplotlib.testing.decorators import image_comparison
10+
import matplotlib as mpl
11+
from matplotlib.testing import subprocess_run_helper
12+
from matplotlib.testing.decorators import check_figures_equal
913
from matplotlib.dates import rrulewrapper
1014
import matplotlib.pyplot as plt
1115
import matplotlib.transforms as mtransforms
@@ -110,6 +114,103 @@ def test_complete():
110114
assert fig.get_label() == 'Figure with a label?'
111115

112116

117+
def _pickle_load_subprocess():
118+
import os
119+
import pickle
120+
121+
path = os.environ['PICKLE_FILE_PATH']
122+
123+
with open(path, 'rb') as blob:
124+
fig = pickle.load(blob)
125+
126+
print(str(pickle.dumps(fig)))
127+
128+
129+
def _generate_complete_test_figure(fig_ref):
130+
fig_ref.set_size_inches((10, 6))
131+
plt.figure(fig_ref)
132+
133+
plt.suptitle('Can you fit any more in a figure?')
134+
135+
# make some arbitrary data
136+
x, y = np.arange(8), np.arange(10)
137+
data = u = v = np.linspace(0, 10, 80).reshape(10, 8)
138+
v = np.sin(v * -0.6)
139+
140+
# Ensure lists also pickle correctly.
141+
plt.subplot(3, 3, 1)
142+
plt.plot(list(range(10)))
143+
144+
plt.subplot(3, 3, 2)
145+
plt.contourf(data, hatches=['//', 'ooo'])
146+
plt.colorbar()
147+
148+
plt.subplot(3, 3, 3)
149+
plt.pcolormesh(data)
150+
151+
plt.subplot(3, 3, 4)
152+
plt.imshow(data)
153+
154+
plt.subplot(3, 3, 5)
155+
plt.pcolor(data)
156+
157+
ax = plt.subplot(3, 3, 6)
158+
ax.set_xlim(0, 7)
159+
ax.set_ylim(0, 9)
160+
plt.streamplot(x, y, u, v)
161+
162+
ax = plt.subplot(3, 3, 7)
163+
ax.set_xlim(0, 7)
164+
ax.set_ylim(0, 9)
165+
plt.quiver(x, y, u, v)
166+
167+
plt.subplot(3, 3, 8)
168+
plt.scatter(x, x ** 2, label='$x^2$')
169+
plt.legend(loc='upper left')
170+
171+
plt.subplot(3, 3, 9)
172+
plt.errorbar(x, x * -0.5, xerr=0.2, yerr=0.4)
173+
174+
175+
@mpl.style.context("default")
176+
@check_figures_equal(extensions=['png'])
177+
def test_pickle_load_from_subprocess(fig_test, fig_ref, tmp_path):
178+
_generate_complete_test_figure(fig_ref)
179+
180+
fp = tmp_path / 'sinus.pickle'
181+
assert not fp.exists()
182+
183+
with fp.open('wb') as file:
184+
pickle.dump(fig_ref, file, pickle.HIGHEST_PROTOCOL)
185+
assert fp.exists()
186+
187+
proc = subprocess_run_helper(
188+
_pickle_load_subprocess,
189+
timeout=60,
190+
PICKLE_FILE_PATH=str(fp),
191+
)
192+
193+
loaded_fig = pickle.loads(ast.literal_eval(proc.stdout))
194+
195+
loaded_fig.canvas.draw()
196+
197+
fig_test.set_size_inches(loaded_fig.get_size_inches())
198+
fig_test.figimage(loaded_fig.canvas.renderer.buffer_rgba())
199+
200+
plt.close(loaded_fig)
201+
202+
203+
def test_gcf():
204+
fig = plt.figure("a label")
205+
buf = BytesIO()
206+
pickle.dump(fig, buf, pickle.HIGHEST_PROTOCOL)
207+
plt.close("all")
208+
assert plt._pylab_helpers.Gcf.figs == {} # No figures must be left.
209+
fig = pickle.loads(buf.getbuffer())
210+
assert plt._pylab_helpers.Gcf.figs != {} # A manager is there again.
211+
assert fig.get_label() == "a label"
212+
213+
113214
def test_no_pyplot():
114215
# tests pickle-ability of a figure not created with pyplot
115216
from matplotlib.backends.backend_pdf import FigureCanvasPdf

0 commit comments

Comments
 (0)
0