14
14
from io import BytesIO
15
15
16
16
17
- def depth_getter (obj ,
18
- current_depth = 0 ,
19
- depth_stack = None ,
17
+ def depth_getter (obj ,
18
+ current_depth = 0 ,
19
+ depth_stack = None ,
20
20
nest_info = 'top level object' ):
21
21
"""
22
22
Returns a dictionary mapping:
23
-
23
+
24
24
id(obj): (shallowest_depth, obj, nest_info)
25
-
26
- for the given object (and its subordinates).
27
-
28
- This, in conjunction with recursive_pickle, can be used to debug
25
+
26
+ for the given object (and its subordinates).
27
+
28
+ This, in conjunction with recursive_pickle, can be used to debug
29
29
pickling issues, although finding others is sometimes a case of
30
30
trial and error.
31
-
31
+
32
32
"""
33
33
if depth_stack is None :
34
34
depth_stack = {}
35
-
35
+
36
36
if id (obj ) in depth_stack :
37
37
stack = depth_stack [id (obj )]
38
38
if stack [0 ] > current_depth :
39
39
del depth_stack [id (obj )]
40
40
else :
41
41
return depth_stack
42
-
42
+
43
43
depth_stack [id (obj )] = (current_depth , obj , nest_info )
44
-
44
+
45
45
if isinstance (obj , (list , tuple )):
46
46
for i , item in enumerate (obj ):
47
- depth_getter (item , current_depth = current_depth + 1 ,
48
- depth_stack = depth_stack ,
47
+ depth_getter (item , current_depth = current_depth + 1 ,
48
+ depth_stack = depth_stack ,
49
49
nest_info = 'list/tuple item #%s in (%s)' % (i , nest_info ))
50
50
else :
51
51
if isinstance (obj , dict ):
@@ -58,16 +58,16 @@ def depth_getter(obj,
58
58
state = obj .__dict__
59
59
else :
60
60
state = {}
61
-
61
+
62
62
for key , value in state .iteritems ():
63
- depth_getter (value , current_depth = current_depth + 1 ,
64
- depth_stack = depth_stack ,
63
+ depth_getter (value , current_depth = current_depth + 1 ,
64
+ depth_stack = depth_stack ,
65
65
nest_info = 'attribute "%s" in (%s)' % (key , nest_info ))
66
-
66
+
67
67
# for instancemethod picklability (and some other issues), uncommenting
68
68
# the following may be helpful
69
69
# print([(name, dobj.__class__) for name, dobj in state.iteritems()], ': ', nest_info, ';', type(obj))
70
-
70
+
71
71
return depth_stack
72
72
73
73
@@ -76,14 +76,14 @@ def recursive_pickle(top_obj):
76
76
Recursively pickle all of the given objects subordinates, starting with
77
77
the deepest first. **Very** handy for debugging pickling issues, but
78
78
also very slow (as it literally pickles each object in turn).
79
-
79
+
80
80
Handles circular object references gracefully.
81
-
81
+
82
82
"""
83
83
objs = depth_getter (top_obj )
84
84
# sort by depth then by nest_info
85
85
objs = sorted (objs .itervalues (), key = lambda val : (- val [0 ], val [2 ]))
86
-
86
+
87
87
for _ , obj , location in objs :
88
88
# print('trying %s' % location)
89
89
try :
@@ -110,90 +110,90 @@ def test_simple():
110
110
111
111
# recursive_pickle(fig)
112
112
pickle .dump (ax , BytesIO (), pickle .HIGHEST_PROTOCOL )
113
-
113
+
114
114
# ax = plt.subplot(121, projection='hammer')
115
115
# recursive_pickle(ax, 'figure')
116
116
# pickle.dump(ax, BytesIO(), pickle.HIGHEST_PROTOCOL)
117
117
118
118
119
- @image_comparison (baseline_images = ['multi_pickle' ],
120
- extensions = ['png' ])
119
+ @image_comparison (baseline_images = ['multi_pickle' ],
120
+ extensions = ['png' ], remove_text = True )
121
121
def test_complete ():
122
122
fig = plt .figure ('Figure with a label?' , figsize = (10 , 6 ))
123
-
123
+
124
124
plt .suptitle ('Can you fit any more in a figure?' )
125
-
125
+
126
126
# make some arbitrary data
127
127
x , y = np .arange (8 ), np .arange (10 )
128
128
data = u = v = np .linspace (0 , 10 , 80 ).reshape (10 , 8 )
129
129
v = np .sin (v * - 0.6 )
130
-
130
+
131
131
plt .subplot (3 ,3 ,1 )
132
132
plt .plot (range (10 ))
133
-
133
+
134
134
plt .subplot (3 , 3 , 2 )
135
135
plt .contourf (data , hatches = ['//' , 'ooo' ])
136
136
plt .colorbar ()
137
-
137
+
138
138
plt .subplot (3 , 3 , 3 )
139
139
plt .pcolormesh (data )
140
-
141
-
140
+
141
+
142
142
plt .subplot (3 , 3 , 4 )
143
143
plt .imshow (data )
144
-
144
+
145
145
plt .subplot (3 , 3 , 5 )
146
146
plt .pcolor (data )
147
-
147
+
148
148
plt .subplot (3 , 3 , 6 )
149
149
plt .streamplot (x , y , u , v )
150
-
150
+
151
151
plt .subplot (3 , 3 , 7 )
152
152
plt .quiver (x , y , u , v )
153
-
153
+
154
154
plt .subplot (3 , 3 , 8 )
155
155
plt .scatter (x , x ** 2 , label = '$x^2$' )
156
156
plt .legend (loc = 'upper left' )
157
-
157
+
158
158
plt .subplot (3 , 3 , 9 )
159
159
plt .errorbar (x , x * - 0.5 , xerr = 0.2 , yerr = 0.4 )
160
-
160
+
161
161
###### plotting is done, now test its pickle-ability #########
162
-
162
+
163
163
# Uncomment to debug any unpicklable objects. This is slow (~200 seconds).
164
164
# recursive_pickle(fig)
165
-
165
+
166
166
result_fh = BytesIO ()
167
167
pickle .dump (fig , result_fh , pickle .HIGHEST_PROTOCOL )
168
-
168
+
169
169
plt .close ('all' )
170
-
170
+
171
171
# make doubly sure that there are no figures left
172
172
assert_equal (plt ._pylab_helpers .Gcf .figs , {})
173
-
173
+
174
174
# wind back the fh and load in the figure
175
175
result_fh .seek (0 )
176
176
fig = pickle .load (result_fh )
177
-
177
+
178
178
# make sure there is now a figure manager
179
179
assert_not_equal (plt ._pylab_helpers .Gcf .figs , {})
180
-
180
+
181
181
assert_equal (fig .get_label (), 'Figure with a label?' )
182
-
183
-
182
+
183
+
184
184
def test_no_pyplot ():
185
185
# tests pickle-ability of a figure not created with pyplot
186
-
186
+
187
187
import pickle as p
188
188
from matplotlib .backends .backend_pdf import FigureCanvasPdf as fc
189
189
from matplotlib .figure import Figure
190
-
190
+
191
191
fig = Figure ()
192
192
can = fc (fig )
193
193
ax = fig .add_subplot (1 , 1 , 1 )
194
194
ax .plot ([1 , 2 , 3 ], [1 , 2 , 3 ])
195
-
196
- # Uncomment to debug any unpicklable objects. This is slow so is not
195
+
196
+ # Uncomment to debug any unpicklable objects. This is slow so is not
197
197
# uncommented by default.
198
198
# recursive_pickle(fig)
199
199
pickle .dump (fig , BytesIO (), pickle .HIGHEST_PROTOCOL )
0 commit comments