Skip to content

Commit f0593a6

Browse files
authored
Merge pull request #22323 from anntzer/unmaxdict
Replace sole use of maxdict by lru_cache.
2 parents e1910b8 + 63608d8 commit f0593a6

File tree

4 files changed

+33
-22
lines changed

4 files changed

+33
-22
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``matplotlib.cbook.maxdict`` is deprecated
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
This class has been deprecated in favor of the standard library
4+
``functools.lru_cache``.

lib/matplotlib/cbook/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ def flatten(seq, scalarp=is_scalar_or_string):
540540
yield from flatten(item, scalarp)
541541

542542

543+
@_api.deprecated("3.6", alternative="functools.lru_cache")
543544
class maxdict(dict):
544545
"""
545546
A dictionary with a maximum size.

lib/matplotlib/tests/test_text.py

+7
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@ def test_pdf_chars_beyond_bmp():
768768

769769
@needs_usetex
770770
def test_metrics_cache():
771+
mpl.text._get_text_metrics_with_cache_impl.cache_clear()
772+
771773
fig = plt.figure()
772774
fig.text(.3, .5, "foo\nbar")
773775
fig.text(.3, .5, "foo\nbar", usetex=True)
@@ -788,3 +790,8 @@ def call(*args, **kwargs):
788790
# collision with the non-TeX string (drawn first here) whose metrics would
789791
# get incorrectly reused by the first TeX string.
790792
assert len(ys["foo"]) == len(ys["bar"]) == 1
793+
794+
info = mpl.text._get_text_metrics_with_cache_impl.cache_info()
795+
# Every string gets a miss for the first layouting (extents), then a hit
796+
# when drawing, but "foo\nbar" gets two hits as it's drawn twice.
797+
assert info.hits > info.misses

lib/matplotlib/text.py

+21-22
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Classes for including text in a figure.
33
"""
44

5+
import functools
56
import logging
67
import math
78
import numbers
@@ -89,6 +90,21 @@ def _get_textbox(text, renderer):
8990
return x_box, y_box, w_box, h_box
9091

9192

93+
def _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi):
94+
"""Call ``renderer.get_text_width_height_descent``, caching the results."""
95+
# Cached based on a copy of fontprop so that later in-place mutations of
96+
# the passed-in argument do not mess up the cache.
97+
return _get_text_metrics_with_cache_impl(
98+
weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)
99+
100+
101+
@functools.lru_cache(4096)
102+
def _get_text_metrics_with_cache_impl(
103+
renderer_ref, text, fontprop, ismath, dpi):
104+
# dpi is unused, but participates in cache invalidation (via the renderer).
105+
return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)
106+
107+
92108
@docstring.interpd
93109
@cbook._define_aliases({
94110
"color": ["c"],
@@ -108,7 +124,6 @@ class Text(Artist):
108124
"""Handle storing and drawing of text in window or data coordinates."""
109125

110126
zorder = 3
111-
_cached = cbook.maxdict(50)
112127

113128
def __repr__(self):
114129
return "Text(%s, %s, %s)" % (self._x, self._y, repr(self._text))
@@ -273,23 +288,6 @@ def update_from(self, other):
273288
self._linespacing = other._linespacing
274289
self.stale = True
275290

276-
def _get_text_metrics_with_cache(
277-
self, renderer, text, fontproperties, ismath):
278-
"""
279-
Call ``renderer.get_text_width_height_descent``, caching the results.
280-
"""
281-
cache_key = (
282-
weakref.ref(renderer),
283-
text,
284-
hash(fontproperties),
285-
ismath,
286-
self.figure.dpi,
287-
)
288-
if cache_key not in self._cached:
289-
self._cached[cache_key] = renderer.get_text_width_height_descent(
290-
text, fontproperties, ismath)
291-
return self._cached[cache_key]
292-
293291
def _get_layout(self, renderer):
294292
"""
295293
Return the extent (bbox) of the text together with
@@ -305,16 +303,17 @@ def _get_layout(self, renderer):
305303
ys = []
306304

307305
# Full vertical extent of font, including ascenders and descenders:
308-
_, lp_h, lp_d = self._get_text_metrics_with_cache(
306+
_, lp_h, lp_d = _get_text_metrics_with_cache(
309307
renderer, "lp", self._fontproperties,
310-
ismath="TeX" if self.get_usetex() else False)
308+
ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
311309
min_dy = (lp_h - lp_d) * self._linespacing
312310

313311
for i, line in enumerate(lines):
314312
clean_line, ismath = self._preprocess_math(line)
315313
if clean_line:
316-
w, h, d = self._get_text_metrics_with_cache(
317-
renderer, clean_line, self._fontproperties, ismath)
314+
w, h, d = _get_text_metrics_with_cache(
315+
renderer, clean_line, self._fontproperties,
316+
ismath=ismath, dpi=self.figure.dpi)
318317
else:
319318
w = h = d = 0
320319

0 commit comments

Comments
 (0)