@@ -72,7 +72,6 @@ class AxesStack(Stack):
7272
7373 """
7474 def __init__ (self ):
75- cbook .warn_deprecated ("2.1" )
7675 Stack .__init__ (self )
7776 self ._ind = 0
7877
@@ -159,62 +158,6 @@ def __contains__(self, a):
159158 return a in self .as_list ()
160159
161160
162- class _AxesStack (object ):
163- """Lightweight stack that tracks Axes in a Figure.
164- """
165-
166- def __init__ (self ):
167- # We maintain a list of (creation_index, key, axes) tuples.
168- # We do not use an OrderedDict because 1. the keys may not be hashable
169- # and 2. we need to directly find a pair corresponding to an axes (i.e.
170- # we'd really need a two-way dict).
171- self ._items = []
172- self ._created = 0
173-
174- def as_list (self ):
175- """Copy of the list of axes, in the order of insertion.
176- """
177- return [ax for _ , _ , ax in sorted (self ._items )]
178-
179- def get (self , key ):
180- """Find the axes corresponding to a key; defaults to `None`.
181- """
182- return next ((ax for _ , k , ax in self ._items if k == key ), None )
183-
184- def current_key_axes (self ):
185- """Return the topmost `(key, axes)` pair, or `(None, None)` if empty.
186- """
187- _ , key , ax = (self ._items or [(None , None , None )])[- 1 ]
188- return key , ax
189-
190- def add (self , key , ax ):
191- """Append a `(key, axes)` pair, unless the axes are already present.
192- """
193- # Skipping existing Axes is needed to support calling `add_axes` with
194- # an already existing Axes.
195- if not any (a == ax for _ , _ , a in self ._items ):
196- self ._items .append ((self ._created , key , ax ))
197- self ._created += 1
198-
199- def bubble (self , ax ):
200- """Move an axes and its corresponding key to the top.
201- """
202- idx , = (idx for idx , (_ , _ , a ) in enumerate (self ._items ) if a == ax )
203- self ._items .append (self ._items [idx ])
204- del self ._items [idx ]
205-
206- def remove (self , ax ):
207- """Remove an axes and its corresponding key.
208- """
209- idx , = (idx for idx , (_ , _ , a ) in enumerate (self ._items ) if a == ax )
210- del self ._items [idx ]
211-
212- def clear (self ):
213- """Clear the stack.
214- """
215- del self ._items [:]
216-
217-
218161class SubplotParams (object ):
219162 """
220163 A class to hold the parameters for a subplot
@@ -415,7 +358,7 @@ def __init__(self,
415358 self .subplotpars = subplotpars
416359 self .set_tight_layout (tight_layout )
417360
418- self ._axstack = _AxesStack () # track all figure axes and current axes
361+ self ._axstack = AxesStack () # track all figure axes and current axes
419362 self .clf ()
420363 self ._cachedRenderer = None
421364
@@ -467,8 +410,10 @@ def show(self, warn=True):
467410 "matplotlib is currently using a non-GUI backend, "
468411 "so cannot show the figure" )
469412
470- axes = property (lambda self : self ._axstack .as_list (),
471- doc = "Read-only: list of axes in Figure" )
413+ def _get_axes (self ):
414+ return self ._axstack .as_list ()
415+
416+ axes = property (fget = _get_axes , doc = "Read-only: list of axes in Figure" )
472417
473418 def _get_dpi (self ):
474419 return self ._dpi
@@ -890,6 +835,36 @@ def delaxes(self, a):
890835 func (self )
891836 self .stale = True
892837
838+ def _make_key (self , * args , ** kwargs ):
839+ 'make a hashable key out of args and kwargs'
840+
841+ def fixitems (items ):
842+ #items may have arrays and lists in them, so convert them
843+ # to tuples for the key
844+ ret = []
845+ for k , v in items :
846+ # some objects can define __getitem__ without being
847+ # iterable and in those cases the conversion to tuples
848+ # will fail. So instead of using the iterable(v) function
849+ # we simply try and convert to a tuple, and proceed if not.
850+ try :
851+ v = tuple (v )
852+ except Exception :
853+ pass
854+ ret .append ((k , v ))
855+ return tuple (ret )
856+
857+ def fixlist (args ):
858+ ret = []
859+ for a in args :
860+ if iterable (a ):
861+ a = tuple (a )
862+ ret .append (a )
863+ return tuple (ret )
864+
865+ key = fixlist (args ), fixitems (six .iteritems (kwargs ))
866+ return key
867+
893868 def add_axes (self , * args , ** kwargs ):
894869 """
895870 Add an axes at position *rect* [*left*, *bottom*, *width*,
@@ -954,9 +929,9 @@ def add_axes(self, *args, **kwargs):
954929
955930 # shortcut the projection "key" modifications later on, if an axes
956931 # with the exact args/kwargs exists, return it immediately.
957- key = ( args , kwargs )
932+ key = self . _make_key ( * args , ** kwargs )
958933 ax = self ._axstack .get (key )
959- if ax :
934+ if ax is not None :
960935 self .sca (ax )
961936 return ax
962937
@@ -976,7 +951,7 @@ def add_axes(self, *args, **kwargs):
976951 # check that an axes of this type doesn't already exist, if it
977952 # does, set it as active and return it
978953 ax = self ._axstack .get (key )
979- if isinstance (ax , projection_class ):
954+ if ax is not None and isinstance (ax , projection_class ):
980955 self .sca (ax )
981956 return ax
982957
@@ -1062,14 +1037,15 @@ def add_subplot(self, *args, **kwargs):
10621037 raise ValueError (msg )
10631038 # make a key for the subplot (which includes the axes object id
10641039 # in the hash)
1065- key = ( args , kwargs )
1040+ key = self . _make_key ( * args , ** kwargs )
10661041 else :
10671042 projection_class , kwargs , key = process_projection_requirements (
10681043 self , * args , ** kwargs )
10691044
10701045 # try to find the axes with this key in the stack
10711046 ax = self ._axstack .get (key )
1072- if ax :
1047+
1048+ if ax is not None :
10731049 if isinstance (ax , projection_class ):
10741050 # the axes already existed, so set it as active & return
10751051 self .sca (ax )
@@ -1638,7 +1614,7 @@ def _gci(self):
16381614 do not use elsewhere.
16391615 """
16401616 # Look first for an image in the current Axes:
1641- ckey , cax = self ._axstack .current_key_axes ()
1617+ cax = self ._axstack .current_key_axes ()[ 1 ]
16421618 if cax is None :
16431619 return None
16441620 im = cax ._gci ()
0 commit comments