From 2a90d9519d4d1d9cc3810456e988b6b8c58d639e Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 29 Nov 2016 20:28:00 +0000 Subject: [PATCH 1/4] Delay the fc-list warning by 5 seconds --- lib/matplotlib/font_manager.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index f9cfb1600cb6..0c1ad4d291de 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -273,11 +273,17 @@ 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. + try: + output = pipe.communicate(timeout=5)[0] + except subprocess.TimeoutExpired: + warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.') + output = pipe.communicate()[0] except (OSError, IOError): # Calling fc-list did not work, so we'll just return nothing return fontfiles From b1bf847c67ecddb3363d18d78cbaf4b6739016ed Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 29 Nov 2016 20:42:26 +0000 Subject: [PATCH 2/4] Make sure TimeoutExpired is defined --- lib/matplotlib/compat/subprocess.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/compat/subprocess.py b/lib/matplotlib/compat/subprocess.py index 6607a011836e..0c2848d62cb7 100644 --- a/lib/matplotlib/compat/subprocess.py +++ b/lib/matplotlib/compat/subprocess.py @@ -26,7 +26,7 @@ else: import subprocess -__all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError'] +__all__ = ['Popen', 'PIPE', 'STDOUT', 'check_output', 'CalledProcessError', 'TimeoutExpired'] if hasattr(subprocess, 'Popen'): @@ -36,6 +36,7 @@ STDOUT = subprocess.STDOUT CalledProcessError = subprocess.CalledProcessError check_output = subprocess.check_output + TimeoutExpired = subprocess.TimeoutExpired else: # In restricted environments (such as Google App Engine), these are # non-existent. Replace them with dummy versions that always raise OSError. @@ -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 From 5ac3d369a5e43a617634a3a5c5c1159a26a9c566 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 30 Nov 2016 22:34:34 +0000 Subject: [PATCH 3/4] Only show the warning after a 5-second delay on Python 3 --- lib/matplotlib/font_manager.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 0c1ad4d291de..5dfa06eefc11 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -278,12 +278,19 @@ def get_fontconfig_fonts(fontext='ttf'): stderr=subprocess.PIPE) # 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. - try: - output = pipe.communicate(timeout=5)[0] - except subprocess.TimeoutExpired: - warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.') + # probably won't notice. However, this only works on Python 3 because + # the timeout keyword argument for communicate is not implemented in 2. + if six.PY2: + warnings.warn('Matplotlib is building the font cache using fc-list. ' + 'This may take a moment.') output = pipe.communicate()[0] + else: + try: + output = pipe.communicate(timeout=5)[0] + except subprocess.TimeoutExpired: + warnings.warn('Matplotlib is building the font cache using ' + 'fc-list. This may take a moment.') + output = pipe.communicate()[0] except (OSError, IOError): # Calling fc-list did not work, so we'll just return nothing return fontfiles From e13d9dbb7c54089a4bdeaab060afdbd15af922a6 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 30 Nov 2016 23:37:44 +0000 Subject: [PATCH 4/4] Avoid duplicate message --- lib/matplotlib/font_manager.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 5dfa06eefc11..bd2ac009337f 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -280,16 +280,18 @@ def get_fontconfig_fonts(fontext='ttf'): # 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 # 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: - warnings.warn('Matplotlib is building the font cache using fc-list. ' - 'This may take a moment.') + warnings.warn(message) output = pipe.communicate()[0] else: try: output = pipe.communicate(timeout=5)[0] except subprocess.TimeoutExpired: - warnings.warn('Matplotlib is building the font cache using ' - 'fc-list. This may take a moment.') + warnings.warn(message) output = pipe.communicate()[0] except (OSError, IOError): # Calling fc-list did not work, so we'll just return nothing