Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cdea77c

Browse filesBrowse files
tacaswellmdboom
authored andcommitted
Merge pull request #5295 from mdboom/too-many-open-files
MNT: Reduce number of font file handles opened
1 parent 1b243ed commit cdea77c
Copy full SHA for cdea77c

File tree

Expand file treeCollapse file tree

13 files changed

+71
-79
lines changed
Filter options
Expand file treeCollapse file tree

13 files changed

+71
-79
lines changed

‎INSTALL

Copy file name to clipboardExpand all lines: INSTALL
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ libpng 1.2 (or later)
214214
``cycler`` 0.9 or later
215215
Composable cycle class used for constructing style-cycles
216216

217+
`functools32`
218+
Required for compatibility if running on versions of Python before
219+
Python 3.2.
220+
217221

218222
Optional GUI framework
219223
^^^^^^^^^^^^^^^^^^^^^^

‎lib/matplotlib/backends/backend_agg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_agg.py
+7-15Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
FigureManagerBase, FigureCanvasBase
3333
from matplotlib.cbook import is_string_like, maxdict, restrict_dict
3434
from matplotlib.figure import Figure
35-
from matplotlib.font_manager import findfont
36-
from matplotlib.ft2font import FT2Font, LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING, \
35+
from matplotlib.font_manager import findfont, get_font
36+
from matplotlib.ft2font import LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING, \
3737
LOAD_DEFAULT, LOAD_NO_AUTOHINT
3838
from matplotlib.mathtext import MathTextParser
3939
from matplotlib.path import Path
@@ -81,7 +81,6 @@ class RendererAgg(RendererBase):
8181
# renderer at a time
8282

8383
lock = threading.RLock()
84-
_fontd = maxdict(50)
8584
def __init__(self, width, height, dpi):
8685
if __debug__: verbose.report('RendererAgg.__init__', 'debug-annoying')
8786
RendererBase.__init__(self)
@@ -191,6 +190,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
191190

192191
flags = get_hinting_flag()
193192
font = self._get_agg_font(prop)
193+
194194
if font is None: return None
195195
if len(s) == 1 and ord(s) > 127:
196196
font.load_char(ord(s), flags=flags)
@@ -272,18 +272,10 @@ def _get_agg_font(self, prop):
272272
if __debug__: verbose.report('RendererAgg._get_agg_font',
273273
'debug-annoying')
274274

275-
key = hash(prop)
276-
font = RendererAgg._fontd.get(key)
277-
278-
if font is None:
279-
fname = findfont(prop)
280-
font = RendererAgg._fontd.get(fname)
281-
if font is None:
282-
font = FT2Font(
283-
fname,
284-
hinting_factor=rcParams['text.hinting_factor'])
285-
RendererAgg._fontd[fname] = font
286-
RendererAgg._fontd[key] = font
275+
fname = findfont(prop)
276+
font = get_font(
277+
fname,
278+
hinting_factor=rcParams['text.hinting_factor'])
287279

288280
font.clear()
289281
size = prop.get_size_in_points()

‎lib/matplotlib/backends/backend_pdf.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_pdf.py
+6-14Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@
3535
from matplotlib.cbook import Bunch, is_string_like, \
3636
get_realpath_and_stat, is_writable_file_like, maxdict
3737
from matplotlib.figure import Figure
38-
from matplotlib.font_manager import findfont, is_opentype_cff_font
38+
from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font
3939
from matplotlib.afm import AFM
4040
import matplotlib.type1font as type1font
4141
import matplotlib.dviread as dviread
42-
from matplotlib.ft2font import FT2Font, FIXED_WIDTH, ITALIC, LOAD_NO_SCALE, \
42+
from matplotlib.ft2font import FIXED_WIDTH, ITALIC, LOAD_NO_SCALE, \
4343
LOAD_NO_HINTING, KERNING_UNFITTED
4444
from matplotlib.mathtext import MathTextParser
4545
from matplotlib.transforms import Affine2D, BboxBase
@@ -757,7 +757,7 @@ def createType1Descriptor(self, t1font, fontfile):
757757
if 0:
758758
flags |= 1 << 18
759759

760-
ft2font = FT2Font(fontfile)
760+
ft2font = get_font(fontfile)
761761

