From ffc7ab0990cf994f08fee286db326a2c28a8fce3 Mon Sep 17 00:00:00 2001 From: Ruth Comer <10599679+rcomer@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:02:12 +0000 Subject: [PATCH] Update handling of sequence labels for plot --- .../next_api_changes/behavior/27767-REC.rst | 7 +++++++ .../deprecations/27767-REC.rst | 9 +++++++++ lib/matplotlib/axes/_base.py | 20 +++++++++++++------ lib/matplotlib/tests/test_legend.py | 10 +++++++++- 4 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 doc/api/next_api_changes/behavior/27767-REC.rst create mode 100644 doc/api/next_api_changes/deprecations/27767-REC.rst diff --git a/doc/api/next_api_changes/behavior/27767-REC.rst b/doc/api/next_api_changes/behavior/27767-REC.rst new file mode 100644 index 000000000000..f6b4dc156732 --- /dev/null +++ b/doc/api/next_api_changes/behavior/27767-REC.rst @@ -0,0 +1,7 @@ +Legend labels for ``plot`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously if a sequence was passed to the *label* parameter of `~.Axes.plot` when +plotting a single dataset, the sequence was automatically cast to string for the legend +label. Now, if the sequence has only one element, that element will be the legend +label. To keep the old behavior, cast the sequence to string before passing. diff --git a/doc/api/next_api_changes/deprecations/27767-REC.rst b/doc/api/next_api_changes/deprecations/27767-REC.rst new file mode 100644 index 000000000000..68781090df0a --- /dev/null +++ b/doc/api/next_api_changes/deprecations/27767-REC.rst @@ -0,0 +1,9 @@ +Legend labels for ``plot`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously if a sequence was passed to the *label* parameter of `~.Axes.plot` when +plotting a single dataset, the sequence was automatically cast to string for the legend +label. This behavior is now deprecated and in future will error if the sequence length +is not one (consistent with multi-dataset behavior, where the number of elements must +match the number of datasets). To keep the old behavior, cast the sequence to string +before passing. diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 51347f08b989..0617fc7681bd 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -513,14 +513,22 @@ def _plot_args(self, axes, tup, kwargs, *, label = kwargs.get('label') n_datasets = max(ncx, ncy) - if n_datasets > 1 and not cbook.is_scalar_or_string(label): - if len(label) != n_datasets: - raise ValueError(f"label must be scalar or have the same " - f"length as the input data, but found " - f"{len(label)} for {n_datasets} datasets.") + + if cbook.is_scalar_or_string(label): + labels = [label] * n_datasets + elif len(label) == n_datasets: labels = label + elif n_datasets == 1: + msg = (f'Passing label as a length {len(label)} sequence when ' + 'plotting a single dataset is deprecated in Matplotlib 3.9 ' + 'and will error in 3.11. To keep the current behavior, ' + 'cast the sequence to string before passing.') + _api.warn_deprecated('3.9', message=msg) + labels = [label] else: - labels = [label] * n_datasets + raise ValueError( + f"label must be scalar or have the same length as the input " + f"data, but found {len(label)} for {n_datasets} datasets.") result = (make_artist(axes, x[:, j % ncx], y[:, j % ncy], kw, {**kwargs, 'label': label}) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index b23649f22e48..73892698882c 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -1197,12 +1197,20 @@ def test_plot_single_input_multiple_label(label_array): x = [1, 2, 3] y = [2, 5, 6] fig, ax = plt.subplots() - ax.plot(x, y, label=label_array) + with pytest.warns(mpl.MatplotlibDeprecationWarning, + match='Passing label as a length 2 sequence'): + ax.plot(x, y, label=label_array) leg = ax.legend() assert len(leg.get_texts()) == 1 assert leg.get_texts()[0].get_text() == str(label_array) +def test_plot_single_input_list_label(): + fig, ax = plt.subplots() + line, = ax.plot([[0], [1]], label=['A']) + assert line.get_label() == 'A' + + def test_plot_multiple_label_incorrect_length_exception(): # check that exception is raised if multiple labels # are given, but number of on labels != number of lines