diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 3c578d431adc..dfae60d872d8 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -750,8 +750,8 @@ def reset_ticks(self): # build a few default ticks; grow as necessary later; only # define 1 so properties set on ticks will be copied as they # grow - cbook.popall(self.majorTicks) - cbook.popall(self.minorTicks) + del self.majorTicks[:] + del self.minorTicks[:] self.majorTicks.extend([self._get_tick(major=True)]) self.minorTicks.extend([self._get_tick(major=False)]) diff --git a/lib/matplotlib/cbook.py b/lib/matplotlib/cbook.py index b907ec01efbb..077337f6d34c 100644 --- a/lib/matplotlib/cbook.py +++ b/lib/matplotlib/cbook.py @@ -1392,12 +1392,6 @@ def remove(self, o): self.push(thiso) -def popall(seq): - 'empty a list' - for i in xrange(len(seq)): - seq.pop() - - def finddir(o, match, case=False): """ return all attributes of *o* which match string in match. if case diff --git a/lib/matplotlib/markers.py b/lib/matplotlib/markers.py index 8eef2ae20ebd..3a5494c0ed58 100644 --- a/lib/matplotlib/markers.py +++ b/lib/matplotlib/markers.py @@ -93,6 +93,8 @@ (TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN, CARETLEFT, CARETRIGHT, CARETUP, CARETDOWN) = list(xrange(8)) +_empty_path = Path(np.empty((0, 2))) + class MarkerStyle(object): @@ -182,7 +184,7 @@ def __setstate__(self, statedict): self._recache() def _recache(self): - self._path = Path(np.empty((0, 2))) + self._path = _empty_path self._transform = IdentityTransform() self._alt_path = None self._alt_transform = None diff --git a/lib/matplotlib/tests/test_pickle.py b/lib/matplotlib/tests/test_pickle.py index 3419b82c2822..da2e7f699e90 100644 --- a/lib/matplotlib/tests/test_pickle.py +++ b/lib/matplotlib/tests/test_pickle.py @@ -278,7 +278,8 @@ def test_transform(): # Check parent -> child links of TransformWrapper. assert_equal(obj.wrapper._child, obj.composite) # Check child -> parent links of TransformWrapper. - assert_equal(list(obj.wrapper._parents.values()), [obj.composite2]) + assert_equal( + [v() for v in obj.wrapper._parents.values()], [obj.composite2]) # Check input and output dimensions are set as expected. assert_equal(obj.wrapper.input_dims, obj.composite.input_dims) assert_equal(obj.wrapper.output_dims, obj.composite.output_dims) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index a7accb320621..7dd04c1e26f4 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -40,7 +40,7 @@ update_path_extents) from numpy.linalg import inv -from weakref import WeakValueDictionary +import weakref import warnings try: set @@ -92,10 +92,7 @@ def __init__(self, shorthand_name=None): other than to improve the readability of ``str(transform)`` when DEBUG=True. """ - # Parents are stored in a WeakValueDictionary, so that if the - # parents are deleted, references from the children won't keep - # them alive. - self._parents = WeakValueDictionary() + self._parents = {} # TransformNodes start out as invalid until their values are # computed for the first time. @@ -109,14 +106,17 @@ def __str__(self): def __getstate__(self): d = self.__dict__.copy() - # turn the weakkey dictionary into a normal dictionary - d['_parents'] = dict(six.iteritems(self._parents)) + # turn the dictionary with weak values into a normal dictionary + d['_parents'] = dict((k, v()) for (k, v) in + six.iteritems(self._parents)) return d def __setstate__(self, data_dict): self.__dict__ = data_dict - # turn the normal dictionary back into a WeakValueDictionary - self._parents = WeakValueDictionary(self._parents) + # turn the normal dictionary back into a dictionary with weak + # values + self._parents = dict((k, weakref.ref(v)) for (k, v) in + six.iteritems(self._parents) if v is not None) def __copy__(self, *args): raise NotImplementedError( @@ -156,8 +156,11 @@ def _invalidate_internal(self, value, invalidating_node): self._invalid = value for parent in list(six.itervalues(self._parents)): - parent._invalidate_internal(value=value, - invalidating_node=self) + # Dereference the weak reference + parent = parent() + if parent is not None: + parent._invalidate_internal( + value=value, invalidating_node=self) def set_children(self, *children): """ @@ -166,8 +169,11 @@ def set_children(self, *children): Should be called from the constructor of any transforms that depend on other transforms. """ + # Parents are stored as weak references, so that if the + # parents are destroyed, references from the children won't + # keep them alive. for child in children: - child._parents[id(self)] = self + child._parents[id(self)] = weakref.ref(self) if DEBUG: _set_children = set_children @@ -1560,8 +1566,9 @@ def __getstate__(self): 'child': self._child, 'input_dims': self.input_dims, 'output_dims': self.output_dims, - # turn the weakkey dictionary into a normal dictionary - 'parents': dict(six.iteritems(self._parents)) + # turn the weak-values dictionary into a normal dictionary + 'parents': dict((k, v()) for (k, v) in + six.iteritems(self._parents)) } def __setstate__(self, state): @@ -1570,8 +1577,10 @@ def __setstate__(self, state): # The child may not be unpickled yet, so restore its information. self.input_dims = state['input_dims'] self.output_dims = state['output_dims'] - # turn the normal dictionary back into a WeakValueDictionary - self._parents = WeakValueDictionary(state['parents']) + # turn the normal dictionary back into a dictionary with weak + # values + self._parents = dict((k, weakref.ref(v)) for (k, v) in + six.iteritems(state['parents']) if v is not None) def __repr__(self): return "TransformWrapper(%r)" % self._child