From 740f28386aa9e7e81bdbe878f81c47e9c58ca194 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 16 Jun 2021 11:47:26 +0200 Subject: [PATCH] Suppress repeated logwarns in postscript output. For a given call to savefig(), we only need to warn once about alpha or usetex support. (RendererPS is generated afresh for each savefig() call, so it's fine to do the caching on it.) --- lib/matplotlib/backends/backend_ps.py | 40 ++++++++++++------------- lib/matplotlib/tests/test_backend_ps.py | 7 +++-- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index b5263f8fbe66..818b17a39801 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -265,6 +265,21 @@ def __init__(self, width, height, pswriter, imagedpi=72): self._path_collection_id = 0 self._character_tracker = _backend_pdf_ps.CharacterTracker() + self._logwarn_once = functools.lru_cache(None)(_log.warning) + + def _is_transparent(self, rgb_or_rgba): + if rgb_or_rgba is None: + return True # Consistent with rgbFace semantics. + elif len(rgb_or_rgba) == 4: + if rgb_or_rgba[3] == 0: + return True + if rgb_or_rgba[3] != 1: + self._logwarn_once( + "The PostScript backend does not support transparency; " + "partially transparent artists will be rendered opaque.") + return False + else: # len() == 3. + return False def set_color(self, r, g, b, store=True): if (r, g, b) != self.color: @@ -457,7 +472,7 @@ def draw_markers( ps_color = ( None - if _is_transparent(rgbFace) + if self._is_transparent(rgbFace) else '%1.3f setgray' % rgbFace[0] if rgbFace[0] == rgbFace[1] == rgbFace[2] else '%1.3f %1.3f %1.3f setrgbcolor' % rgbFace[:3]) @@ -552,7 +567,7 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms, def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None): # docstring inherited if not hasattr(self, "psfrag"): - _log.warning( + self._logwarn_once( "The PS backend determines usetex status solely based on " "rcParams['text.usetex'] and does not support having " "usetex=True only for some elements; this element will thus " @@ -589,7 +604,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None): def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): # docstring inherited - if _is_transparent(gc.get_rgb()): + if self._is_transparent(gc.get_rgb()): return # Special handling for fully transparent. if ismath == 'TeX': @@ -729,10 +744,10 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): """ write = self._pswriter.write mightstroke = (gc.get_linewidth() > 0 - and not _is_transparent(gc.get_rgb())) + and not self._is_transparent(gc.get_rgb())) if not mightstroke: stroke = False - if _is_transparent(rgbFace): + if self._is_transparent(rgbFace): fill = False hatch = gc.get_hatch() @@ -769,21 +784,6 @@ def _draw_ps(self, ps, gc, rgbFace, *, fill=True, stroke=True): write("grestore\n") -def _is_transparent(rgb_or_rgba): - if rgb_or_rgba is None: - return True # Consistent with rgbFace semantics. - elif len(rgb_or_rgba) == 4: - if rgb_or_rgba[3] == 0: - return True - if rgb_or_rgba[3] != 1: - _log.warning( - "The PostScript backend does not support transparency; " - "partially transparent artists will be rendered opaque.") - return False - else: # len() == 3. - return False - - @_api.deprecated("3.4", alternative="GraphicsContextBase") class GraphicsContextPS(GraphicsContextBase): def get_capstyle(self): diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index 57215367ab3b..a70145cc6d2d 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -149,10 +149,11 @@ def test_failing_latex(): @needs_usetex def test_partial_usetex(caplog): caplog.set_level("WARNING") - plt.figtext(.5, .5, "foo", usetex=True) + plt.figtext(.1, .1, "foo", usetex=True) + plt.figtext(.2, .2, "bar", usetex=True) plt.savefig(io.BytesIO(), format="ps") - assert caplog.records and all("as if usetex=False" in record.getMessage() - for record in caplog.records) + record, = caplog.records # asserts there's a single record. + assert "as if usetex=False" in record.getMessage() @image_comparison(["useafm.eps"])