From cf86846c8f1d7e95718ab866449d853d4890d937 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Mon, 16 Sep 2019 17:44:36 -0400 Subject: [PATCH] Backport PR #15271: Fix font weight validation --- lib/matplotlib/rcsetup.py | 21 +++++++++++++++++---- lib/matplotlib/tests/test_rcparams.py | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 685117113fcd..520e71d3bf4e 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -401,6 +401,19 @@ def validate_fontsize(s): validate_fontsizelist = _listify_validator(validate_fontsize) +def validate_fontweight(s): + weights = [ + 'ultralight', 'light', 'normal', 'regular', 'book', 'medium', 'roman', + 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 'black'] + # Note: Historically, weights have been case-sensitive in Matplotlib + if s in weights: + return s + try: + return int(s) + except (ValueError, TypeError): + raise ValueError(f'{s} is not a valid font weight. %s') + + def validate_font_properties(s): parse_fontconfig_pattern(s) return s @@ -1095,7 +1108,7 @@ def _validate_linestyle(ls): 'font.style': ['normal', validate_string], 'font.variant': ['normal', validate_string], 'font.stretch': ['normal', validate_string], - 'font.weight': ['normal', validate_string], + 'font.weight': ['normal', validate_fontweight], 'font.size': [10, validate_float], # Base font size in points 'font.serif': [['DejaVu Serif', 'Bitstream Vera Serif', 'Computer Modern Roman', @@ -1174,7 +1187,7 @@ def _validate_linestyle(ls): 'axes.titlesize': ['large', validate_fontsize], # fontsize of the # axes title 'axes.titlelocation': ['center', validate_axes_titlelocation], # alignment of axes title - 'axes.titleweight': ['normal', validate_string], # font weight of axes title + 'axes.titleweight': ['normal', validate_fontweight], # font weight of axes title 'axes.titlecolor': ['auto', validate_color_or_auto], # font color of axes title 'axes.titlepad': [6.0, validate_float], # pad from axes top to title in points 'axes.grid': [False, validate_bool], # display grid or not @@ -1187,7 +1200,7 @@ def _validate_linestyle(ls): 'axes.labelsize': ['medium', validate_fontsize], # fontsize of the # x any y labels 'axes.labelpad': [4.0, validate_float], # space between label and axis - 'axes.labelweight': ['normal', validate_string], # fontsize of the x any y labels + 'axes.labelweight': ['normal', validate_fontweight], # fontsize of the x any y labels 'axes.labelcolor': ['black', validate_color], # color of axis label 'axes.formatter.limits': [[-5, 6], validate_nseq_int(2)], # use scientific notation if log10 @@ -1320,7 +1333,7 @@ def _validate_linestyle(ls): ## figure props # figure title 'figure.titlesize': ['large', validate_fontsize], - 'figure.titleweight': ['normal', validate_string], + 'figure.titleweight': ['normal', validate_fontweight], # figure size in inches: width by height 'figure.figsize': [[6.4, 4.8], validate_nseq_float(2)], diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index a6b4890cd6e6..87dfbeceba8c 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -19,6 +19,7 @@ validate_colorlist, validate_color, validate_bool, + validate_fontweight, validate_nseq_int, validate_nseq_float, validate_cycler, @@ -415,6 +416,26 @@ def test_validator_invalid(validator, arg, exception_type): validator(arg) +@pytest.mark.parametrize('weight, parsed_weight', [ + ('bold', 'bold'), + ('BOLD', ValueError), # weight is case-sensitive + (100, 100), + ('100', 100), + (np.array(100), 100), + # fractional fontweights are not defined. This should actually raise a + # ValueError, but historically did not. + (20.6, 20), + ('20.6', ValueError), + ([100], ValueError), +]) +def test_validate_fontweight(weight, parsed_weight): + if parsed_weight is ValueError: + with pytest.raises(ValueError): + validate_fontweight(weight) + else: + assert validate_fontweight(weight) == parsed_weight + + def test_keymaps(): key_list = [k for k in mpl.rcParams if 'keymap' in k] for k in key_list: