Skip to content

Don't pass unused xdescent to _get_packed_offsets. #24462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions lib/matplotlib/offsetbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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


Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
48 changes: 23 additions & 25 deletions lib/matplotlib/tests/test_offsetbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'])
Expand Down