diff --git a/doc/api/api_changes/2017-06-06-no_share_across_figures.rst b/doc/api/api_changes/2017-06-06-no_share_across_figures.rst new file mode 100644 index 000000000000..a1759f2fcf2e --- /dev/null +++ b/doc/api/api_changes/2017-06-06-no_share_across_figures.rst @@ -0,0 +1,8 @@ +Axis-sharing between figures is blocked +``````````````````````````````````````` + +An attempt to share an axis between ``Axes`` objects in different +figures will now raise a ValueError. Previously such sharing +was allowed but could lead to an endless loop when combined +with fixed aspect ratios, as in the case of ``imshow``, for +example. diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 7948c14de8e9..c3ce27fd4188 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -435,9 +435,9 @@ def __init__(self, fig, rect, Optional keyword arguments: - ================ ========================================= + ================ ============================================== Keyword Description - ================ ========================================= + ================ ============================================== *adjustable* [ 'box' | 'datalim' | 'box-forced'] *alpha* float: the alpha transparency (can be None) *anchor* [ 'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', @@ -458,10 +458,10 @@ def __init__(self, fig, rect, toolbar button status *position* [left, bottom, width, height] in class:`~matplotlib.figure.Figure` coords - *sharex* an class:`~matplotlib.axes.Axes` instance - to share the x-axis with - *sharey* an class:`~matplotlib.axes.Axes` instance - to share the y-axis with + *sharex* another class:`~matplotlib.axes.Axes` instance + in *fig* to share the x-axis with + *sharey* another class:`~matplotlib.axes.Axes` instance + in *fig* to share the y-axis with *title* the title string *visible* [ *True* | *False* ] whether the axes is visible @@ -475,7 +475,7 @@ def __init__(self, fig, rect, *yscale* [%(scale)s] *yticklabels* sequence of strings *yticks* sequence of floats - ================ ========================================= + ================ ============================================== """ % {'scale': ' | '.join( [repr(x) for x in mscale.get_scale_names()])} martist.Artist.__init__(self) @@ -494,6 +494,8 @@ def __init__(self, fig, rect, self._sharex = sharex self._sharey = sharey if sharex is not None: + if sharex.get_figure() is not fig: + raise ValueError('Shared Axes must be in the same figure') self._shared_x_axes.join(self, sharex) if sharex._adjustable == 'box': sharex._adjustable = 'datalim' @@ -501,6 +503,8 @@ def __init__(self, fig, rect, # 'shared axes: "adjustable" is being changed to "datalim"') self._adjustable = 'datalim' if sharey is not None: + if sharey.get_figure() is not fig: + raise ValueError('Shared Axes must be in the same figure') self._shared_y_axes.join(self, sharey) if sharey._adjustable == 'box': sharey._adjustable = 'datalim' diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 86b6f2a3ddc2..d344e4c2310a 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4220,6 +4220,15 @@ def test_empty_shared_subplots(): assert y1 >= 6 +def test_shared_fig_fails(): + # Github Issue #2790, sharing works only within a figure + fig, ax = plt.subplots() + with pytest.raises(ValueError): + plt.subplots(sharex=ax) + with pytest.raises(ValueError): + plt.subplots(sharey=ax) + + def test_relim_visible_only(): x1 = (0., 10.) y1 = (0., 10.)