Skip to content

Commit 46ffb4c

Browse files
committed
MNT: expire legend-related deprecations
1 parent 2d319fe commit 46ffb4c

File tree

4 files changed

+22
-29
lines changed

4 files changed

+22
-29
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Mixing positional and keyword arguments for ``legend`` handles and labels...
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... is no longer valid. If passing *handles* and *labels* to ``legend``, they must
4+
now be passed either both positionally or both as keywords.
5+
6+
Legend labels for ``plot``
7+
~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
Previously if a sequence was passed to the *label* parameter of `~.Axes.plot` when
9+
plotting a single dataset, the sequence was automatically cast to string for the legend
10+
label. Now, if the sequence length is not one an error is raised. To keep the old
11+
behavior, cast the sequence to string before passing.

lib/matplotlib/axes/_base.py

-7
Original file line numberDiff line numberDiff line change
@@ -523,13 +523,6 @@ def _plot_args(self, axes, tup, kwargs, *,
523523
labels = [label] * n_datasets
524524
elif len(label) == n_datasets:
525525
labels = label
526-
elif n_datasets == 1:
527-
msg = (f'Passing label as a length {len(label)} sequence when '
528-
'plotting a single dataset is deprecated in Matplotlib 3.9 '
529-
'and will error in 3.11. To keep the current behavior, '
530-
'cast the sequence to string before passing.')
531-
_api.warn_deprecated('3.9', message=msg)
532-
labels = [label]
533526
else:
534527
raise ValueError(
535528
f"label must be scalar or have the same length as the input "

lib/matplotlib/legend.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,7 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs):
12861286
legend(handles=handles, labels=labels)
12871287
12881288
The behavior for a mixture of positional and keyword handles and labels
1289-
is undefined and issues a warning; it will be an error in the future.
1289+
is undefined and raises an error.
12901290
12911291
Parameters
12921292
----------
@@ -1319,10 +1319,8 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs):
13191319
handlers = kwargs.get('handler_map')
13201320

13211321
if (handles is not None or labels is not None) and args:
1322-
_api.warn_deprecated("3.9", message=(
1323-
"You have mixed positional and keyword arguments, some input may "
1324-
"be discarded. This is deprecated since %(since)s and will "
1325-
"become an error in %(removal)s."))
1322+
raise ValueError("When passing handles and labels, they must both be "
1323+
"passed positionally or both as keywords.")
13261324

13271325
if (hasattr(handles, "__len__") and
13281326
hasattr(labels, "__len__") and

lib/matplotlib/tests/test_legend.py

+8-17
Original file line numberDiff line numberDiff line change
@@ -390,17 +390,14 @@ def test_legend_kwargs_handles_labels(self):
390390
ax.legend(labels=('a', 'b'), handles=(lnc, lns))
391391
Legend.assert_called_with(ax, (lnc, lns), ('a', 'b'))
392392

393-
def test_warn_mixed_args_and_kwargs(self):
393+
def test_error_mixed_args_and_kwargs(self):
394394
fig, ax = plt.subplots()
395395
th = np.linspace(0, 2*np.pi, 1024)
396396
lns, = ax.plot(th, np.sin(th), label='sin')
397397
lnc, = ax.plot(th, np.cos(th), label='cos')
398-
with pytest.warns(DeprecationWarning) as record:
398+
msg = 'must both be passed positionally or both as keywords'
399+
with pytest.raises(ValueError, match=msg):
399400
ax.legend((lnc, lns), labels=('a', 'b'))
400-
assert len(record) == 1
401-
assert str(record[0].message).startswith(
402-
"You have mixed positional and keyword arguments, some input may "
403-
"be discarded.")
404401

405402
def test_parasite(self):
406403
from mpl_toolkits.axes_grid1 import host_subplot # type: ignore[import]
@@ -460,16 +457,13 @@ def test_legend_kw_args(self):
460457
fig, (lines, lines2), ('a', 'b'), loc='right',
461458
bbox_transform=fig.transFigure)
462459

463-
def test_warn_args_kwargs(self):
460+
def test_error_args_kwargs(self):
464461
fig, axs = plt.subplots(1, 2)
465462
lines = axs[0].plot(range(10))
466463
lines2 = axs[1].plot(np.arange(10) * 2.)
467-
with pytest.warns(DeprecationWarning) as record:
464+
msg = 'must both be passed positionally or both as keywords'
465+
with pytest.raises(ValueError, match=msg):
468466
fig.legend((lines, lines2), labels=('a', 'b'))
469-
assert len(record) == 1
470-
assert str(record[0].message).startswith(
471-
"You have mixed positional and keyword arguments, some input may "
472-
"be discarded.")
473467

474468

475469
def test_figure_legend_outside():
@@ -1187,12 +1181,9 @@ def test_plot_single_input_multiple_label(label_array):
11871181
x = [1, 2, 3]
11881182
y = [2, 5, 6]
11891183
fig, ax = plt.subplots()
1190-
with pytest.warns(mpl.MatplotlibDeprecationWarning,
1191-
match='Passing label as a length 2 sequence'):
1184+
with pytest.raises(ValueError,
1185+
match='label must be scalar or have the same length'):
11921186
ax.plot(x, y, label=label_array)
1193-
leg = ax.legend()
1194-
assert len(leg.get_texts()) == 1
1195-
assert leg.get_texts()[0].get_text() == str(label_array)
11961187

11971188

11981189
def test_plot_single_input_list_label():

0 commit comments

Comments
 (0)