Skip to content

Commit f0e270c

Browse files
committed
Fix exception handling in FT2Font init.
It needs to return -1 when an exception is set, or Python raises a `SystemError` instead.
1 parent 49593b7 commit f0e270c

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

lib/matplotlib/tests/test_font_manager.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from io import BytesIO
1+
from io import BytesIO, StringIO
22
import multiprocessing
33
import os
44
from pathlib import Path
@@ -128,6 +128,24 @@ def test_find_ttc():
128128
fig.savefig(BytesIO(), format="ps")
129129

130130

131+
def test_find_invalid(tmpdir):
132+
tmp_path = Path(tmpdir)
133+
134+
with pytest.raises(FileNotFoundError):
135+
get_font(tmp_path / 'non-existent-font-name.ttf')
136+
137+
with pytest.raises(FileNotFoundError):
138+
get_font(str(tmp_path / 'non-existent-font-name.ttf'))
139+
140+
with pytest.raises(FileNotFoundError):
141+
get_font(bytes(tmp_path / 'non-existent-font-name.ttf'))
142+
143+
# Not really public, but get_font doesn't expose non-filename constructor.
144+
from matplotlib.ft2font import FT2Font
145+
with pytest.raises(TypeError, match='path or binary-mode file'):
146+
FT2Font(StringIO())
147+
148+
131149
@pytest.mark.skipif(sys.platform != 'linux', reason='Linux only')
132150
def test_user_fonts_linux(tmpdir, monkeypatch):
133151
font_test_file = 'mpltest.ttf'

src/ft2font_wrapper.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ static int PyFT2Font_init(PyFT2Font *self, PyObject *args, PyObject *kwds)
461461
long hinting_factor = 8;
462462
int kerning_factor = 0;
463463
const char *names[] = { "filename", "hinting_factor", "_kerning_factor", NULL };
464+
int ret = 0;
464465

465466
if (!PyArg_ParseTupleAndKeywords(
466467
args, kwds, "O|l$i:FT2Font", (char **)names, &filename,
@@ -480,6 +481,7 @@ static int PyFT2Font_init(PyFT2Font *self, PyObject *args, PyObject *kwds)
480481
if (PyBytes_Check(filename) || PyUnicode_Check(filename)) {
481482
if (!(open = PyDict_GetItemString(PyEval_GetBuiltins(), "open")) // Borrowed reference.
482483
|| !(self->py_file = PyObject_CallFunction(open, "Os", filename, "rb"))) {
484+
ret = -1;
483485
goto exit;
484486
}
485487
self->stream.close = &close_file_callback;
@@ -488,12 +490,14 @@ static int PyFT2Font_init(PyFT2Font *self, PyObject *args, PyObject *kwds)
488490
|| !PyBytes_Check(data)) {
489491
PyErr_SetString(PyExc_TypeError,
490492
"First argument must be a path or binary-mode file object");
493+
ret = -1;
491494
goto exit;
492495
} else {
493496
self->py_file = filename;
494497
self->stream.close = NULL;
495498
Py_INCREF(filename);
496499
}
500+
Py_CLEAR(data);
497501

498502
CALL_CPP_FULL(
499503
"FT2Font", (self->x = new FT2Font(open_args, hinting_factor)),
@@ -507,7 +511,7 @@ static int PyFT2Font_init(PyFT2Font *self, PyObject *args, PyObject *kwds)
507511
exit:
508512
Py_XDECREF(data);
509513

510-
return 0;
514+
return ret;
511515
}
512516

513517
static void PyFT2Font_dealloc(PyFT2Font *self)

0 commit comments

Comments
 (0)