762762
descriptor = {
763763
'Type': Name('FontDescriptor'),
@@ -817,7 +817,7 @@ def _get_xobject_symbol_name(self, filename, symbol_name):
817817
def embedTTF(self, filename, characters):
818818
"""Embed the TTF font from the named file into the document."""
819819

820-
font = FT2Font(filename)
820+
font = get_font(filename)
821821
fonttype = rcParams['pdf.fonttype']
822822

823823
def cvt(length, upe=font.units_per_EM, nearest=True):
@@ -1526,7 +1526,6 @@ def writeTrailer(self):
15261526

15271527

15281528
class RendererPdf(RendererBase):
1529-
truetype_font_cache = maxdict(50)
15301529
afm_font_cache = maxdict(50)
15311530

15321531
def __init__(self, file, image_dpi):
@@ -2127,15 +2126,8 @@ def _get_font_afm(self, prop):
21272126
return font
21282127

21292128
def _get_font_ttf(self, prop):
2130-
key = hash(prop)
2131-
font = self.truetype_font_cache.get(key)
2132-
if font is None:
2133-
filename = findfont(prop)
2134-
font = self.truetype_font_cache.get(filename)
2135-
if font is None:
2136-
font = FT2Font(filename)
2137-
self.truetype_font_cache[filename] = font
2138-
self.truetype_font_cache[key] = font
2129+
filename = findfont(prop)
2130+
font = get_font(filename)
21392131
font.clear()
21402132
font.set_size(prop.get_size_in_points(), 72)
21412133
return font

‎lib/matplotlib/backends/backend_pgf.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_pgf.py
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@
3636
system_fonts = []
3737
if sys.platform.startswith('win'):
3838
from matplotlib import font_manager
39-
from matplotlib.ft2font import FT2Font
4039
for f in font_manager.win32InstalledFonts():
4140
try:
42-
system_fonts.append(FT2Font(str(f)).family_name)
41+
system_fonts.append(font_manager.get_font(str(f)).family_name)
4342
except:
4443
pass # unknown error, skip this font
4544
else:

‎lib/matplotlib/backends/backend_ps.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_ps.py
+5-13Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
2828
is_writable_file_like, maxdict, file_requires_unicode
2929
from matplotlib.figure import Figure
3030

31-
from matplotlib.font_manager import findfont, is_opentype_cff_font
32-
from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING
31+
from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font
32+
from matplotlib.ft2font import KERNING_DEFAULT, LOAD_NO_HINTING
3333
from matplotlib.ttconv import convert_ttf_to_ps
3434
from matplotlib.mathtext import MathTextParser
3535
from matplotlib._mathtext_data import uni2type1
@@ -199,7 +199,6 @@ class RendererPS(RendererBase):
199199
context instance that controls the colors/styles.
200200
"""
201201

202-
fontd = maxdict(50)
203202
afmfontd = maxdict(50)
204203

205204
def __init__(self, width, height, pswriter, imagedpi=72):
@@ -393,15 +392,8 @@ def _get_font_afm(self, prop):
393392
return font
394393

395394
def _get_font_ttf(self, prop):
396-
key = hash(prop)
397-
font = self.fontd.get(key)
398-
if font is None:
399-
fname = findfont(prop)
400-
font = self.fontd.get(fname)
401-
if font is None:
402-
font = FT2Font(fname)
403-
self.fontd[fname] = font
404-
self.fontd[key] = font
395+
fname = findfont(prop)
396+
font = get_font(fname)
405397
font.clear()
406398
size = prop.get_size_in_points()
407399
font.set_size(size, 72.0)
@@ -1145,7 +1137,7 @@ def print_figure_impl():
11451137
if not rcParams['ps.useafm']:
11461138
for font_filename, chars in six.itervalues(ps_renderer.used_characters):
11471139
if len(chars):
1148-
font = FT2Font(font_filename)
1140+
font = get_font(font_filename)
11491141
cmap = font.get_charmap()
11501142
glyph_ids = []
11511143
for c in chars:

‎lib/matplotlib/backends/backend_svg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_svg.py
+5-12Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
from matplotlib.cbook import is_string_like, is_writable_file_like, maxdict
2020
from matplotlib.colors import rgb2hex
2121
from matplotlib.figure import Figure
22-
from matplotlib.font_manager import findfont, FontProperties
23-
from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING
22+
from matplotlib.font_manager import findfont, FontProperties, get_font
23+
from matplotlib.ft2font import KERNING_DEFAULT, LOAD_NO_HINTING
2424
from matplotlib.mathtext import MathTextParser
2525
from matplotlib.path import Path
2626
from matplotlib import _path
@@ -326,15 +326,8 @@ def _make_flip_transform(self, transform):
326326
.translate(0.0, self.height))
327327

328328
def _get_font(self, prop):
329-
key = hash(prop)
330-
font = self.fontd.get(key)
331-
if font is None:
332-
fname = findfont(prop)
333-
font = self.fontd.get(fname)
334-
if font is None:
335-
font = FT2Font(fname)
336-
self.fontd[fname] = font
337-
self.fontd[key] = font
329+
fname = findfont(prop)
330+
font = get_font(fname)
338331
font.clear()
339332
size = prop.get_size_in_points()
340333
font.set_size(size, 72.0)
@@ -495,7 +488,7 @@ def _write_svgfonts(self):
495488
writer = self.writer
496489
writer.start('defs')
497490
for font_fname, chars in six.iteritems(self._fonts):
498-
font = FT2Font(font_fname)
491+
font = get_font(font_fname)
499492
font.set_size(72, 72)
500493
sfnt = font.get_sfnt()
501494
writer.start('font', id=sfnt[(1, 0, 0, 4)])

‎lib/matplotlib/font_manager.py

Copy file name to clipboardExpand all lines: lib/matplotlib/font_manager.py
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@
6363
from matplotlib.fontconfig_pattern import \
6464
parse_fontconfig_pattern, generate_fontconfig_pattern
6565

66+
try:
67+
from functools import lru_cache
68+
except ImportError:
69+
from functools32 import lru_cache
70+
71+
6672
USE_FONTCONFIG = False
6773
verbose = matplotlib.verbose
6874

@@ -733,7 +739,7 @@ def get_name(self):
733739
Return the name of the font that best matches the font
734740
properties.
735741
"""
736-
return ft2font.FT2Font(findfont(self)).family_name
742+
return get_font(findfont(self)).family_name
737743

738744
def get_style(self):
739745
"""
@@ -1316,7 +1322,6 @@ def findfont(self, prop, fontext='ttf', directory=None,
13161322
_lookup_cache[fontext].set(prop, result)
13171323
return result
13181324

1319-
13201325
_is_opentype_cff_font_cache = {}
13211326
def is_opentype_cff_font(filename):
13221327
"""
@@ -1337,6 +1342,10 @@ def is_opentype_cff_font(filename):
13371342
fontManager = None
13381343
_fmcache = None
13391344

1345+
1346+
get_font = lru_cache(64)(ft2font.FT2Font)
1347+
1348+
13401349
# The experimental fontconfig-based backend.
13411350
if USE_FONTCONFIG and sys.platform != 'win32':
13421351
import re

‎lib/matplotlib/mathtext.py

Copy file name to clipboardExpand all lines: lib/matplotlib/mathtext.py
+4-5Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@
5050
from matplotlib.afm import AFM
5151
from matplotlib.cbook import Bunch, get_realpath_and_stat, \
5252
is_string_like, maxdict
53-
from matplotlib.ft2font import FT2Font, FT2Image, KERNING_DEFAULT, LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING
54-
from matplotlib.font_manager import findfont, FontProperties
53+
from matplotlib.ft2font import FT2Image, KERNING_DEFAULT, LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING
54+
from matplotlib.font_manager import findfont, FontProperties, get_font
5555
from matplotlib._mathtext_data import latex_to_bakoma, \
5656
latex_to_standard, tex2uni, latex_to_cmex, stix_virtual_fonts
5757
from matplotlib import get_data_path, rcParams
@@ -563,7 +563,7 @@ def __init__(self, default_font_prop, mathtext_backend):
563563
self._fonts = {}
564564

565565
filename = findfont(default_font_prop)
566-
default_font = self.CachedFont(FT2Font(filename))
566+
default_font = self.CachedFont(get_font(filename))
567567
self._fonts['default'] = default_font
568568
self._fonts['regular'] = default_font
569569

@@ -576,10 +576,9 @@ def _get_font(self, font):
576576
basename = self.fontmap[font]
577577
else:
578578
basename = font
579-
580579
cached_font = self._fonts.get(basename)
581580
if cached_font is None and os.path.exists(basename):
582-
font = FT2Font(basename)
581+
font = get_font(basename)
583582
cached_font = self.CachedFont(font)
584583
self._fonts[basename] = cached_font
585584
self._fonts[font.postscript_name] = cached_font

‎lib/matplotlib/tests/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/__init__.py
-6Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,6 @@ def setup():
4949
rcParams['text.hinting'] = False
5050
rcParams['text.hinting_factor'] = 8
5151

52-
# Clear the font caches. Otherwise, the hinting mode can travel
53-
# from one test to another.
54-
backend_agg.RendererAgg._fontd.clear()
55-
backend_pdf.RendererPdf.truetype_font_cache.clear()
56-
backend_svg.RendererSVG.fontd.clear()
57-
5852

5953
def assert_str_equal(reference_str, test_str,
6054
format_str=('String {str1} and {str2} do not '

‎lib/matplotlib/textpath.py

Copy file name to clipboardExpand all lines: lib/matplotlib/textpath.py
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
from matplotlib.path import Path
1414
from matplotlib import rcParams
1515
import matplotlib.font_manager as font_manager
16-
from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING
16+
from matplotlib.ft2font import KERNING_DEFAULT, LOAD_NO_HINTING
1717
from matplotlib.ft2font import LOAD_TARGET_LIGHT
1818
from matplotlib.mathtext import MathTextParser
1919
import matplotlib.dviread as dviread
20-
from matplotlib.font_manager import FontProperties
20+
from matplotlib.font_manager import FontProperties, get_font
2121
from matplotlib.transforms import Affine2D
2222
from matplotlib.externals.six.moves.urllib.parse import quote as urllib_quote
2323

@@ -54,7 +54,7 @@ def _get_font(self, prop):
5454
find a ttf font.
5555
"""
5656
fname = font_manager.findfont(prop)
57-
font = FT2Font(fname)
57+
font = get_font(fname)
5858
font.set_size(self.FONT_SCALE, self.DPI)
5959

6060
return font
@@ -336,7 +336,7 @@ def get_glyphs_tex(self, prop, s, glyph_map=None,
336336
font_bunch = self.tex_font_map[dvifont.texname]
337337

338338
if font_and_encoding is None:
339-
font = FT2Font(font_bunch.filename)
339+
font = get_font(font_bunch.filename)
340340

341341
for charmap_name, charmap_code in [("ADOBE_CUSTOM",
342342
1094992451),

‎lib/mpl_toolkits/tests/__init__.py

Copy file name to clipboardExpand all lines: lib/mpl_toolkits/tests/__init__.py
-6Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,6 @@ def setup():
4949
rcParams['text.hinting'] = False
5050
rcParams['text.hinting_factor'] = 8
5151

52-
# Clear the font caches. Otherwise, the hinting mode can travel
53-
# from one test to another.
54-
backend_agg.RendererAgg._fontd.clear()
55-
backend_pdf.RendererPdf.truetype_font_cache.clear()
56-
backend_svg.RendererSVG.fontd.clear()
57-
5852

5953
def assert_str_equal(reference_str, test_str,
6054
format_str=('String {str1} and {str2} do not '

‎setup.py

Copy file name to clipboardExpand all lines: setup.py
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
'Required dependencies and extensions',
6868
setupext.Numpy(),
6969
setupext.Dateutil(),
70+
setupext.FuncTools32(),
7071
setupext.Pytz(),
7172
setupext.Cycler(),
7273
setupext.Tornado(),

‎setupext.py

Copy file name to clipboardExpand all lines: setupext.py
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,29 @@ def get_install_requires(self):
12211221
return [dateutil]
12221222

12231223

1224+
class FuncTools32(SetupPackage):
1225+
name = "functools32"
1226+
1227+
def check(self):
1228+
if sys.version_info[:2] < (3, 2):
1229+
try:
1230+
import functools32
1231+
except ImportError:
1232+
return (
1233+
"functools32 was not found. It is required for for"
1234+
"python versions prior to 3.2")
1235+
1236+
return "using functools32"
1237+
else:
1238+
return "Not required"
1239+
1240+
def get_install_requires(self):
1241+
if sys.version_info[:2] < (3, 2):
1242+
return ['functools32']
1243+
else:
1244+
return []
1245+
1246+
12241247
class Tornado(OptionalPackage):
12251248
name = "tornado"
12261249

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.