Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dd54033

Browse files
authored
Revert "ENH: Switch to a private, simpler AxesStack."
1 parent 4c33d97 commit dd54033

File tree

2 files changed

+47
-67
lines changed

2 files changed

+47
-67
lines changed

lib/matplotlib/figure.py

Lines changed: 42 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
218161
class 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()

lib/matplotlib/projections/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ def process_projection_requirements(figure, *args, **kwargs):
9696
raise TypeError('projection must be a string, None or implement a '
9797
'_as_mpl_axes method. Got %r' % projection)
9898

99-
return projection_class, kwargs, (args, kwargs)
99+
# Make the key without projection kwargs, this is used as a unique
100+
# lookup for axes instances
101+
key = figure._make_key(*args, **kwargs)
102+
103+
return projection_class, kwargs, key
100104

101105

102106
def get_projection_names():

0 commit comments

Comments
 (0)