Skip to content

FIX: behaviour of legend labels with leading underscores did not adhere to the API documentation #24713

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

Closed
Closed
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
18 changes: 2 additions & 16 deletions lib/matplotlib/legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"""

import itertools
import logging
import time

import numpy as np
Expand Down Expand Up @@ -418,17 +417,6 @@ def val_or_rc(val, rc_name):
self.borderaxespad = val_or_rc(borderaxespad, 'legend.borderaxespad')
self.columnspacing = val_or_rc(columnspacing, 'legend.columnspacing')
self.shadow = val_or_rc(shadow, 'legend.shadow')
# trim handles and labels if illegal label...
_lab, _hand = [], []
for label, handle in zip(labels, handles):
if isinstance(label, str) and label.startswith('_'):
_api.warn_external(f"The label {label!r} of {handle!r} starts "
"with '_'. It is thus excluded from the "
"legend.")
else:
_lab.append(label)
_hand.append(handle)
labels, handles = _lab, _hand

handles = list(handles)
if len(handles) < 2:
Expand Down Expand Up @@ -1228,8 +1216,6 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs):
*kwargs* with keywords handles and labels removed.

"""
log = logging.getLogger(__name__)

handlers = kwargs.get('handler_map')
extra_args = ()

Expand All @@ -1253,8 +1239,8 @@ def _parse_legend_args(axs, *args, handles=None, labels=None, **kwargs):
elif len(args) == 0:
handles, labels = _get_legend_handles_labels(axs, handlers)
if not handles:
log.warning(
"No artists with labels found to put in legend. Note that "
_api.warn_external(
"No artists with labels found to put in legend. Note that "
"artists whose label start with an underscore are ignored "
"when legend() is called with no argument.")

Expand Down
55 changes: 38 additions & 17 deletions lib/matplotlib/tests/test_legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,40 @@ def test_various_labels():
ax.legend(numpoints=1, loc='best')


def test_legend_label_with_leading_underscore():
def test_legend_label_with_leading_underscore1():
"""
Test that artists with labels starting with an underscore are not added to
the legend, and that a warning is issued if one tries to add them
explicitly.
the legend when the legend method is called with no arguments, and that a
warning is issued if one tries to add them explicitly.
"""
fig, ax = plt.subplots()
line, = ax.plot([0, 1], label='_foo')
ax.plot([0, 1], label='_foo')
with pytest.warns(UserWarning,
match=r"starts with '_'.*excluded from the legend."):
legend = ax.legend(handles=[line])
match=r"artists whose label start with an underscore "
"are ignored"):
legend = ax.legend()
assert len(legend.legendHandles) == 0


def test_legend_label_with_leading_underscore2():
"""
Test that artists with labels starting with an underscore are added to the
legend when the legend method is called with arguments.
"""
fig, ax = plt.subplots()
lines = ax.plot([0, 1], label='_foo')
legend = ax.legend(handles=lines)
assert len(legend.legendHandles) == 1
legend = ax.legend(handles=lines, labels=["_foo"])
assert len(legend.legendHandles) == 1
legend = ax.legend(labels=["_foo"])
assert len(legend.legendHandles) == 1
legend = ax.legend(["_foo"])
assert len(legend.legendHandles) == 1
legend = ax.legend(lines, ["_foo"])
assert len(legend.legendHandles) == 1


@image_comparison(['legend_labels_first.png'], remove_text=True)
def test_labels_first():
# test labels to left of markers
Expand Down Expand Up @@ -512,9 +532,10 @@ def test_text_nohandler_warning():
"""Test that Text artists with labels raise a warning"""
fig, ax = plt.subplots()
ax.text(x=0, y=0, s="text", label="label")
with pytest.warns(UserWarning) as record:
with pytest.warns(UserWarning,
match="Legend does not support handles for .+ "
"instances"):
ax.legend()
assert len(record) == 1

# this should _not_ warn:
f, ax = plt.subplots()
Expand Down Expand Up @@ -546,7 +567,7 @@ def test_legend_title_empty():
# it comes back as an empty string, and that it is not
# visible:
fig, ax = plt.subplots()
ax.plot(range(10))
ax.plot(range(10), label="foo")
leg = ax.legend()
assert leg.get_title().get_text() == ""
assert not leg.get_title().get_visible()
Expand Down Expand Up @@ -579,7 +600,7 @@ def test_window_extent_cached_renderer():

def test_legend_title_fontprop_fontsize():
# test the title_fontsize kwarg
plt.plot(range(10))
plt.plot(range(10), label="foo")
with pytest.raises(ValueError):
plt.legend(title='Aardvark', title_fontsize=22,
title_fontproperties={'family': 'serif', 'size': 22})
Expand All @@ -590,27 +611,27 @@ def test_legend_title_fontprop_fontsize():

fig, axes = plt.subplots(2, 3, figsize=(10, 6))
axes = axes.flat
axes[0].plot(range(10))
axes[0].plot(range(10), label="foo")
leg0 = axes[0].legend(title='Aardvark', title_fontsize=22)
assert leg0.get_title().get_fontsize() == 22
axes[1].plot(range(10))
axes[1].plot(range(10), label="foo")
leg1 = axes[1].legend(title='Aardvark',
title_fontproperties={'family': 'serif', 'size': 22})
assert leg1.get_title().get_fontsize() == 22
axes[2].plot(range(10))
axes[2].plot(range(10), label="foo")
mpl.rcParams['legend.title_fontsize'] = None
leg2 = axes[2].legend(title='Aardvark',
title_fontproperties={'family': 'serif'})
assert leg2.get_title().get_fontsize() == mpl.rcParams['font.size']
axes[3].plot(range(10))
axes[3].plot(range(10), label="foo")
leg3 = axes[3].legend(title='Aardvark')
assert leg3.get_title().get_fontsize() == mpl.rcParams['font.size']
axes[4].plot(range(10))
axes[4].plot(range(10), label="foo")
mpl.rcParams['legend.title_fontsize'] = 20
leg4 = axes[4].legend(title='Aardvark',
title_fontproperties={'family': 'serif'})
assert leg4.get_title().get_fontsize() == 20
axes[5].plot(range(10))
axes[5].plot(range(10), label="foo")
leg5 = axes[5].legend(title='Aardvark')
assert leg5.get_title().get_fontsize() == 20

Expand Down Expand Up @@ -895,7 +916,7 @@ def test_legend_labelcolor_rcparam_markerfacecolor_short():


def test_get_set_draggable():
legend = plt.legend()
legend = plt.legend("foo")
assert not legend.get_draggable()
legend.set_draggable(True)
assert legend.get_draggable()
Expand Down