2121
2222import six
2323
24- import re , sys
25- from pyparsing import Literal , ZeroOrMore , \
26- Optional , Regex , StringEnd , ParseException , Suppress
24+ import re
25+ import sys
26+ from pyparsing import (Literal , ZeroOrMore , Optional , Regex , StringEnd ,
27+ ParseException , Suppress )
28+
29+ try :
30+ from functools import lru_cache
31+ except ImportError :
32+ from backports .functools_lru_cache import lru_cache
2733
2834family_punc = r'\\\-:,'
2935family_unescape = re .compile (r'\\([%s])' % family_punc ).sub
@@ -166,7 +172,13 @@ def _property(self, s, loc, tokens):
166172 self ._properties .setdefault (key , []).extend (val )
167173 return []
168174
169- parse_fontconfig_pattern = FontconfigPatternParser ().parse
175+
176+ # `parse_fontconfig_pattern` is a bottleneck during the tests because it is
177+ # repeatedly called when the rcParams are reset (to validate the default
178+ # fonts). In practice, the cache size doesn't grow beyond a few dozen entries
179+ # during the test suite.
180+ parse_fontconfig_pattern = lru_cache ()(FontconfigPatternParser ().parse )
181+
170182
171183def generate_fontconfig_pattern (d ):
172184 """
@@ -180,7 +192,8 @@ def generate_fontconfig_pattern(d):
180192 val = getattr (d , 'get_' + key )()
181193 if val is not None and val != []:
182194 if type (val ) == list :
183- val = [value_escape (r'\\\1' , str (x )) for x in val if x is not None ]
195+ val = [value_escape (r'\\\1' , str (x )) for x in val
196+ if x is not None ]
184197 if val != []:
185198 val = ',' .join (val )
186199 props .append (":%s=%s" % (key , val ))
0 commit comments