Skip to content

Commit 0634c0a

Browse files
committed
Bugfix for loc legend validation
Co-authored-by: John Paul Jepko <jpjepko@users.noreply.github.com>
1 parent 70e0ba8 commit 0634c0a

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

lib/matplotlib/legend.py

+15
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import itertools
2525
import logging
26+
import numbers
2627
import time
2728

2829
import numpy as np
@@ -517,6 +518,9 @@ def val_or_rc(val, rc_name):
517518
if not self.isaxes and loc in [0, 'best']:
518519
loc = 'upper right'
519520

521+
type_err_message = ("loc must be string, coordinate tuple, or"
522+
f" an integer 0-10, not {loc!r}")
523+
520524
# handle outside legends:
521525
self._outside_loc = None
522526
if isinstance(loc, str):
@@ -535,6 +539,17 @@ def val_or_rc(val, rc_name):
535539
loc = locs[0] + ' ' + locs[1]
536540
# check that loc is in acceptable strings
537541
loc = _api.check_getitem(self.codes, loc=loc)
542+
elif isinstance(loc, tuple):
543+
# validate the tuple represents Real coordinates
544+
if len(loc) != 2 or not all(isinstance(e, numbers.Real) for e in loc):
545+
raise ValueError(type_err_message)
546+
elif isinstance(loc, int):
547+
# validate the integer represents a string numeric value
548+
if loc < 0 or loc > 10:
549+
raise ValueError(type_err_message)
550+
else:
551+
# all other cases are invalid values of loc
552+
raise ValueError(type_err_message)
538553

539554
if self.isaxes and self._outside_loc:
540555
raise ValueError(

lib/matplotlib/tests/test_legend.py

+63
Original file line numberDiff line numberDiff line change
@@ -1219,3 +1219,66 @@ def test_ncol_ncols(fig_test, fig_ref):
12191219
ncols = 3
12201220
fig_test.legend(strings, ncol=ncols)
12211221
fig_ref.legend(strings, ncols=ncols)
1222+
1223+
1224+
def test_loc_invalid_tuple_exception():
1225+
# check that exception is raised if the loc arg
1226+
# of legend is not a 2-tuple of numbers
1227+
fig, ax = plt.subplots()
1228+
with pytest.raises(ValueError, match=('loc must be string, coordinate '
1229+
'tuple, or an integer 0-10, not \\(1.1,\\)')):
1230+
ax.legend(loc=(1.1, ))
1231+
1232+
with pytest.raises(ValueError, match=('loc must be string, coordinate '
1233+
'tuple, or an integer 0-10, not \\(0.481, 0.4227, 0.4523\\)')):
1234+
ax.legend(loc=(0.481, 0.4227, 0.4523))
1235+
1236+
with pytest.raises(ValueError, match=('loc must be string, coordinate '
1237+
'tuple, or an integer 0-10, not \\(0.481, \'go blue\'\\)')):
1238+
ax.legend(loc=(0.481, "go blue"))
1239+
1240+
1241+
def test_loc_valid_tuple():
1242+
fig, ax = plt.subplots()
1243+
ax.legend(loc=(0.481, 0.442))
1244+
ax.legend(loc=(1, 2))
1245+
1246+
1247+
def test_loc_invalid_type():
1248+
fig, ax = plt.subplots()
1249+
with pytest.raises(ValueError, match=("loc must be string, coordinate "
1250+
"tuple, or an integer 0-10, not {'not': True}")):
1251+
ax.legend(loc={'not': True})
1252+
1253+
1254+
def test_loc_validation_string_numeric_value():
1255+
fig, ax = plt.subplots()
1256+
ax.legend(loc=0)
1257+
ax.legend(loc=1)
1258+
ax.legend(loc=5)
1259+
ax.legend(loc=10)
1260+
with pytest.raises(ValueError, match=('loc must be string, coordinate '
1261+
'tuple, or an integer 0-10, not 11')):
1262+
ax.legend(loc=11)
1263+
1264+
with pytest.raises(ValueError, match=('loc must be string, coordinate '
1265+
'tuple, or an integer 0-10, not -1')):
1266+
ax.legend(loc=-1)
1267+
1268+
1269+
def test_loc_validation_string_value():
1270+
fig, ax = plt.subplots()
1271+
ax.legend(loc='best')
1272+
ax.legend(loc='upper right')
1273+
ax.legend(loc='best')
1274+
ax.legend(loc='upper right')
1275+
ax.legend(loc='upper left')
1276+
ax.legend(loc='lower left')
1277+
ax.legend(loc='lower right')
1278+
ax.legend(loc='right')
1279+
ax.legend(loc='center left')
1280+
ax.legend(loc='center right')
1281+
ax.legend(loc='lower center')
1282+
ax.legend(loc='upper center')
1283+
with pytest.raises(ValueError, match="'wrong' is not a valid value for"):
1284+
ax.legend(loc='wrong')

0 commit comments

Comments
 (0)