Skip to content

Delay the fc-list warning by 5 seconds #7532

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/matplotlib/compat/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
else:
import subprocess

__all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError']
__all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError', 'TimeoutExpired']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be line-wrapped ❤️ pep8



if hasattr(subprocess, 'Popen'):
Expand All @@ -36,6 +36,7 @@
STDOUT = subprocess.STDOUT
CalledProcessError = subprocess.CalledProcessError
check_output = subprocess.check_output
TimeoutExpired = subprocess.TimeoutExpired
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work on python2 unless subprocess32 is installed.

Python 2.7.12 (default, Nov  7 2016, 11:55:55) 
[GCC 6.2.1 20160830] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.TimeoutExpired
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'TimeoutExpired'
>>> 

This looks like it is working on travis because subprocess32 in an install require (not a run-time require) so it is always getting installed on travis. I think that there is a way to install mpl such that this will fail.

else:
# In restricted environments (such as Google App Engine), these are
# non-existent. Replace them with dummy versions that always raise OSError.
Expand All @@ -49,3 +50,4 @@ def check_output(*args, **kwargs):
# There is no need to catch CalledProcessError. These stubs cannot raise
# it. None in an except clause will simply not match any exceptions.
CalledProcessError = None
TimeoutExpired = None
19 changes: 17 additions & 2 deletions lib/matplotlib/font_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,26 @@ def get_fontconfig_fonts(fontext='ttf'):

fontfiles = {}
try:
warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')
pipe = subprocess.Popen(['fc-list', '--format=%{file}\\n'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output = pipe.communicate()[0]
# We emit a warning if the process has not completed after 5 seconds.
# We avoid showing it before since if this takes < 5 seconds, the user
# probably won't notice. However, this only works on Python 3 because
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subprocess32 doesn't have this? It is only an optional requirement, but that means that if people read our installation file (…), it'll work for 2.7

# the timeout keyword argument for communicate is not implemented in 2.

message = ('Matplotlib is building the font cache using fc-list. '
'This may take a moment.')

if six.PY2:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't test for python2 but for whether subprocess has the attribute TimeoutExpired here:

hasattr(subprocess, TimeoutExpired)

subprocess32 being an optional dependency, that may work for python2.7.

warnings.warn(message)
output = pipe.communicate()[0]
else:
try:
output = pipe.communicate(timeout=5)[0]
except subprocess.TimeoutExpired:
warnings.warn(message)
output = pipe.communicate()[0]
except (OSError, IOError):
# Calling fc-list did not work, so we'll just return nothing
return fontfiles
Expand Down