diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py index 89bd3550f3a6..6ca9521cf971 100644 --- a/lib/matplotlib/offsetbox.py +++ b/lib/matplotlib/offsetbox.py @@ -46,16 +46,13 @@ def bbox_artist(*args, **kwargs): mbbox_artist(*args, **kwargs) -def _get_packed_offsets(wd_list, total, sep, mode="fixed"): +def _get_packed_offsets(widths, total, sep, mode="fixed"): r""" - Pack boxes specified by their ``(width, xdescent)`` pair. + Pack boxes specified by their *widths*. For simplicity of the description, the terminology used here assumes a horizontal layout, but the function works equally for a vertical layout. - *xdescent* is analogous to the usual descent, but along the x-direction; it - is currently ignored. - There are three packing *mode*\s: - 'fixed': The elements are packed tight to the left with a spacing of @@ -79,8 +76,8 @@ def _get_packed_offsets(wd_list, total, sep, mode="fixed"): Parameters ---------- - wd_list : list of (float, float) - (width, xdescent) of boxes to be packed. + widths : list of float + Widths of boxes to be packed. total : float or None Intended total length. *None* if not used. sep : float @@ -95,11 +92,10 @@ def _get_packed_offsets(wd_list, total, sep, mode="fixed"): offsets : array of float The left offsets of the boxes. """ - w_list, d_list = zip(*wd_list) # d_list is currently not used. _api.check_in_list(["fixed", "expand", "equal"], mode=mode) if mode == "fixed": - offsets_ = np.cumsum([0] + [w + sep for w in w_list]) + offsets_ = np.cumsum([0] + [w + sep for w in widths]) offsets = offsets_[:-1] if total is None: total = offsets_[-1] - sep @@ -110,24 +106,24 @@ def _get_packed_offsets(wd_list, total, sep, mode="fixed"): # is None and used in conjugation with tight layout. if total is None: total = 1 - if len(w_list) > 1: - sep = (total - sum(w_list)) / (len(w_list) - 1) + if len(widths) > 1: + sep = (total - sum(widths)) / (len(widths) - 1) else: sep = 0 - offsets_ = np.cumsum([0] + [w + sep for w in w_list]) + offsets_ = np.cumsum([0] + [w + sep for w in widths]) offsets = offsets_[:-1] return total, offsets elif mode == "equal": - maxh = max(w_list) + maxh = max(widths) if total is None: if sep is None: raise ValueError("total and sep cannot both be None when " "using layout mode 'equal'") - total = (maxh + sep) * len(w_list) + total = (maxh + sep) * len(widths) else: - sep = total / len(w_list) - maxh - offsets = (maxh + sep) * np.arange(len(w_list)) + sep = total / len(widths) - maxh + offsets = (maxh + sep) * np.arange(len(widths)) return total, offsets @@ -445,7 +441,7 @@ def get_extent_offsets(self, renderer): self.width, self.align) - pack_list = [(h, yd) for w, h, xd, yd in whd_list] + pack_list = [h for w, h, xd, yd in whd_list] height, yoffsets_ = _get_packed_offsets(pack_list, self.height, sep, self.mode) @@ -483,8 +479,7 @@ def get_extent_offsets(self, renderer): self.height, self.align) - pack_list = [(w, xd) for w, h, xd, yd in whd_list] - + pack_list = [w for w, h, xd, yd in whd_list] width, xoffsets_ = _get_packed_offsets(pack_list, self.width, sep, self.mode) diff --git a/lib/matplotlib/tests/test_offsetbox.py b/lib/matplotlib/tests/test_offsetbox.py index dc71e14cdb08..02756ff5598b 100644 --- a/lib/matplotlib/tests/test_offsetbox.py +++ b/lib/matplotlib/tests/test_offsetbox.py @@ -122,71 +122,69 @@ def test_expand_with_tight_layout(): fig.tight_layout() # where the crash used to happen -@pytest.mark.parametrize('wd_list', - ([(150, 1)], [(150, 1)]*3, [(0.1, 1)], [(0.1, 1)]*2)) +@pytest.mark.parametrize('widths', + ([150], [150, 150, 150], [0.1], [0.1, 0.1])) @pytest.mark.parametrize('total', (250, 100, 0, -1, None)) @pytest.mark.parametrize('sep', (250, 1, 0, -1)) @pytest.mark.parametrize('mode', ("expand", "fixed", "equal")) -def test_get_packed_offsets(wd_list, total, sep, mode): +def test_get_packed_offsets(widths, total, sep, mode): # Check a (rather arbitrary) set of parameters due to successive similar # issue tickets (at least #10476 and #10784) related to corner cases # triggered inside this function when calling higher-level functions # (e.g. `Axes.legend`). # These are just some additional smoke tests. The output is untested. - _get_packed_offsets(wd_list, total, sep, mode=mode) + _get_packed_offsets(widths, total, sep, mode=mode) _Params = namedtuple('_params', 'wd_list, total, sep, expected') -@pytest.mark.parametrize('wd_list, total, sep, expected', [ +@pytest.mark.parametrize('widths, total, sep, expected', [ _Params( # total=None - [(3, 0), (1, 0), (2, 0)], total=None, sep=1, expected=(8, [0, 4, 6])), + [3, 1, 2], total=None, sep=1, expected=(8, [0, 4, 6])), _Params( # total larger than required - [(3, 0), (1, 0), (2, 0)], total=10, sep=1, expected=(10, [0, 4, 6])), + [3, 1, 2], total=10, sep=1, expected=(10, [0, 4, 6])), _Params( # total smaller than required - [(3, 0), (1, 0), (2, 0)], total=5, sep=1, expected=(5, [0, 4, 6])), + [3, 1, 2], total=5, sep=1, expected=(5, [0, 4, 6])), ]) -def test_get_packed_offsets_fixed(wd_list, total, sep, expected): - result = _get_packed_offsets(wd_list, total, sep, mode='fixed') +def test_get_packed_offsets_fixed(widths, total, sep, expected): + result = _get_packed_offsets(widths, total, sep, mode='fixed') assert result[0] == expected[0] assert_allclose(result[1], expected[1]) -@pytest.mark.parametrize('wd_list, total, sep, expected', [ +@pytest.mark.parametrize('widths, total, sep, expected', [ _Params( # total=None (implicit 1) - [(.1, 0)] * 3, total=None, sep=None, expected=(1, [0, .45, .9])), + [.1, .1, .1], total=None, sep=None, expected=(1, [0, .45, .9])), _Params( # total larger than sum of widths - [(3, 0), (1, 0), (2, 0)], total=10, sep=1, expected=(10, [0, 5, 8])), + [3, 1, 2], total=10, sep=1, expected=(10, [0, 5, 8])), _Params( # total smaller sum of widths: overlapping boxes - [(3, 0), (1, 0), (2, 0)], total=5, sep=1, expected=(5, [0, 2.5, 3])), + [3, 1, 2], total=5, sep=1, expected=(5, [0, 2.5, 3])), ]) -def test_get_packed_offsets_expand(wd_list, total, sep, expected): - result = _get_packed_offsets(wd_list, total, sep, mode='expand') +def test_get_packed_offsets_expand(widths, total, sep, expected): + result = _get_packed_offsets(widths, total, sep, mode='expand') assert result[0] == expected[0] assert_allclose(result[1], expected[1]) -@pytest.mark.parametrize('wd_list, total, sep, expected', [ +@pytest.mark.parametrize('widths, total, sep, expected', [ _Params( # total larger than required - [(3, 0), (2, 0), (1, 0)], total=6, sep=None, expected=(6, [0, 2, 4])), + [3, 2, 1], total=6, sep=None, expected=(6, [0, 2, 4])), _Params( # total smaller sum of widths: overlapping boxes - [(3, 0), (2, 0), (1, 0), (.5, 0)], total=2, sep=None, - expected=(2, [0, 0.5, 1, 1.5])), + [3, 2, 1, .5], total=2, sep=None, expected=(2, [0, 0.5, 1, 1.5])), _Params( # total larger than required - [(.5, 0), (1, 0), (.2, 0)], total=None, sep=1, - expected=(6, [0, 2, 4])), + [.5, 1, .2], total=None, sep=1, expected=(6, [0, 2, 4])), # the case total=None, sep=None is tested separately below ]) -def test_get_packed_offsets_equal(wd_list, total, sep, expected): - result = _get_packed_offsets(wd_list, total, sep, mode='equal') +def test_get_packed_offsets_equal(widths, total, sep, expected): + result = _get_packed_offsets(widths, total, sep, mode='equal') assert result[0] == expected[0] assert_allclose(result[1], expected[1]) def test_get_packed_offsets_equal_total_none_sep_none(): with pytest.raises(ValueError): - _get_packed_offsets([(1, 0)] * 3, total=None, sep=None, mode='equal') + _get_packed_offsets([1, 1, 1], total=None, sep=None, mode='equal') @pytest.mark.parametrize('child_type', ['draw', 'image', 'text'])