diff --git a/lib/matplotlib/axes/_subplots.py b/lib/matplotlib/axes/_subplots.py index d2f7e4a4174e..4ff7b44dcd12 100644 --- a/lib/matplotlib/axes/_subplots.py +++ b/lib/matplotlib/axes/_subplots.py @@ -187,6 +187,18 @@ def _make_twin_axes(self, *kl, **kwargs): return ax2 +# this here to support cartopy which was using a private part of the +# API to register their Axes subclasses. + +# In 3.1 this should be changed to a dict subclass that warns on use +# In 3.3 to a dict subclass that raises a useful exception on use +# In 3.4 should be removed + +# The slow timeline is to give cartopy enough time to get several +# release out before we break them. +_subplot_classes = {} + + @functools.lru_cache(None) def subplot_class_factory(axes_class=None): """ @@ -198,9 +210,16 @@ def subplot_class_factory(axes_class=None): """ if axes_class is None: axes_class = Axes - return type("%sSubplot" % axes_class.__name__, - (SubplotBase, axes_class), - {'_axes_class': axes_class}) + try: + # Avoid creating two different instances of GeoAxesSubplot... + # Only a temporary backcompat fix. This should be removed in + # 3.4 + return next(cls for cls in SubplotBase.__subclasses__() + if cls.__bases__ == (SubplotBase, axes_class)) + except StopIteration: + return type("%sSubplot" % axes_class.__name__, + (SubplotBase, axes_class), + {'_axes_class': axes_class}) # This is provided for backward compatibility diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 6c1f7a2c4019..6afed91f34ff 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5789,3 +5789,21 @@ def test_spines_properbbox_after_zoom(): None, False, False) bb2 = ax.spines['bottom'].get_window_extent(fig.canvas.get_renderer()) np.testing.assert_allclose(bb.get_points(), bb2.get_points(), rtol=1e-6) + + +def test_cartopy_backcompat(): + import matplotlib + import matplotlib.axes + import matplotlib.axes._subplots + + class Dummy(matplotlib.axes.Axes): + ... + + class DummySubplot(matplotlib.axes.SubplotBase, Dummy): + _axes_class = Dummy + + matplotlib.axes._subplots._subplot_classes[Dummy] = DummySubplot + + FactoryDummySubplot = matplotlib.axes.subplot_class_factory(Dummy) + + assert DummySubplot is FactoryDummySubplot