diff --git a/doc/devel/contributing.rst b/doc/devel/contributing.rst
index 74449565fd94..e77e667b313a 100644
--- a/doc/devel/contributing.rst
+++ b/doc/devel/contributing.rst
@@ -171,7 +171,7 @@ repository `__ on GitHub,
then submit a "pull request" (PR).
The best practices for using GitHub to make PRs to Matplotlib are
-documented in the :ref:`development-workflow` section.
+documented in the :ref:`development-workflow` section.
A brief overview is:
@@ -437,6 +437,70 @@ forced to use ``**kwargs``. An example is
elif len(args) == 1:
...etc...
+.. _using_logging:
+
+Using logging for debug messages
+--------------------------------
+
+Matplotlib uses the standard python `logging` library to write verbose
+warnings, information, and
+debug messages. Please use it! In all those places you write :func:`print()`
+statements to do your debugging, try using :func:`log.debug()` instead!
+
+
+To include `logging` in your module, at the top of the module, you need to
+``import logging``. Then calls in your code like::
+
+ _log = logging.getLogger(__name__) # right after the imports
+
+ # code
+ # more code
+ _log.info('Here is some information')
+ _log.debug('Here is some more detailed information')
+
+will log to a logger named ``matplotlib.yourmodulename``.
+
+If an end-user of Matplotlib sets up `logging` to display at levels
+more verbose than `logger.WARNING` in their code as follows::
+
+ import logging
+ fmt = '%(name)s:%(lineno)5d - %(levelname)s - %(message)s'
+ logging.basicConfig(level=logging.DEBUG, format=fmt)
+ import matplotlib.pyplot as plt
+
+Then they will receive messages like::
+
+ matplotlib.backends: 89 - INFO - backend MacOSX version unknown
+ matplotlib.yourmodulename: 347 - INFO - Here is some information
+ matplotlib.yourmodulename: 348 - DEBUG - Here is some more detailed information
+
+Which logging level to use?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are five levels at which you can emit messages.
+`logging.critical` and `logging.error`
+are really only there for errors that will end the use of the library but
+not kill the interpreter. `logging.warning` overlaps with the
+``warnings`` library. The
+`logging tutorial `_
+suggests that the difference
+between `logging.warning` and `warnings.warn` is that
+`warnings.warn` be used for things the user must change to stop
+the warning, whereas `logging.warning` can be more persistent.
+
+By default, `logging` displays all log messages at levels higher than
+`logging.WARNING` to `sys.stderr`.
+
+Calls to `logging.info` are not displayed by default. They are for
+information that the user may want to know if the program behaves oddly.
+For instance, if an object isn't drawn because its position is ``NaN``,
+that can usually be ignored, but a mystified user could set
+``logging.basicConfig(level=logging.INFO)`` and get an error message that
+says why.
+
+`logging.debug` is the least likely to be displayed, and hence can
+be the most verbose.
+
.. _custom_backend:
Developing a new backend
diff --git a/doc/faq/troubleshooting_faq.rst b/doc/faq/troubleshooting_faq.rst
index 7074147c142b..3ceb9a578468 100644
--- a/doc/faq/troubleshooting_faq.rst
+++ b/doc/faq/troubleshooting_faq.rst
@@ -9,10 +9,10 @@ Troubleshooting
.. _matplotlib-version:
-Obtaining matplotlib version
+Obtaining Matplotlib version
============================
-To find out your matplotlib version number, import it and print the
+To find out your Matplotlib version number, import it and print the
``__version__`` attribute::
>>> import matplotlib
@@ -25,7 +25,7 @@ To find out your matplotlib version number, import it and print the
:file:`matplotlib` install location
===================================
-You can find what directory matplotlib is installed in by importing it
+You can find what directory Matplotlib is installed in by importing it
and printing the ``__file__`` attribute::
>>> import matplotlib
@@ -37,7 +37,7 @@ and printing the ``__file__`` attribute::
:file:`matplotlib` configuration and cache directory locations
==============================================================
-Each user has a matplotlib configuration directory which may contain a
+Each user has a Matplotlib configuration directory which may contain a
:ref:`matplotlibrc ` file. To
locate your :file:`matplotlib/` configuration directory, use
:func:`matplotlib.get_configdir`::
@@ -79,7 +79,7 @@ directory and the cache directory.
Getting help
============
-There are a number of good resources for getting help with matplotlib.
+There are a number of good resources for getting help with Matplotlib.
There is a good chance your question has already been asked:
- The `mailing list archive `_.
@@ -114,11 +114,35 @@ provide the following information in your e-mail to the `mailing list
the error will help you find a bug in *your* code that is causing the
problem.
-* You can get very helpful debugging output from matlotlib by running your
- script with a ``verbose-helpful`` or ``--verbose-debug`` flags and posting
- the verbose output the lists::
+* You can get helpful debugging output from Matlotlib by using the `logging`
+ library in your code and posting the verbose output to the lists. For a
+ command-line version of this, try::
- python simple_plot.py --verbose-helpful > output.txt
+ python -c "from logging import *; basicConfig(level=DEBUG); from pylab import *; plot(); show()"
+
+
+ If you want to put the debugging hooks in your own code, then the
+ most simple way to do so is to insert the following *before* any calls
+ to ``import matplotlib``::
+
+ import logging
+ logging.basicConfig(level=logging.DEBUG)
+
+ import matplotlib.pyplot as plt
+
+ Note that if you want to use `logging` in your own code, but do not
+ want verbose Matplotlib output, you can set the logging level
+ for Matplotlib independently::
+
+ import logging
+ # set DEBUG for everything
+ logging.basicConfig(level=logging.DEBUG)
+ logger = logging.getLogger('matplotlib')
+ # set WARNING for Matplotlib
+ logger.setLevel(logging.WARNING)
+
+ The `logging` module is very flexible, and can be a valuable tool in chasing
+ down errors.
If you compiled Matplotlib yourself, please also provide:
diff --git a/doc/users/next_whats_new/2017_10_10_logging.rst b/doc/users/next_whats_new/2017_10_10_logging.rst
new file mode 100644
index 000000000000..8013f2f165b5
--- /dev/null
+++ b/doc/users/next_whats_new/2017_10_10_logging.rst
@@ -0,0 +1,24 @@
+Logging for debug output
+------------------------
+
+Matplotlib has in the past (sporadically) used an internal
+verbose-output reporter. This version converts those calls to using the
+standard python `logging` library.
+
+Support for the old ``rcParams`` ``verbose.level`` and ``verbose.fileo`` is
+dropped.
+
+The command-line options ``--verbose-helpful`` and ``--verbose-debug`` are
+still accepted, but deprecated. They are now equivalent to setting
+``logging.INFO`` and ``logging.DEBUG``.
+
+The logger's root name is ``matplotlib`` and can be accessed from programs
+as::
+
+ import logging
+ mlog = logging.getLogger('matplotlib')
+
+Instructions for basic usage are in :ref:`troubleshooting-faq` and for
+developers in :ref:`contributing`.
+
+.. _logging: https://docs.python.org/3/library/logging.html
diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 659d2a2ea846..b3935f75a4a7 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -113,6 +113,7 @@
import inspect
import itertools
import locale
+import logging
import os
import re
import sys
@@ -137,6 +138,8 @@
__version__ = str(get_versions()['version'])
del get_versions
+_log = logging.getLogger(__name__)
+
__version__numpy__ = str('1.7.1') # minimum required numpy version
__bibtex__ = r"""@Article{Hunter:2007,
@@ -160,6 +163,9 @@
if not (_python27 or _python34):
raise ImportError("Matplotlib requires Python 2.7 or 3.4 or later")
+if _python27:
+ _log.addHandler(logging.NullHandler())
+
def compare_versions(a, b):
"return True if a is greater than or equal to b"
@@ -215,7 +221,75 @@ def _is_writable_dir(p):
"""
return os.access(p, os.W_OK) and os.path.isdir(p)
+_verbose_msg = """\
+Command line argument --verbose-LEVEL is deprecated.
+This functionality is now provided by the standard
+python logging library. To get more (or less) logging output:
+ import logging
+ logger = logging.getLogger('matplotlib')
+ logger.set_level(logging.INFO)"""
+
+
+def _set_logger_verbose_level(level_str='silent', file_str='sys.stdout'):
+ """
+ Use a --verbose-LEVEL level to set the logging level:
+
+ """
+ levelmap = {'silent': logging.WARNING, 'helpful': logging.INFO,
+ 'debug': logging.DEBUG, 'debug-annoying': logging.DEBUG,
+ 'info': logging.INFO, 'warning': logging.WARNING}
+ # Check that current state of logger isn't already more verbose
+ # than the requested level. If it is more verbose, then leave more
+ # verbose.
+ newlev = levelmap[level_str]
+ oldlev = _log.getEffectiveLevel()
+ if newlev < oldlev:
+ _log.setLevel(newlev)
+ std = {
+ 'sys.stdout': sys.stdout,
+ 'sys.stderr': sys.stderr,
+ }
+ if file_str in std:
+ fileo = std[file_str]
+ else:
+ fileo = sys.stdout
+ try:
+ fileo = open(file_str, 'w')
+ # if this fails, we will just write to stdout
+ except IOError:
+ warnings.warn('could not open log file "{0}"'
+ 'for writing. Check your '
+ 'matplotlibrc'.format(file_str))
+ console = logging.StreamHandler(fileo)
+ console.setLevel(newlev)
+ _log.addHandler(console)
+
+
+def _parse_commandline():
+ """
+ Check for --verbose-LEVEL type command line arguments and
+ set logging level appropriately.
+ """
+ levels = ('silent', 'helpful', 'debug', 'debug-annoying',
+ 'info', 'warning')
+
+ for arg in sys.argv[1:]:
+ # cast to str because we are using unicode_literals,
+ # and argv is always str
+
+ if arg.startswith(str('--verbose-')):
+ level_str = arg[10:]
+ # If it doesn't match one of ours, then don't even
+ # bother noting it, we are just a 3rd-party library
+ # to somebody else's script.
+ if level_str in levels:
+ _set_logger_verbose_level(level_str)
+
+_parse_commandline()
+
+
+@cbook.deprecated("2.2", message=_verbose_msg)
class Verbose(object):
"""
A class to handle reporting. Set the fileo attribute to any file
@@ -311,7 +385,29 @@ def ge(self, level):
return self.vald[self.level] >= self.vald[level]
-verbose = Verbose()
+def _wrap(fmt, func, level='INFO', always=True):
+ """
+ return a callable function that wraps func and reports its
+ output through logger
+
+ if always is True, the report will occur on every function
+ call; otherwise only on the first time the function is called
+ """
+ assert callable(func)
+
+ def wrapper(*args, **kwargs):
+ ret = func(*args, **kwargs)
+
+ if (always or not wrapper._spoke):
+ lvl = logging.getLevelName(level.upper())
+ _log.log(lvl, fmt % ret)
+ spoke = True
+ if not wrapper._spoke:
+ wrapper._spoke = spoke
+ return ret
+ wrapper._spoke = False
+ wrapper.__doc__ = func.__doc__
+ return wrapper
def checkdep_dvipng():
@@ -512,7 +608,7 @@ def _create_tmp_config_dir():
return configdir
-get_home = verbose.wrap('$HOME=%s', _get_home, always=False)
+get_home = _wrap('$HOME=%s', _get_home, always=False)
def _get_xdg_config_dir():
@@ -601,7 +697,7 @@ def _get_configdir():
"""
return _get_config_or_cache_dir(_get_xdg_config_dir())
-get_configdir = verbose.wrap('CONFIGDIR=%s', _get_configdir, always=False)
+get_configdir = _wrap('CONFIGDIR=%s', _get_configdir, always=False)
def _get_cachedir():
@@ -613,7 +709,7 @@ def _get_cachedir():
"""
return _get_config_or_cache_dir(_get_xdg_cache_dir())
-get_cachedir = verbose.wrap('CACHEDIR=%s', _get_cachedir, always=False)
+get_cachedir = _wrap('CACHEDIR=%s', _get_cachedir, always=False)
def _decode_filesystem_path(path):
@@ -671,8 +767,8 @@ def _get_data_path_cached():
defaultParams['datapath'][0] = _get_data_path()
return defaultParams['datapath'][0]
-get_data_path = verbose.wrap('matplotlib data path %s', _get_data_path_cached,
- always=False)
+get_data_path = _wrap('matplotlib data path %s', _get_data_path_cached,
+ always=False)
def get_py2exe_datafiles():
@@ -1035,22 +1131,18 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
if key not in _all_deprecated])
config.update(config_from_file)
- verbose.set_level(config['verbose.level'])
- verbose.set_fileo(config['verbose.fileo'])
-
if config['datapath'] is None:
config['datapath'] = get_data_path()
if "".join(config['text.latex.preamble']):
- verbose.report("""
+ _log.info("""
*****************************************************************
You have the following UNSUPPORTED LaTeX preamble customizations:
%s
Please do not ask for support with these customizations active.
*****************************************************************
-""" % '\n'.join(config['text.latex.preamble']), 'helpful')
-
- verbose.report('loaded rc file %s' % fname)
+""", '\n'.join(config['text.latex.preamble']))
+ _log.info('loaded rc file %s', fname)
return config
@@ -1736,9 +1828,7 @@ def inner(ax, *args, **kwargs):
return inner
return param
-
-verbose.report('matplotlib version %s' % __version__)
-verbose.report('verbose.level %s' % verbose.level)
-verbose.report('interactive is %s' % is_interactive())
-verbose.report('platform is %s' % sys.platform)
-verbose.report('loaded modules: %s' % list(sys.modules), 'debug')
+_log.info('matplotlib version %s', __version__)
+_log.info('interactive is %s', is_interactive())
+_log.info('platform is %s', sys.platform)
+_log.debug('loaded modules: %s', list(sys.modules))
diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py
index 8cd6b410b4f3..ddd337dccd84 100644
--- a/lib/matplotlib/animation.py
+++ b/lib/matplotlib/animation.py
@@ -39,17 +39,20 @@
import tempfile
import uuid
import warnings
+import logging
+
from matplotlib._animation_data import (DISPLAY_TEMPLATE, INCLUDED_FRAMES,
JS_INCLUDE)
from matplotlib.cbook import iterable, deprecated
from matplotlib.compat import subprocess
-from matplotlib import verbose
from matplotlib import rcParams, rcParamsDefault, rc_context
if sys.version_info < (3, 0):
from cStringIO import StringIO as InMemory
else:
from io import BytesIO as InMemory
+_log = logging.getLogger(__name__)
+
# Process creation flag for subprocess to prevent it raising a terminal
# window. See for example:
# https://stackoverflow.com/questions/24130623/using-python-subprocess-popen-cant-prevent-exe-stopped-working-prompt
@@ -319,13 +322,11 @@ def _adjust_frame_size(self):
w, h = adjusted_figsize(wo, ho, self.dpi, 2)
if not (wo, ho) == (w, h):
self.fig.set_size_inches(w, h, forward=True)
- verbose.report('figure size (inches) has been adjusted '
- 'from %s x %s to %s x %s' % (wo, ho, w, h),
- level='helpful')
+ _log.info('figure size (inches) has been adjusted '
+ 'from %s x %s to %s x %s', wo, ho, w, h)
else:
w, h = self.fig.get_size_inches()
- verbose.report('frame size in pixels is %s x %s' % self.frame_size,
- level='debug')
+ _log.debug('frame size in pixels is %s x %s' % self.frame_size)
return w, h
def setup(self, fig, outfile, dpi=None):
@@ -358,11 +359,8 @@ def _run(self):
# movie file. *args* returns the sequence of command line arguments
# from a few configuration options.
command = self._args()
- if verbose.ge('debug'):
- output = sys.stdout
- else:
- output = subprocess.PIPE
- verbose.report('MovieWriter.run: running command: %s' %
+ output = subprocess.PIPE
+ _log.info('MovieWriter.run: running command: %s',
' '.join(command))
self._proc = subprocess.Popen(command, shell=False,
stdout=output, stderr=output,
@@ -380,8 +378,7 @@ def grab_frame(self, **savefig_kwargs):
All keyword arguments in savefig_kwargs are passed on to the `savefig`
command that saves the figure.
'''
- verbose.report('MovieWriter.grab_frame: Grabbing frame.',
- level='debug')
+ _log.debug('MovieWriter.grab_frame: Grabbing frame.')
try:
# re-adjust the figure size in case it has been changed by the
# user. We must ensure that every frame is the same size or
@@ -393,12 +390,12 @@ def grab_frame(self, **savefig_kwargs):
dpi=self.dpi, **savefig_kwargs)
except (RuntimeError, IOError) as e:
out, err = self._proc.communicate()
- verbose.report('MovieWriter -- Error '
- 'running proc:\n%s\n%s' % (out, err),
- level='helpful')
+ _log.info('MovieWriter -- Error '
+ 'running proc:\n%s\n%s' % (out, err))
raise IOError('Error saving animation to file (cause: {0}) '
'Stdout: {1} StdError: {2}. It may help to re-run '
- 'with --verbose-debug.'.format(e, out, err))
+ 'with logging level set to '
+ 'DEBUG.'.format(e, out, err))
def _frame_sink(self):
'''Returns the place to which frames should be written.'''
@@ -412,10 +409,10 @@ def cleanup(self):
'''Clean-up and collect the process used to write the movie file.'''
out, err = self._proc.communicate()
self._frame_sink().close()
- verbose.report('MovieWriter -- '
- 'Command stdout:\n%s' % out, level='debug')
- verbose.report('MovieWriter -- '
- 'Command stderr:\n%s' % err, level='debug')
+ _log.debug('MovieWriter -- '
+ 'Command stdout:\n%s' % out)
+ _log.debug('MovieWriter -- '
+ 'Command stderr:\n%s' % err)
@classmethod
def bin_path(cls):
@@ -524,10 +521,9 @@ def _frame_sink(self):
# Save the filename so we can delete it later if necessary
self._temp_names.append(fname)
- verbose.report(
+ _log.debug(
'FileMovieWriter.frame_sink: saving frame %d to fname=%s' %
- (self._frame_counter, fname),
- level='debug')
+ (self._frame_counter, fname))
self._frame_counter += 1 # Ensures each created name is 'unique'
# This file returned here will be closed once it's used by savefig()
@@ -541,8 +537,7 @@ def grab_frame(self, **savefig_kwargs):
command that saves the figure.
'''
# Overloaded to explicitly close temp file.
- verbose.report('MovieWriter.grab_frame: Grabbing frame.',
- level='debug')
+ _log.debug('MovieWriter.grab_frame: Grabbing frame.')
try:
# Tell the figure to save its data to the sink, using the
# frame format and dpi.
@@ -552,9 +547,8 @@ def grab_frame(self, **savefig_kwargs):
except RuntimeError:
out, err = self._proc.communicate()
- verbose.report('MovieWriter -- Error '
- 'running proc:\n%s\n%s' % (out,
- err), level='helpful')
+ _log.info('MovieWriter -- Error '
+ 'running proc:\n%s\n%s' % (out, err))
raise
def finish(self):
@@ -569,15 +563,12 @@ def finish(self):
try:
stdout = [s.decode() for s in self._proc._stdout_buff]
stderr = [s.decode() for s in self._proc._stderr_buff]
- verbose.report("MovieWriter.finish: stdout: %s" % stdout,
- level='helpful')
- verbose.report("MovieWriter.finish: stderr: %s" % stderr,
- level='helpful')
+ _log.info("MovieWriter.finish: stdout: %s", stdout)
+ _log.info("MovieWriter.finish: stderr: %s", stderr)
except Exception as e:
pass
msg = ('Error creating movie, return code: ' +
- str(self._proc.returncode) +
- ' Try setting mpl.verbose.set_level("helpful")')
+ str(self._proc.returncode))
raise RuntimeError(msg)
def cleanup(self):
@@ -585,10 +576,9 @@ def cleanup(self):
# Delete temporary files
if self.clear_temp:
- verbose.report(
+ _log.debug(
'MovieWriter: clearing temporary fnames=%s' %
- str(self._temp_names),
- level='debug')
+ str(self._temp_names))
for fname in self._temp_names:
os.remove(fname)
@@ -650,7 +640,8 @@ def _args(self):
'-s', '%dx%d' % self.frame_size, '-pix_fmt', self.frame_format,
'-r', str(self.fps)]
# Logging is quieted because subprocess.PIPE has limited buffer size.
- if not verbose.ge('debug'):
+
+ if (_log.getEffectiveLevel() < logging.DEBUG):
args += ['-loglevel', 'quiet']
args += ['-i', 'pipe:'] + self.output_args
return args
@@ -933,7 +924,7 @@ def __init__(self, fps=30, codec=None, bitrate=None, extra_args=None,
if self.default_mode not in ['loop', 'once', 'reflect']:
self.default_mode = 'loop'
- warnings.warn("unrecognized default_mode: using 'loop'")
+ _log.warning("unrecognized default_mode: using 'loop'")
self._saved_frames = []
self._total_bytes = 0
@@ -969,7 +960,7 @@ def grab_frame(self, **savefig_kwargs):
imgdata64 = encodebytes(f.getvalue()).decode('ascii')
self._total_bytes += len(imgdata64)
if self._total_bytes >= self._bytes_limit:
- warnings.warn("Animation size has reached {0._total_bytes} "
+ _log.warning("Animation size has reached {0._total_bytes} "
"bytes, exceeding the limit of "
"{0._bytes_limit}. If you're sure you want "
"a larger animation embedded, set the "
@@ -1220,7 +1211,7 @@ class to use, such as 'ffmpeg' or 'mencoder'. If ``None``,
extra_args=extra_args,
metadata=metadata)
else:
- warnings.warn("MovieWriter %s unavailable" % writer)
+ _log.warning("MovieWriter %s unavailable" % writer)
try:
writer = writers[writers.list()[0]](fps, codec, bitrate,
@@ -1230,12 +1221,10 @@ class to use, such as 'ffmpeg' or 'mencoder'. If ``None``,
raise ValueError("Cannot save animation: no writers are "
"available. Please install "
"ffmpeg to save animations.")
-
- verbose.report('Animation.save using %s' % type(writer),
- level='helpful')
+ _log.info('Animation.save using %s', type(writer))
if 'bbox_inches' in savefig_kwargs:
- warnings.warn("Warning: discarding the 'bbox_inches' argument in "
+ _log.warning("Warning: discarding the 'bbox_inches' argument in "
"'savefig_kwargs' as it may cause frame size "
"to vary, which is inappropriate for animation.")
savefig_kwargs.pop('bbox_inches')
@@ -1248,10 +1237,9 @@ class to use, such as 'ffmpeg' or 'mencoder'. If ``None``,
# allow for this non-existent use case or find a way to make it work.
with rc_context():
if rcParams['savefig.bbox'] == 'tight':
- verbose.report("Disabling savefig.bbox = 'tight', as it "
+ _log.info("Disabling savefig.bbox = 'tight', as it "
"may cause frame size to vary, which "
- "is inappropriate for animation.",
- level='helpful')
+ "is inappropriate for animation.")
rcParams['savefig.bbox'] = None
with writer.saving(self._fig, filename, dpi):
for anim in all_anim:
@@ -1422,7 +1410,7 @@ def to_html5_video(self, embed_limit=None):
vid64 = encodebytes(video.read())
vid_len = len(vid64)
if vid_len >= embed_limit:
- warnings.warn("Animation movie is {} bytes, exceeding "
+ _log.warning("Animation movie is {} bytes, exceeding "
"the limit of {}. If you're sure you want a "
"large animation embedded, set the "
"animation.embed_limit rc parameter to a "
diff --git a/lib/matplotlib/backends/__init__.py b/lib/matplotlib/backends/__init__.py
index c2b29d474d8d..f74eabb95cbc 100644
--- a/lib/matplotlib/backends/__init__.py
+++ b/lib/matplotlib/backends/__init__.py
@@ -7,7 +7,9 @@
import inspect
import traceback
import warnings
+import logging
+_log = logging.getLogger(__name__)
backend = matplotlib.get_backend()
_backend_loading_tb = "".join(
@@ -85,8 +87,7 @@ def do_nothing(*args, **kwargs):
draw_if_interactive = getattr(backend_mod, 'draw_if_interactive',
do_nothing)
- matplotlib.verbose.report('backend %s version %s' %
- (name, backend_version))
+ _log.info('backend %s version %s' % (name, backend_version))
# need to keep a global reference to the backend for compatibility
# reasons. See https://github.com/matplotlib/matplotlib/issues/6092
diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py
index fc5a2866f438..1d867fea8914 100644
--- a/lib/matplotlib/backends/backend_agg.py
+++ b/lib/matplotlib/backends/backend_agg.py
@@ -28,7 +28,7 @@
import numpy as np
from collections import OrderedDict
from math import radians, cos, sin
-from matplotlib import verbose, rcParams, __version__
+from matplotlib import rcParams, __version__
from matplotlib.backend_bases import (
_Backend, FigureCanvasBase, FigureManagerBase, RendererBase, cursors)
from matplotlib.figure import Figure
diff --git a/lib/matplotlib/backends/backend_gtk.py b/lib/matplotlib/backends/backend_gtk.py
index ec2d3a6a609d..ba62b1c4e208 100644
--- a/lib/matplotlib/backends/backend_gtk.py
+++ b/lib/matplotlib/backends/backend_gtk.py
@@ -3,7 +3,10 @@
import six
-import os, sys, warnings
+import logging
+import os
+import sys
+import warnings
if six.PY3:
warnings.warn(
@@ -38,7 +41,9 @@
from matplotlib.widgets import SubplotTool
from matplotlib import (
- cbook, colors as mcolors, lines, markers, rcParams, verbose)
+ cbook, colors as mcolors, lines, markers, rcParams)
+
+_log = logging.getLogger(__name__)
backend_version = "%d.%d.%d" % gtk.pygtk_version
@@ -512,7 +517,8 @@ def __init__(self, canvas, num):
# all, so I am not sure how to catch it. I am unhappy
# diong a blanket catch here, but an not sure what a
# better way is - JDH
- verbose.report('Could not load matplotlib icon: %s' % sys.exc_info()[1])
+ _log.info('Could not load matplotlib '
+ 'icon: %s', sys.exc_info()[1])
self.vbox = gtk.VBox()
self.window.add(self.vbox)
@@ -997,7 +1003,7 @@ def on_dialog_lineprops_cancelbutton_clicked(self, button):
window_icon = os.path.join(rcParams['datapath'], 'images', icon_filename)
except:
window_icon = None
- verbose.report('Could not load matplotlib icon: %s' % sys.exc_info()[1])
+ _log.info('Could not load matplotlib icon: %s', sys.exc_info()[1])
def error_msg_gtk(msg, parent=None):
if parent is not None: # find the toplevel gtk.Window
diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py
index 16800bcbca52..0500f52c2bf9 100644
--- a/lib/matplotlib/backends/backend_gtk3.py
+++ b/lib/matplotlib/backends/backend_gtk3.py
@@ -3,7 +3,9 @@
import six
-import os, sys
+import logging
+import os
+import sys
try:
import gi
@@ -37,7 +39,9 @@
from matplotlib.widgets import SubplotTool
from matplotlib import (
- backend_tools, cbook, colors as mcolors, lines, verbose, rcParams)
+ backend_tools, cbook, colors as mcolors, lines, rcParams)
+
+_log = logging.getLogger(__name__)
backend_version = "%s.%s.%s" % (
Gtk.get_major_version(), Gtk.get_micro_version(), Gtk.get_minor_version())
@@ -366,7 +370,7 @@ def __init__(self, canvas, num):
# all, so I am not sure how to catch it. I am unhappy
# doing a blanket catch here, but am not sure what a
# better way is - JDH
- verbose.report('Could not load matplotlib icon: %s' % sys.exc_info()[1])
+ _log.info('Could not load matplotlib icon: %s', sys.exc_info()[1])
self.vbox = Gtk.Box()
self.vbox.set_property("orientation", Gtk.Orientation.VERTICAL)
diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py
index 46b8ac2d46ca..f84b3d539afd 100644
--- a/lib/matplotlib/backends/backend_pdf.py
+++ b/lib/matplotlib/backends/backend_pdf.py
@@ -16,6 +16,7 @@
import sys
import time
import warnings
+import logging
import zlib
import collections
from io import BytesIO
@@ -52,6 +53,8 @@
from matplotlib import _png
from matplotlib import ttconv
+_log = logging.getLogger(__name__)
+
# Overview
#
# The low-level knowledge about pdf syntax lies mainly in the pdfRepr
@@ -658,9 +661,7 @@ def fontName(self, fontprop):
Fx = Name('F%d' % self.nextFont)
self.fontNames[filename] = Fx
self.nextFont += 1
- matplotlib.verbose.report(
- 'Assigning font %s = %r' % (Fx, filename),
- 'debug')
+ _log.debug('Assigning font %s = %r' % (Fx, filename))
return Fx
@@ -694,9 +695,8 @@ def dviFontName(self, dvifont):
pdfname = Name('F%d' % self.nextFont)
self.nextFont += 1
- matplotlib.verbose.report(
- 'Assigning font {0} = {1} (dvi)'.format(pdfname, dvifont.texname),
- 'debug')
+ _log.debug('Assigning font {0} = {1} (dvi)'.format(pdfname,
+ dvifont.texname))
self.dviFontInfo[dvifont.texname] = Bunch(
dvifont=dvifont,
pdfname=pdfname,
@@ -710,19 +710,18 @@ def writeFonts(self):
fonts = {}
for dviname, info in sorted(self.dviFontInfo.items()):
Fx = info.pdfname
- matplotlib.verbose.report('Embedding Type-1 font %s from dvi'
- % dviname, 'debug')
+ _log.debug('Embedding Type-1 font %s from dvi' % dviname)
fonts[Fx] = self._embedTeXFont(info)
for filename in sorted(self.fontNames):
Fx = self.fontNames[filename]
- matplotlib.verbose.report('Embedding font %s' % filename, 'debug')
+ _log.debug('Embedding font %s' % filename)
if filename.endswith('.afm'):
# from pdf.use14corefonts
- matplotlib.verbose.report('Writing AFM font', 'debug')
+ _log.debug('Writing AFM font')
fonts[Fx] = self._write_afm_font(filename)
else:
# a normal TrueType font
- matplotlib.verbose.report('Writing TrueType font', 'debug')
+ _log.debug('Writing TrueType font')
realpath, stat_key = get_realpath_and_stat(filename)
chars = self.used_characters.get(stat_key)
if chars is not None and len(chars[1]):
@@ -744,7 +743,7 @@ def _write_afm_font(self, filename):
def _embedTeXFont(self, fontinfo):
msg = ('Embedding TeX font {0} - fontinfo={1}'
.format(fontinfo.dvifont.texname, fontinfo.__dict__))
- matplotlib.verbose.report(msg, 'debug')
+ _log.debug(msg)
# Widths
widthsObject = self.reserveObject('font widths')
diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py
index 401892435d90..7711ba26c9ea 100644
--- a/lib/matplotlib/backends/backend_ps.py
+++ b/lib/matplotlib/backends/backend_ps.py
@@ -10,9 +10,10 @@
import glob, os, shutil, sys, time, datetime
import io
+import logging
from tempfile import mkstemp
-from matplotlib import verbose, __version__, rcParams, checkdep_ghostscript
+from matplotlib import __version__, rcParams, checkdep_ghostscript
from matplotlib.afm import AFM
from matplotlib.backend_bases import (
_Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase,
@@ -39,6 +40,7 @@
import binascii
import re
+_log = logging.getLogger(__name__)
backend_version = 'Level II'
@@ -1328,10 +1330,10 @@ def write(self, *kl, **kwargs):
paperWidth, paperHeight = papersize[papertype]
if (width > paperWidth or height > paperHeight) and isEPSF:
paperWidth, paperHeight = papersize[temp_papertype]
- verbose.report(
+ _log.info(
('Your figure is too big to fit on %s paper. %s '
'paper will be used to prevent clipping.'
- ) % (papertype, temp_papertype), 'helpful')
+ ) % (papertype, temp_papertype))
texmanager = ps_renderer.get_texmanager()
font_preamble = texmanager.get_font_preamble()
@@ -1429,9 +1431,9 @@ def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
try:
latexh.write(s.encode('ascii'))
except UnicodeEncodeError:
- verbose.report("You are using unicode and latex, but have "
- "not enabled the matplotlib 'text.latex.unicode' "
- "rcParam.", 'helpful')
+ _log.info("You are using unicode and latex, but have "
+ "not enabled the matplotlib 'text.latex.unicode' "
+ "rcParam.")
raise
# Replace \\ for / so latex does not think there is a function call
@@ -1440,7 +1442,7 @@ def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
latexfile = latexfile.replace("~", "\\string~")
command = [str("latex"), "-interaction=nonstopmode",
'"%s"' % latexfile]
- verbose.report(command, 'debug')
+ _log.debug('%s', command)
try:
report = subprocess.check_output(command, cwd=tmpdir,
stderr=subprocess.STDOUT)
@@ -1451,11 +1453,11 @@ def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
'Here is the full report generated by LaTeX:\n%s '
'\n\n' % (latexfile,
exc.output.decode("utf-8"))))
- verbose.report(report, 'debug')
+ _log.debug(report)
command = [str('dvips'), '-q', '-R0', '-o', os.path.basename(psfile),
os.path.basename(dvifile)]
- verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command, cwd=tmpdir,
stderr=subprocess.STDOUT)
@@ -1466,7 +1468,7 @@ def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble,
'Here is the full report generated by dvips:\n%s '
'\n\n' % (dvifile,
exc.output.decode("utf-8"))))
- verbose.report(report, 'debug')
+ _log.debug(report)
os.remove(epsfile)
shutil.move(psfile, tmpfile)
@@ -1513,7 +1515,7 @@ def gs_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False):
command = [str(gs_exe), "-dBATCH", "-dNOPAUSE", "-r%d" % dpi,
"-sDEVICE=%s" % device_name, paper_option,
"-sOutputFile=%s" % psfile, tmpfile]
- verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exc:
@@ -1521,7 +1523,7 @@ def gs_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False):
('ghostscript was not able to process your image.\n'
'Here is the full report generated by ghostscript:\n%s '
'\n\n' % exc.output.decode("utf-8")))
- verbose.report(report, 'debug')
+ _log.debug(report)
os.remove(tmpfile)
shutil.move(psfile, tmpfile)
@@ -1571,7 +1573,7 @@ def xpdf_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False):
"-sGrayImageFilter=FlateEncode",
"-sColorImageFilter=FlateEncode", paper_option, tmpfile,
pdffile]
- verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command, stderr=subprocess.STDOUT)
@@ -1580,10 +1582,10 @@ def xpdf_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False):
('ps2pdf was not able to process your image.\n'
'Here is the full report generated by ps2pdf:\n%s '
'\n\n' % exc.output.decode("utf-8")))
- verbose.report(report, 'debug')
+ _log.debug(report)
command = [str("pdftops"), "-paper", "match", "-level2", pdffile, psfile]
- verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exc:
@@ -1591,7 +1593,7 @@ def xpdf_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False):
('pdftops was not able to process your image.\n'
'Here is the full report generated by pdftops:\n%s '
'\n\n' % exc.output.decode("utf-8")))
- verbose.report(report, 'debug')
+ _log.debug(report)
os.remove(tmpfile)
shutil.move(psfile, tmpfile)
@@ -1630,14 +1632,14 @@ def get_bbox(tmpfile, bbox):
gs_exe = ps_backend_helper.gs_exe
command = [gs_exe, "-dBATCH", "-dNOPAUSE", "-sDEVICE=bbox" "%s" % tmpfile]
- verbose.report(command, 'debug')
+ _log.debug(command)
p = subprocess.Popen(command, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
close_fds=True)
(stdout, stderr) = (p.stdout, p.stderr)
- verbose.report(stdout.read(), 'debug-annoying')
+ _log.debug(stdout.read())
bbox_info = stderr.read()
- verbose.report(bbox_info, 'helpful')
+ _log.info(bbox_info)
bbox_found = re.search('%%HiResBoundingBox: .*', bbox_info)
if bbox_found:
bbox_info = bbox_found.group()
diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py
index 98a0369f8128..f799973f932e 100644
--- a/lib/matplotlib/backends/backend_svg.py
+++ b/lib/matplotlib/backends/backend_svg.py
@@ -10,11 +10,12 @@
import os, base64, tempfile, gzip, io, sys, codecs, re
import numpy as np
+import logging
from hashlib import md5
import uuid
-from matplotlib import verbose, __version__, rcParams
+from matplotlib import __version__, rcParams
from matplotlib.backend_bases import (
_Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase,
RendererBase)
@@ -32,6 +33,8 @@
from xml.sax.saxutils import escape as escape_xml_text
+_log = logging.getLogger(__name__)
+
backend_version = __version__
# ----------------------------------------------------------------------
@@ -823,7 +826,7 @@ def draw_image(self, gc, x, y, im, transform=None):
else:
self._imaged[self.basename] = self._imaged.get(self.basename, 0) + 1
filename = '%s.image%d.png'%(self.basename, self._imaged[self.basename])
- verbose.report('Writing image file for inclusion: %s' % filename)
+ _log.info('Writing image file for inclusion: %s', filename)
_png.write_png(im, filename)
oid = oid or 'Im_' + self._make_id('image', filename)
attrib['xlink:href'] = filename
diff --git a/lib/matplotlib/backends/backend_tkagg.py b/lib/matplotlib/backends/backend_tkagg.py
index 58d171f0d737..75257811c998 100644
--- a/lib/matplotlib/backends/backend_tkagg.py
+++ b/lib/matplotlib/backends/backend_tkagg.py
@@ -8,6 +8,7 @@
import os, sys, math
import os.path
+import logging
# Paint image to Tk photo blitter extension
import matplotlib.backends.tkagg as tkagg
@@ -30,9 +31,9 @@
import matplotlib.cbook as cbook
-rcParams = matplotlib.rcParams
-verbose = matplotlib.verbose
+_log = logging.getLogger(__name__)
+rcParams = matplotlib.rcParams
backend_version = Tk.TkVersion
@@ -1059,7 +1060,7 @@ def new_figure_manager_given_figure(num, figure):
window.tk.call('wm', 'foobar', window._w, icon_img)
except Exception as exc:
# log the failure (due e.g. to Tk version), but carry on
- verbose.report('Could not load matplotlib icon: %s' % exc)
+ _log.info('Could not load matplotlib icon: %s', exc)
canvas = FigureCanvasTkAgg(figure, master=window)
manager = FigureManagerTkAgg(canvas, num, window)
diff --git a/lib/matplotlib/backends/qt_compat.py b/lib/matplotlib/backends/qt_compat.py
index 3542228d9799..3b8d4ecf3478 100644
--- a/lib/matplotlib/backends/qt_compat.py
+++ b/lib/matplotlib/backends/qt_compat.py
@@ -6,8 +6,11 @@
import six
import os
+import logging
import sys
-from matplotlib import rcParams, verbose
+from matplotlib import rcParams
+
+_log = logging.getLogger(__name__)
# Available APIs.
QT_API_PYQT = 'PyQt4' # API is not set here; Python 2.x default is V 1
@@ -111,7 +114,7 @@
QT_API = QT_API_PYSIDE
cond = ("Could not import sip; falling back on PySide\n"
"in place of PyQt4 or PyQt5.\n")
- verbose.report(cond, 'helpful')
+ _log.info(cond)
if _sip_imported:
if QT_API == QT_API_PYQTv2:
@@ -124,14 +127,14 @@
sip.setapi('QString', 2)
except:
res = 'QString API v2 specification failed. Defaulting to v1.'
- verbose.report(cond + res, 'helpful')
+ _log.info(cond + res)
# condition has now been reported, no need to repeat it:
cond = ""
try:
sip.setapi('QVariant', 2)
except:
res = 'QVariant API v2 specification failed. Defaulting to v1.'
- verbose.report(cond + res, 'helpful')
+ _log.info(cond + res)
if QT_API == QT_API_PYQT5:
try:
from PyQt5 import QtCore, QtGui, QtWidgets
diff --git a/lib/matplotlib/blocking_input.py b/lib/matplotlib/blocking_input.py
index 4dc50f47eb68..17e3633a39ae 100644
--- a/lib/matplotlib/blocking_input.py
+++ b/lib/matplotlib/blocking_input.py
@@ -26,10 +26,11 @@
unicode_literals)
import six
-from matplotlib import verbose
import matplotlib.lines as mlines
-import warnings
+import logging
+
+_log = logging.getLogger(__name__)
class BlockingInput(object):
@@ -50,8 +51,7 @@ def on_event(self, event):
# overkill for the base class, but this is consistent with
# subclasses
self.add_event(event)
-
- verbose.report("Event %i" % len(self.events))
+ _log.info("Event %i", len(self.events))
# This will extract info from events
self.post_event()
@@ -148,7 +148,7 @@ def post_event(self):
This will be called to process events
"""
if len(self.events) == 0:
- warnings.warn("No events yet")
+ _log.warning("No events yet")
elif self.events[-1].name == 'key_press_event':
self.key_event()
else:
@@ -230,8 +230,7 @@ def add_click(self, event):
This add the coordinates of an event to the list of clicks
"""
self.clicks.append((event.xdata, event.ydata))
-
- verbose.report("input %i: %f,%f" %
+ _log.info("input %i: %f,%f" %
(len(self.clicks), event.xdata, event.ydata))
# If desired plot up click
@@ -361,7 +360,7 @@ def post_event(self):
Determines if it is a key event
"""
if len(self.events) == 0:
- warnings.warn("No events yet")
+ _log.warning("No events yet")
else:
self.keyormouse = self.events[-1].name == 'key_press_event'
diff --git a/lib/matplotlib/dviread.py b/lib/matplotlib/dviread.py
index 014d134533c1..f3b55ddd532a 100644
--- a/lib/matplotlib/dviread.py
+++ b/lib/matplotlib/dviread.py
@@ -26,10 +26,7 @@
from collections import namedtuple
import errno
from functools import partial, wraps
-import matplotlib
-import matplotlib.cbook as mpl_cbook
-from matplotlib.compat import subprocess
-from matplotlib import rcParams
+import logging
import numpy as np
import re
import struct
@@ -37,6 +34,11 @@
import textwrap
import os
+import matplotlib
+import matplotlib.cbook as mpl_cbook
+from matplotlib.compat import subprocess
+from matplotlib import rcParams
+
try:
from functools import lru_cache
except ImportError: # Py2
@@ -46,6 +48,8 @@
def ord(x):
return x
+_log = logging.getLogger(__name__)
+
# Dvi is a bytecode format documented in
# http://mirrors.ctan.org/systems/knuth/dist/texware/dvitype.web
# http://texdoc.net/texmf-dist/doc/generic/knuth/texware/dvitype.pdf
@@ -204,7 +208,7 @@ def __init__(self, filename, dpi):
*dpi* only sets the units and does not limit the resolution.
Use None to return TeX's internal units.
"""
- matplotlib.verbose.report('Dvi: ' + filename, 'debug')
+ _log.debug('Dvi: ' + filename)
self.file = open(filename, 'rb')
self.dpi = dpi
self.fonts = {}
@@ -450,12 +454,11 @@ def _xxx(self, datalen):
else:
def chr_(x):
return x
- matplotlib.verbose.report(
+ _log.debug(
'Dvi._xxx: encountered special: %s'
% ''.join([(32 <= ord(ch) < 127) and chr_(ch)
or '<%02x>' % ord(ch)
- for ch in special]),
- 'debug')
+ for ch in special]))
@dispatch(min=243, max=246, args=('olen1', 'u4', 'u4', 'u4', 'u1', 'u1'))
def _fnt_def(self, k, c, s, d, a, l):
@@ -580,10 +583,8 @@ def _width_of(self, char):
width = self._tfm.width.get(char, None)
if width is not None:
return _mul2012(width, self._scale)
-
- matplotlib.verbose.report(
- 'No width for char %d in font %s' % (char, self.texname),
- 'debug')
+ _log.debug(
+ 'No width for char %d in font %s' % (char, self.texname))
return 0
def _height_depth_of(self, char):
@@ -596,10 +597,9 @@ def _height_depth_of(self, char):
(self._tfm.depth, "depth")):
value = metric.get(char, None)
if value is None:
- matplotlib.verbose.report(
+ _log.debug(
'No %s for char %d in font %s' % (
- name, char, self.texname),
- 'debug')
+ name, char, self.texname))
result.append(0)
else:
result.append(_mul2012(value, self._scale))
@@ -712,7 +712,7 @@ def _pre(self, i, x, cs, ds):
if i != 202:
raise ValueError("Unknown vf format %d" % i)
if len(x):
- matplotlib.verbose.report('vf file comment: ' + x, 'debug')
+ _log.debug('vf file comment: ' + x)
self.state = _dvistate.outer
# cs = checksum, ds = design size
@@ -760,14 +760,14 @@ class Tfm(object):
__slots__ = ('checksum', 'design_size', 'width', 'height', 'depth')
def __init__(self, filename):
- matplotlib.verbose.report('opening tfm file ' + filename, 'debug')
+ _log.debug('opening tfm file ' + filename)
with open(filename, 'rb') as file:
header1 = file.read(24)
lh, bc, ec, nw, nh, nd = \
struct.unpack(str('!6H'), header1[2:14])
- matplotlib.verbose.report(
+ _log.debug(
'lh=%d, bc=%d, ec=%d, nw=%d, nh=%d, nd=%d' % (
- lh, bc, ec, nw, nh, nd), 'debug')
+ lh, bc, ec, nw, nh, nd))
header2 = file.read(4*lh)
self.checksum, self.design_size = \
struct.unpack(str('!2I'), header2[:8])
@@ -864,7 +864,7 @@ def __getitem__(self, texname):
msg = fmt.format(texname.decode('ascii'), self._filename)
msg = textwrap.fill(msg, break_on_hyphens=False,
break_long_words=False)
- matplotlib.verbose.report(msg, 'helpful')
+ _log.info(msg)
raise
fn, enc = result.filename, result.encoding
if fn is not None and not fn.startswith(b'/'):
@@ -937,10 +937,9 @@ def _parse(self, file):
w.group('enc2') or w.group('enc1'))
if enc:
if encoding is not None:
- matplotlib.verbose.report(
+ _log.debug(
'Multiple encodings for %s = %s'
- % (texname, psname),
- 'debug')
+ % (texname, psname))
encoding = enc
continue
# File names are probably unquoted:
@@ -983,11 +982,9 @@ class Encoding(object):
def __init__(self, filename):
with open(filename, 'rb') as file:
- matplotlib.verbose.report('Parsing TeX encoding ' + filename,
- 'debug-annoying')
+ _log.debug('Parsing TeX encoding ' + filename)
self.encoding = self._parse(file)
- matplotlib.verbose.report('Result: ' + repr(self.encoding),
- 'debug-annoying')
+ _log.debug('Result: ' + repr(self.encoding))
def __iter__(self):
for name in self.encoding:
@@ -1047,9 +1044,8 @@ def find_tex_file(filename, format=None):
if format is not None:
cmd += ['--format=' + format]
cmd += [filename]
-
- matplotlib.verbose.report('find_tex_file(%s): %s'
- % (filename, cmd), 'debug')
+ _log.debug('find_tex_file(%s): %s'
+ % (filename, cmd))
# stderr is unused, but reading it avoids a subprocess optimization
# that breaks EINTR handling in some Python versions:
# http://bugs.python.org/issue12493
@@ -1057,8 +1053,7 @@ def find_tex_file(filename, format=None):
pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = pipe.communicate()[0].rstrip()
- matplotlib.verbose.report('find_tex_file result: %s' % result,
- 'debug')
+ _log.debug('find_tex_file result: %s' % result)
return result.decode('ascii')
@@ -1078,7 +1073,6 @@ def _fontfile(cls, suffix, texname):
if __name__ == '__main__':
import sys
- matplotlib.verbose.set_level('debug-annoying')
fname = sys.argv[1]
try:
dpi = float(sys.argv[2])
diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py
index a8ff2e303417..d1eda6858344 100644
--- a/lib/matplotlib/figure.py
+++ b/lib/matplotlib/figure.py
@@ -16,6 +16,7 @@
import six
+import logging
import warnings
import numpy as np
@@ -48,6 +49,8 @@
TransformedBbox)
from matplotlib.backend_bases import NonGuiException
+_log = logging.getLogger(__name__)
+
docstring.interpd.update(projection_names=get_projection_names())
diff --git a/lib/matplotlib/finance.py b/lib/matplotlib/finance.py
index d64b09c87523..9121c41c87aa 100644
--- a/lib/matplotlib/finance.py
+++ b/lib/matplotlib/finance.py
@@ -17,10 +17,11 @@
from six.moves.urllib.request import urlopen
import datetime
+import logging
import numpy as np
-from matplotlib import colors as mcolors, verbose, get_cachedir
+from matplotlib import colors as mcolors, get_cachedir
from matplotlib.dates import date2num
from matplotlib.cbook import iterable, mkdirs, warn_deprecated
from matplotlib.collections import LineCollection, PolyCollection
@@ -28,6 +29,8 @@
from matplotlib.patches import Rectangle
from matplotlib.transforms import Affine2D
+_log = logging.getLogger(__name__)
+
warn_deprecated(
since=2.0,
message=("The finance module has been deprecated in mpl 2.0 and will "
@@ -338,7 +341,7 @@ def fetch_historical_yahoo(ticker, date1, date2, cachename=None,
if dividends:
g = 'v'
- verbose.report('Retrieving dividends instead of prices')
+ _log.info('Retrieving dividends instead of prices')
else:
g = 'd'
@@ -353,14 +356,14 @@ def fetch_historical_yahoo(ticker, date1, date2, cachename=None,
if cachename is not None:
if os.path.exists(cachename):
fh = open(cachename)
- verbose.report('Using cachefile %s for '
+ _log.info('Using cachefile %s for '
'%s' % (cachename, ticker))
else:
mkdirs(os.path.abspath(os.path.dirname(cachename)))
with contextlib.closing(urlopen(url)) as urlfh:
with open(cachename, 'wb') as fh:
fh.write(urlfh.read())
- verbose.report('Saved %s data to cache file '
+ _log.info('Saved %s data to cache file '
'%s' % (ticker, cachename))
fh = open(cachename, 'r')
diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py
index bcffeb02f6cb..70044d692bfa 100644
--- a/lib/matplotlib/font_manager.py
+++ b/lib/matplotlib/font_manager.py
@@ -53,6 +53,7 @@
import sys
from threading import Timer
import warnings
+import logging
import matplotlib
from matplotlib import afm, cbook, ft2font, rcParams, get_cachedir
@@ -65,9 +66,9 @@
except ImportError:
from backports.functools_lru_cache import lru_cache
+_log = logging.getLogger(__name__)
USE_FONTCONFIG = False
-verbose = matplotlib.verbose
font_scalings = {
'xx-small' : 0.579,
@@ -554,7 +555,7 @@ def createFontList(fontfiles, fontext='ttf'):
# Add fonts from list of known font files.
seen = set()
for fpath in fontfiles:
- verbose.report('createFontDict: %s' % fpath, 'debug')
+ _log.debug('createFontDict: %s' % (fpath))
fname = os.path.split(fpath)[1]
if fname in seen:
continue
@@ -564,12 +565,12 @@ def createFontList(fontfiles, fontext='ttf'):
try:
fh = open(fpath, 'rb')
except EnvironmentError:
- verbose.report("Could not open font file %s" % fpath)
+ _log.info("Could not open font file %s", fpath)
continue
try:
font = afm.AFM(fh)
except RuntimeError:
- verbose.report("Could not parse font file %s" % fpath)
+ _log.info("Could not parse font file %s", fpath)
continue
finally:
fh.close()
@@ -581,13 +582,13 @@ def createFontList(fontfiles, fontext='ttf'):
try:
font = ft2font.FT2Font(fpath)
except RuntimeError:
- verbose.report("Could not open font file %s" % fpath)
+ _log.info("Could not open font file %s", fpath)
continue
except UnicodeError:
- verbose.report("Cannot handle unicode filenames")
+ _log.info("Cannot handle unicode filenames")
continue
except IOError:
- verbose.report("IO error - cannot open font file %s" % fpath)
+ _log.info("IO error - cannot open font file %s", fpath)
continue
try:
prop = ttfFontProperty(font)
@@ -1057,8 +1058,7 @@ def __init__(self, size=None, weight='normal'):
paths.extend(ttfpath.split(':'))
else:
paths.append(ttfpath)
-
- verbose.report('font search path %s'%(str(paths)))
+ _log.info('font search path %s', str(paths))
# Load TrueType fonts and create font dictionary.
self.ttffiles = findSystemFonts(paths) + findSystemFonts()
@@ -1068,7 +1068,7 @@ def __init__(self, size=None, weight='normal'):
self.defaultFont = {}
for fname in self.ttffiles:
- verbose.report('trying fontname %s' % fname, 'debug')
+ _log.debug('trying fontname %s' % fname)
if fname.lower().find('DejaVuSans.ttf')>=0:
self.defaultFont['ttf'] = fname
break
@@ -1288,8 +1288,9 @@ def _findfont_cached(self, prop, fontext, directory, fallback_to_default,
if not isinstance(prop, FontProperties):
prop = FontProperties(prop)
fname = prop.get_file()
+
if fname is not None:
- verbose.report('findfont returning %s'%fname, 'debug')
+ _log.debug('findfont returning %s'%fname)
return fname
if fontext == 'afm':
@@ -1340,14 +1341,14 @@ def _findfont_cached(self, prop, fontext, directory, fallback_to_default,
UserWarning)
result = self.defaultFont[fontext]
else:
- verbose.report(
+ _log.info(
'findfont: Matching %s to %s (%s) with score of %f' %
(prop, best_font.name, repr(best_font.fname), best_score))
result = best_font.fname
if not os.path.isfile(result):
if rebuild_if_missing:
- verbose.report(
+ _log.info(
'findfont: Found a missing font file. Rebuilding cache.')
_rebuild()
return fontManager.findfont(
@@ -1444,8 +1445,7 @@ def _rebuild():
if _fmcache:
with cbook.Locked(cachedir):
json_dump(fontManager, _fmcache)
-
- verbose.report("generated new fontManager")
+ _log.info("generated new fontManager")
if _fmcache:
try:
@@ -1455,7 +1455,7 @@ def _rebuild():
_rebuild()
else:
fontManager.default_size = None
- verbose.report("Using fontManager instance from %s" % _fmcache)
+ _log.info("Using fontManager instance from %s", _fmcache)
except cbook.Locked.TimeoutError:
raise
except:
diff --git a/lib/matplotlib/sankey.py b/lib/matplotlib/sankey.py
index d57a66333ba8..84a2c2950faf 100644
--- a/lib/matplotlib/sankey.py
+++ b/lib/matplotlib/sankey.py
@@ -5,6 +5,7 @@
unicode_literals)
import six
+import logging
from six.moves import zip
import numpy as np
@@ -12,10 +13,11 @@
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.transforms import Affine2D
-from matplotlib import verbose
from matplotlib import docstring
from matplotlib import rcParams
+_log = logging.getLogger(__name__)
+
__author__ = "Kevin L. Davies"
__credits__ = ["Yannick Copin"]
__license__ = "BSD"
@@ -465,22 +467,21 @@ def add(self, patchlabel='', flows=None, orientations=None, labels='',
"trunklength is negative.\nThis isn't allowed, because it would "
"cause poor layout.")
if np.abs(np.sum(flows)) > self.tolerance:
- verbose.report(
- "The sum of the flows is nonzero (%f).\nIs the "
- "system not at steady state?" % np.sum(flows), 'helpful')
+ _log.info("The sum of the flows is nonzero (%f).\nIs the "
+ "system not at steady state?", np.sum(flows))
scaled_flows = self.scale * flows
gain = sum(max(flow, 0) for flow in scaled_flows)
loss = sum(min(flow, 0) for flow in scaled_flows)
if not (0.5 <= gain <= 2.0):
- verbose.report(
+ _log.info(
"The scaled sum of the inputs is %f.\nThis may "
"cause poor layout.\nConsider changing the scale so"
- " that the scaled sum is approximately 1.0." % gain, 'helpful')
+ " that the scaled sum is approximately 1.0.", gain)
if not (-2.0 <= loss <= -0.5):
- verbose.report(
+ _log.info(
"The scaled sum of the outputs is %f.\nThis may "
"cause poor layout.\nConsider changing the scale so"
- " that the scaled sum is approximately 1.0." % gain, 'helpful')
+ " that the scaled sum is approximately 1.0.", gain)
if prior is not None:
if prior < 0:
raise ValueError("The index of the prior diagram is negative.")
@@ -522,11 +523,11 @@ def add(self, patchlabel='', flows=None, orientations=None, labels='',
elif flow <= -self.tolerance:
are_inputs[i] = False
else:
- verbose.report(
+ _log.info(
"The magnitude of flow %d (%f) is below the "
"tolerance (%f).\nIt will not be shown, and it "
"cannot be used in a connection."
- % (i, flow, self.tolerance), 'helpful')
+ % (i, flow, self.tolerance))
# Determine the angles of the arrows (before rotation).
angles = [None] * n
diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py
index f7bb1fb0e1be..64fbd5dbe65c 100644
--- a/lib/matplotlib/tests/test_backend_ps.py
+++ b/lib/matplotlib/tests/test_backend_ps.py
@@ -140,7 +140,6 @@ def test_tilde_in_tempfilename():
plt.rc('text', usetex=True)
plt.plot([1, 2, 3, 4])
plt.xlabel(r'\textbf{time} (s)')
- # matplotlib.verbose.set_level("debug")
output_eps = os.path.join(base_tempdir, 'tex_demo.eps')
# use the PS backend to write the file...
plt.savefig(output_eps, format="ps")
diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py
index ac2875bdae12..cafb56f93d9b 100644
--- a/lib/matplotlib/texmanager.py
+++ b/lib/matplotlib/texmanager.py
@@ -44,6 +44,7 @@
import shutil
import sys
import warnings
+import logging
from hashlib import md5
@@ -57,6 +58,7 @@
import matplotlib.dviread as dviread
import re
+_log = logging.getLogger(__name__)
DEBUG = False
@@ -68,17 +70,16 @@ def dvipng_hack_alpha():
stderr=STDOUT, close_fds=(sys.platform != 'win32'))
stdout, stderr = p.communicate()
except OSError:
- mpl.verbose.report('No dvipng was found', 'helpful')
+ _log.info('No dvipng was found')
return False
lines = stdout.decode(sys.getdefaultencoding()).split('\n')
for line in lines:
if line.startswith('dvipng '):
version = line.split()[-1]
- mpl.verbose.report('Found dvipng version %s' % version,
- 'helpful')
+ _log.info('Found dvipng version %s', version)
version = distutils.version.LooseVersion(version)
return version < distutils.version.LooseVersion('1.6')
- mpl.verbose.report('Unexpected response from dvipng -version', 'helpful')
+ _log.info('Unexpected response from dvipng -version')
return False
@@ -169,11 +170,10 @@ def __init__(self):
elif isinstance(ff, six.string_types) and ff.lower() in self.font_families:
self.font_family = ff.lower()
else:
- mpl.verbose.report(
+ _log.info(
'font.family must be one of (%s) when text.usetex is True. '
- 'serif will be used by default.' %
- ', '.join(self.font_families),
- 'helpful')
+ 'serif will be used by default.',
+ ', '.join(self.font_families))
self.font_family = 'serif'
fontconfig = [self.font_family]
@@ -192,9 +192,9 @@ def __init__(self):
if DEBUG:
print('$s font is not compatible with usetex')
else:
- mpl.verbose.report('No LaTeX-compatible font found for the '
+ _log.info('No LaTeX-compatible font found for the '
'%s font family in rcParams. Using '
- 'default.' % font_family, 'helpful')
+ 'default.', font_family)
setattr(self, font_family_attr, self.font_info[font_family])
fontconfig.append(getattr(self, font_family_attr)[0])
# Add a hash of the latex preamble to self._fontconfig so that the
@@ -295,10 +295,9 @@ def make_tex(self, tex, fontsize):
try:
fh.write(s.encode('ascii'))
except UnicodeEncodeError as err:
- mpl.verbose.report("You are using unicode and latex, but "
+ _log.info("You are using unicode and latex, but "
"have not enabled the matplotlib "
- "'text.latex.unicode' rcParam.",
- 'helpful')
+ "'text.latex.unicode' rcParam.")
raise
return texfile
@@ -356,10 +355,9 @@ def make_tex_preview(self, tex, fontsize):
try:
fh.write(s.encode('ascii'))
except UnicodeEncodeError as err:
- mpl.verbose.report("You are using unicode and latex, but "
+ _log.info("You are using unicode and latex, but "
"have not enabled the matplotlib "
- "'text.latex.unicode' rcParam.",
- 'helpful')
+ "'text.latex.unicode' rcParam.")
raise
return texfile
@@ -376,12 +374,11 @@ def make_dvi(self, tex, fontsize):
basefile = self.get_basefile(tex, fontsize)
dvifile = '%s.dvi' % basefile
-
if DEBUG or not os.path.exists(dvifile):
texfile = self.make_tex(tex, fontsize)
command = [str("latex"), "-interaction=nonstopmode",
os.path.basename(texfile)]
- mpl.verbose.report(command, 'debug')
+ _log.debug(command)
with Locked(self.texcache):
try:
report = subprocess.check_output(command,
@@ -394,7 +391,7 @@ def make_dvi(self, tex, fontsize):
'Here is the full report generated by LaTeX:\n%s '
'\n\n' % (repr(tex.encode('unicode_escape')),
exc.output.decode("utf-8"))))
- mpl.verbose.report(report, 'debug')
+ _log.debug(report)
for fname in glob.glob(basefile + '*'):
if fname.endswith('dvi'):
pass
@@ -425,7 +422,7 @@ def make_dvi_preview(self, tex, fontsize):
texfile = self.make_tex_preview(tex, fontsize)
command = [str("latex"), "-interaction=nonstopmode",
os.path.basename(texfile)]
- mpl.verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command,
cwd=self.texcache,
@@ -437,7 +434,7 @@ def make_dvi_preview(self, tex, fontsize):
'Here is the full report generated by LaTeX:\n%s '
'\n\n' % (repr(tex.encode('unicode_escape')),
exc.output.decode("utf-8"))))
- mpl.verbose.report(report, 'debug')
+ _log.debug(report)
# find the box extent information in the latex output
# file and store them in ".baseline" file
@@ -475,7 +472,7 @@ def make_png(self, tex, fontsize, dpi):
command = [str("dvipng"), "-bg", "Transparent", "-D", str(dpi),
"-T", "tight", "-o", os.path.basename(pngfile),
os.path.basename(dvifile)]
- mpl.verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command,
cwd=self.texcache,
@@ -487,7 +484,7 @@ def make_png(self, tex, fontsize, dpi):
'Here is the full report generated by dvipng:\n%s '
'\n\n' % (repr(tex.encode('unicode_escape')),
exc.output.decode("utf-8"))))
- mpl.verbose.report(report, 'debug')
+ _log.debug(report)
return pngfile
@@ -505,7 +502,7 @@ def make_ps(self, tex, fontsize):
command = [str("dvips"), "-q", "-E", "-o",
os.path.basename(psfile),
os.path.basename(dvifile)]
- mpl.verbose.report(command, 'debug')
+ _log.debug(command)
try:
report = subprocess.check_output(command,
cwd=self.texcache,
@@ -517,7 +514,7 @@ def make_ps(self, tex, fontsize):
'Here is the full report generated by dvips:\n%s '
'\n\n' % (repr(tex.encode('unicode_escape')),
exc.output.decode("utf-8"))))
- mpl.verbose.report(report, 'debug')
+ _log.debug(report)
return psfile
diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py
index 22a27756f895..a55afdb49b69 100644
--- a/lib/matplotlib/text.py
+++ b/lib/matplotlib/text.py
@@ -9,6 +9,7 @@
import math
import warnings
+import logging
import weakref
import contextlib
@@ -20,7 +21,7 @@
import matplotlib.artist as artist
from matplotlib.artist import Artist
from matplotlib.cbook import maxdict
-from matplotlib import docstring, verbose
+from matplotlib import docstring
from matplotlib.font_manager import FontProperties
from matplotlib.patches import FancyBboxPatch
from matplotlib.patches import FancyArrowPatch, Rectangle
@@ -33,6 +34,8 @@
from matplotlib.textpath import TextPath
+_log = logging.getLogger(__name__)
+
def _process_text_args(override, fontdict=None, **kwargs):
"Return an override dict. See :func:`~pyplot.text' docstring for info"
@@ -721,9 +724,7 @@ def draw(self, renderer):
posy = float(textobj.convert_yunits(textobj._y))
posx, posy = trans.transform_point((posx, posy))
if not np.isfinite(posx) or not np.isfinite(posy):
- verbose.report("x and y are not finite values for text "
- "string '{}'. Not rendering "
- "text.".format(self.get_text()), 'helpful')
+ _log.warning("posx and posy should be finite values")
return
canvasw, canvash = renderer.get_canvas_width_height()
diff --git a/matplotlibrc.template b/matplotlibrc.template
index 5013c9755c8e..22fb2cfef5a1 100644
--- a/matplotlibrc.template
+++ b/matplotlibrc.template
@@ -557,26 +557,6 @@ backend : $TEMPLATE_BACKEND
# docstring params
#docstring.hardcopy = False # set this when you want to generate hardcopy docstring
-# Set the verbose flags. This controls how much information
-# matplotlib gives you at runtime and where it goes. The verbosity
-# levels are: silent, helpful, debug, debug-annoying. Any level is
-# inclusive of all the levels below it. If your setting is "debug",
-# you'll get all the debug and helpful messages. When submitting
-# problems to the mailing-list, please set verbose to "helpful" or "debug"
-# and paste the output into your report.
-#
-# The "fileo" gives the destination for any calls to verbose.report.
-# These objects can a filename, or a filehandle like sys.stdout.
-#
-# You can override the rc default verbosity from the command line by
-# giving the flags --verbose-LEVEL where LEVEL is one of the legal
-# levels, e.g., --verbose-helpful.
-#
-# You can access the verbose instance in your code
-# from matplotlib import verbose.
-#verbose.level : silent # one of silent, helpful, debug, debug-annoying
-#verbose.fileo : sys.stdout # a log filename, sys.stdout or sys.stderr
-
# Event keys to interact with figures/plots via keyboard.
# Customize these settings according to your needs.
# Leave the field(s) empty if you don't need a key-map. (i.e., fullscreen : '')