Skip to content

Commit 3687f94

Browse files
authored
Fix rc init when matplotlib is imported first (#569)
* Fix rc init when matplotlib is imported first
1 parent 076175c commit 3687f94

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

ultraplot/internals/rcsetup.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,14 @@ def copy(self):
734734
if not hasattr(RcParams, "validate"): # not mission critical so skip
735735
warnings._warn_ultraplot("Failed to update matplotlib rcParams validators.")
736736
else:
737+
738+
def _validator_accepts(validator, value):
739+
try:
740+
validator(value)
741+
return True
742+
except Exception:
743+
return False
744+
737745
_validate = RcParams.validate
738746
_validate["image.cmap"] = _validate_cmap("continuous")
739747
_validate["legend.loc"] = _validate_belongs(*LEGEND_LOCS)
@@ -752,6 +760,20 @@ def copy(self):
752760
_validate[_key] = functools.partial(_validate_color, alternative="auto")
753761
if _validator is getattr(msetup, "validate_color_or_inherit", None):
754762
_validate[_key] = functools.partial(_validate_color, alternative="inherit")
763+
# Matplotlib may wrap fontsize validators in callable objects instead of
764+
# exposing validate_fontsize directly. Detect these by behavior so custom
765+
# shorthands like "med-large" remain valid regardless of import order.
766+
if (
767+
_key.endswith("size")
768+
and _key not in FONT_KEYS
769+
and _validator_accepts(_validator, "large")
770+
and not _validator_accepts(_validator, "med-large")
771+
):
772+
FONT_KEYS.add(_key)
773+
if _validator_accepts(_validator, None):
774+
_validate[_key] = _validate_or_none(_validate_fontsize)
775+
else:
776+
_validate[_key] = _validate_fontsize
755777
for _keys, _validator_replace in ((EM_KEYS, _validate_em), (PT_KEYS, _validate_pt)):
756778
for _key in _keys:
757779
_validator = _validate.get(_key, None)

ultraplot/tests/test_config.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import importlib
2+
import os
3+
import pathlib
4+
import subprocess
5+
import sys
26
import threading
37
from queue import Queue
48

@@ -212,3 +216,45 @@ def _reader():
212216
observed = [results.get() for _ in range(results.qsize())]
213217
assert observed, "No rcParams observations were recorded."
214218
assert all(value in allowed for value in observed)
219+
220+
221+
def _run_in_subprocess(code):
222+
code = (
223+
"import pathlib\n"
224+
"import sys\n"
225+
"sys.path.insert(0, str(pathlib.Path.cwd()))\n" + code
226+
)
227+
env = os.environ.copy()
228+
env["MPLBACKEND"] = "Agg"
229+
return subprocess.run(
230+
[sys.executable, "-c", code],
231+
capture_output=True,
232+
text=True,
233+
cwd=str(pathlib.Path(__file__).resolve().parents[2]),
234+
env=env,
235+
)
236+
237+
238+
def test_matplotlib_import_before_ultraplot_allows_rc_mutation():
239+
"""
240+
Import order regression test for issue #568.
241+
"""
242+
result = _run_in_subprocess(
243+
"import matplotlib.pyplot as plt\n"
244+
"import ultraplot as uplt\n"
245+
"uplt.rc['figure.facecolor'] = 'white'\n"
246+
)
247+
assert result.returncode == 0, result.stderr
248+
249+
250+
def test_matplotlib_import_before_ultraplot_allows_custom_fontsize_tokens():
251+
"""
252+
Ensure patched fontsize validators are active regardless of import order.
253+
"""
254+
result = _run_in_subprocess(
255+
"import matplotlib.pyplot as plt\n"
256+
"import ultraplot as uplt\n"
257+
"for key in ('axes.titlesize', 'figure.titlesize', 'legend.fontsize', 'xtick.labelsize'):\n"
258+
" uplt.rc[key] = 'med-large'\n"
259+
)
260+
assert result.returncode == 0, result.stderr

0 commit comments

Comments
 (0)