Skip to content

Commit 63f2914

Browse files
committed
Raise an exception when find_tex_file fails to find a file.
The exception message is clearer for end users than downstream callers failing to `open()` a file named `""`. Also update the function's docstring. _tfmfile now never returns None (an exception would have been raised earlier by find_tex_file), so remove the corresponding branch.
1 parent 97ba9d4 commit 63f2914

File tree

3 files changed

+59
-42
lines changed

3 files changed

+59
-42
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``dviread.find_tex_file`` raises ``FileNotFoundError`` for missing files
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, it would return an empty string in such cases. Raising an
4+
exception allows attaching a user-friendly message instead.

lib/matplotlib/dviread.py

+50-41
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,6 @@ def _fnt_def_real(self, k, c, s, d, a, l):
470470
n = self.file.read(a + l)
471471
fontname = n[-l:].decode('ascii')
472472
tfm = _tfmfile(fontname)
473-
if tfm is None:
474-
raise FileNotFoundError("missing font metrics file: %s" % fontname)
475473
if c != 0 and tfm.checksum != 0 and c != tfm.checksum:
476474
raise ValueError('tfm checksum mismatch: %s' % n)
477475

@@ -992,21 +990,20 @@ def search(self, filename):
992990
self._proc.stdin.write(os.fsencode(filename) + b"\n")
993991
self._proc.stdin.flush()
994992
out = self._proc.stdout.readline().rstrip()
995-
return "" if out == b"nil" else os.fsdecode(out)
993+
return None if out == b"nil" else os.fsdecode(out)
996994

997995

998996
@lru_cache()
999997
@_api.delete_parameter("3.5", "format")
1000998
def find_tex_file(filename, format=None):
1001999
"""
1002-
Find a file in the texmf tree.
1000+
Find a file in the texmf tree using kpathsea_.
10031001
1004-
Calls :program:`kpsewhich` which is an interface to the kpathsea
1005-
library [1]_. Most existing TeX distributions on Unix-like systems use
1006-
kpathsea. It is also available as part of MikTeX, a popular
1007-
distribution on Windows.
1002+
The kpathsea library, provided by most existing TeX distributions, both
1003+
on Unix-like systems and on Windows (MikTeX), is invoked via a long-lived
1004+
luatex process if luatex is installed, or via kpsewhich otherwise.
10081005
1009-
*If the file is not found, an empty string is returned*.
1006+
.. _kpathsea: http://www.tug.org/kpathsea/
10101007
10111008
Parameters
10121009
----------
@@ -1016,10 +1013,10 @@ def find_tex_file(filename, format=None):
10161013
Could be e.g. 'tfm' or 'vf' to limit the search to that type of files.
10171014
Deprecated.
10181015
1019-
References
1020-
----------
1021-
.. [1] `Kpathsea documentation <http://www.tug.org/kpathsea/>`_
1022-
The library that :program:`kpsewhich` is part of.
1016+
Raises
1017+
------
1018+
FileNotFoundError
1019+
If the file is not found.
10231020
"""
10241021

10251022
# we expect these to always be ascii encoded, but use utf-8
@@ -1029,39 +1026,51 @@ def find_tex_file(filename, format=None):
10291026
if isinstance(format, bytes):
10301027
format = format.decode('utf-8', errors='replace')
10311028

1032-
if format is None:
1033-
try:
1034-
lk = _LuatexKpsewhich()
1035-
except FileNotFoundError:
1036-
pass # Fallback to directly calling kpsewhich, as below.
1037-
else:
1038-
return lk.search(filename)
1039-
1040-
if os.name == 'nt':
1041-
# On Windows only, kpathsea can use utf-8 for cmd args and output.
1042-
# The `command_line_encoding` environment variable is set to force it
1043-
# to always use utf-8 encoding. See Matplotlib issue #11848.
1044-
kwargs = {'env': {**os.environ, 'command_line_encoding': 'utf-8'},
1045-
'encoding': 'utf-8'}
1046-
else: # On POSIX, run through the equivalent of os.fsdecode().
1047-
kwargs = {'encoding': sys.getfilesystemencoding(),
1048-
'errors': 'surrogatescape'}
1049-
1050-
cmd = ['kpsewhich']
1051-
if format is not None:
1052-
cmd += ['--format=' + format]
1053-
cmd += [filename]
10541029
try:
1055-
result = cbook._check_and_log_subprocess(cmd, _log, **kwargs)
1056-
except (FileNotFoundError, RuntimeError):
1057-
return ''
1058-
return result.rstrip('\n')
1030+
lk = _LuatexKpsewhich()
1031+
except FileNotFoundError:
1032+
lk = None # Fallback to directly calling kpsewhich, as below.
1033+
1034+
if lk and format is None:
1035+
path = lk.search(filename)
1036+
1037+
else:
1038+
if os.name == 'nt':
1039+
# On Windows only, kpathsea can use utf-8 for cmd args and output.
1040+
# The `command_line_encoding` environment variable is set to force
1041+
# it to always use utf-8 encoding. See Matplotlib issue #11848.
1042+
kwargs = {'env': {**os.environ, 'command_line_encoding': 'utf-8'},
1043+
'encoding': 'utf-8'}
1044+
else: # On POSIX, run through the equivalent of os.fsdecode().
1045+
kwargs = {'encoding': sys.getfilesystemencoding(),
1046+
'errors': 'surrogatescape'}
1047+
1048+
cmd = ['kpsewhich']
1049+
if format is not None:
1050+
cmd += ['--format=' + format]
1051+
cmd += [filename]
1052+
try:
1053+
path = (cbook._check_and_log_subprocess(cmd, _log, **kwargs)
1054+
.rstrip('\n'))
1055+
except (FileNotFoundError, RuntimeError):
1056+
path = None
1057+
1058+
if path:
1059+
return path
1060+
else:
1061+
raise FileNotFoundError(
1062+
f"Matplotlib's TeX implementation searched for a file named "
1063+
f"{filename!r} in your texmf tree, but could not find it")
10591064

10601065

10611066
@lru_cache()
10621067
def _fontfile(cls, suffix, texname):
1063-
filename = find_tex_file(texname + suffix)
1064-
return cls(filename) if filename else None
1068+
try:
1069+
filename = find_tex_file(texname + suffix)
1070+
except FileNotFoundError:
1071+
return None
1072+
else:
1073+
return cls(filename)
10651074

10661075

10671076
_tfmfile = partial(_fontfile, Tfm, ".tfm")

lib/matplotlib/testing/__init__.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,8 @@ def _check_for_pgf(texsystem):
7878

7979

8080
def _has_tex_package(package):
81-
return bool(mpl.dviread.find_tex_file(f"{package}.sty"))
81+
try:
82+
mpl.dviread.find_tex_file(f"{package}.sty")
83+
return True
84+
except FileNotFoundError:
85+
return False

0 commit comments

Comments
 (0)