Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 67e57b2

Browse files
committed
1) Replaced warnings.warn with either logging.warnings or cbook._warn_external.
2) Updated contributions guidelines to use cbook._warn_external.
1 parent f288977 commit 67e57b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+399
-340
lines changed

doc/devel/contributing.rst

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -449,29 +449,71 @@ Then they will receive messages like::
449449
Which logging level to use?
450450
~~~~~~~~~~~~~~~~~~~~~~~~~~~
451451

452-
There are five levels at which you can emit messages. `logging.critical` and
453-
`logging.error` are really only there for errors that will end the use of the
454-
library but not kill the interpreter. `logging.warning` overlaps with the
455-
`warnings` library. The `logging tutorial`_ suggests that the difference
456-
between `logging.warning` and `warnings.warn` is that `warnings.warn` should
457-
be used for things the user must change to stop the warning (typically in the
458-
source), whereas `logging.warning` can be more persistent. Moreover, note
459-
that `warnings.warn` will by default only emit a given warning *once*, whereas
460-
`logging.warning` will display the message every time it is called.
452+
There are five levels at which you can emit messages.
453+
454+
- `logging.critical` and `logging.error` are really only there for errors that
455+
will end the use of the library but not kill the interpreter.
456+
- `logging.warning` and `cbook._warn_external` are used to warn the user,
457+
see below.
458+
- `logging.info` is for information that the user may want to know if the
459+
program behaves oddly. They are not displayed by default. For instance, if
460+
an object isn't drawn because its position is ``NaN``, that can usually
461+
be ignored, but a mystified user could call
462+
``logging.basicConfig(level=logging.INFO)`` and get an error message that
463+
says why.
464+
- `logging.debug` is the least likely to be displayed, and hence can be the
465+
most verbose. "Expected" code paths (e.g., reporting normal intermediate
466+
steps of layouting or rendering) should only log at this level.
461467

462468
By default, `logging` displays all log messages at levels higher than
463469
`logging.WARNING` to `sys.stderr`.
464470

465-
Calls to `logging.info` are not displayed by default. They are for
466-
information that the user may want to know if the program behaves oddly.
467-
For instance, if an object isn't drawn because its position is ``NaN``,
468-
that can usually be ignored, but a mystified user could call
469-
``logging.basicConfig(level=logging.INFO)`` and get an error message that
470-
says why.
471+
The `logging tutorial`_ suggests that the difference
472+
between `logging.warning` and `cbook._warn_external` (which uses
473+
`warnings.warn`) is that `cbook._warn_external` should be used for things the
474+
user must change to stop the warning (typically in the source), whereas
475+
`logging.warning` can be more persistent. Moreover, note that
476+
`cbook._warn_external` will by default only emit a given warning *once* for
477+
each line of user code, whereas `logging.warning` will display the message
478+
every time it is called.
471479

472-
`logging.debug` is the least likely to be displayed, and hence can be the most
473-
verbose. "Expected" code paths (e.g., reporting normal intermediate steps of
474-
layouting or rendering) should only log at this level.
480+
By default, `warnings.warn` displays the line of code that has the `warn` call.
481+
This usually isn't more informative than the warning message itself. Therefore,
482+
Matplotlib uses `cbook._warn_external` which uses `warnings.warn`, but goes
483+
up the stack and displays the first line of code outside of Matplotlib.
484+
For example, for the module::
485+
486+
# in my_matplotlib_module.py
487+
import warnings
488+
489+
def set_range(bottom, top):
490+
if bottom == top:
491+
warnings.warn('Attempting to set identical bottom==top')
492+
493+
494+
running the script::
495+
496+
from matplotlib import my_matplotlib_module
497+
my_matplotlib_module.set_range(0, 0) #set range
498+
499+
500+
will display::
501+
502+
UserWarning: Attempting to set identical bottom==top
503+
warnings.warn('Attempting to set identical bottom==top')
504+
505+
Modifying the module to use `cbook._warn_external`::
506+
507+
from matplotlib import cbook
508+
509+
def set_range(bottom, top):
510+
if bottom == top:
511+
cbook._warn_external('Attempting to set identical bottom==top')
512+
513+
and running the same script will display::
514+
515+
UserWarning: Attempting to set identical bottom==top
516+
my_matplotlib_module.set_range(0, 0) #set range
475517

476518
.. _logging tutorial: https://docs.python.org/3/howto/logging.html#logging-basic-tutorial
477519

lib/matplotlib/__init__.py

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,8 @@ def _set_logger_verbose_level(level_str='silent', file_str='sys.stdout'):
244244
fileo = open(file_str, 'w')
245245
# if this fails, we will just write to stdout
246246
except IOError:
247-
warnings.warn('could not open log file "{0}"'
248-
'for writing. Check your '
249-
'matplotlibrc'.format(file_str))
247+
_log.warning('could not open log file "{0}" for writing. '
248+
'Check your matplotlibrc'.format(file_str))
250249
console = logging.StreamHandler(fileo)
251250
console.setLevel(newlev)
252251
_log.addHandler(console)
@@ -307,8 +306,9 @@ def set_level(self, level):
307306
if self._commandLineVerbose is not None:
308307
level = self._commandLineVerbose
309308
if level not in self.levels:
310-
warnings.warn('matplotlib: unrecognized --verbose-* string "%s".'
311-
' Legal values are %s' % (level, self.levels))
309+
cbook._warn_external('matplotlib: unrecognized --verbose-* '
310+
'string "%s". Legal values are %s' %
311+
(level, self.levels))
312312
else:
313313
self.level = level
314314

@@ -487,9 +487,9 @@ def checkdep_ps_distiller(s):
487487
gs_exec, gs_v = checkdep_ghostscript()
488488
if not gs_exec:
489489
flag = False
490-
warnings.warn('matplotlibrc ps.usedistiller option can not be used '
491-
'unless ghostscript 9.0 or later is installed on your '
492-
'system')
490+
_log.warning('matplotlibrc ps.usedistiller option can not be used '
491+
'unless ghostscript 9.0 or later is installed on your '
492+
'system')
493493

494494
if s == 'xpdf':
495495
pdftops_req = '3.0'
@@ -502,9 +502,9 @@ def checkdep_ps_distiller(s):
502502
pass
503503
else:
504504
flag = False
505-
warnings.warn(('matplotlibrc ps.usedistiller can not be set to '
506-
'xpdf unless xpdf-%s or later is installed on '
507-
'your system') % pdftops_req)
505+
_log.warning(('matplotlibrc ps.usedistiller can not be set to '
506+
'xpdf unless xpdf-%s or later is installed on '
507+
'your system') % pdftops_req)
508508

509509
if flag:
510510
return s
@@ -522,22 +522,22 @@ def checkdep_usetex(s):
522522

523523
if shutil.which("tex") is None:
524524
flag = False
525-
warnings.warn('matplotlibrc text.usetex option can not be used unless '
526-
'TeX is installed on your system')
525+
_log.warning('matplotlibrc text.usetex option can not be used unless '
526+
'TeX is installed on your system')
527527

528528
dvipng_v = checkdep_dvipng()
529529
if not compare_versions(dvipng_v, dvipng_req):
530530
flag = False
531-
warnings.warn('matplotlibrc text.usetex can not be used with *Agg '
532-
'backend unless dvipng-%s or later is installed on '
533-
'your system' % dvipng_req)
531+
_log.warning('matplotlibrc text.usetex can not be used with *Agg '
532+
'backend unless dvipng-%s or later is installed on '
533+
'your system' % dvipng_req)
534534

535535
gs_exec, gs_v = checkdep_ghostscript()
536536
if not compare_versions(gs_v, gs_req):
537537
flag = False
538-
warnings.warn('matplotlibrc text.usetex can not be used unless '
539-
'ghostscript-%s or later is installed on your system'
540-
% gs_req)
538+
_log.warning('matplotlibrc text.usetex can not be used unless '
539+
'ghostscript-%s or later is installed on your system'
540+
% gs_req)
541541

542542
return flag
543543

@@ -961,17 +961,17 @@ def _rc_params_in_file(fname, fail_on_error=False):
961961
tup = strippedline.split(':', 1)
962962
if len(tup) != 2:
963963
error_details = _error_details_fmt % (cnt, line, fname)
964-
warnings.warn('Illegal %s' % error_details)
964+
_log.warning('Illegal %s' % error_details)
965965
continue
966966
key, val = tup
967967
key = key.strip()
968968
val = val.strip()
969969
if key in rc_temp:
970-
warnings.warn('Duplicate key in file "%s", line #%d' %
971-
(fname, cnt))
970+
_log.warning('Duplicate key in file "%s", line #%d' %
971+
(fname, cnt))
972972
rc_temp[key] = (val, line, cnt)
973973
except UnicodeDecodeError:
974-
warnings.warn(
974+
_log.warning(
975975
('Cannot decode configuration file %s with '
976976
'encoding %s, check LANG and LC_* variables')
977977
% (fname, locale.getpreferredencoding(do_setlocale=False) or
@@ -990,8 +990,8 @@ def _rc_params_in_file(fname, fail_on_error=False):
990990
config[key] = val # try to convert to proper type or skip
991991
except Exception as msg:
992992
error_details = _error_details_fmt % (cnt, line, fname)
993-
warnings.warn('Bad val "%s" on %s\n\t%s' %
994-
(val, error_details, msg))
993+
_log.warning('Bad val "%s" on %s\n\t%s' %
994+
(val, error_details, msg))
995995

996996
for key, (val, line, cnt) in rc_temp.items():
997997
if key in defaultParams:
@@ -1002,8 +1002,8 @@ def _rc_params_in_file(fname, fail_on_error=False):
10021002
config[key] = val # try to convert to proper type or skip
10031003
except Exception as msg:
10041004
error_details = _error_details_fmt % (cnt, line, fname)
1005-
warnings.warn('Bad val "%s" on %s\n\t%s' %
1006-
(val, error_details, msg))
1005+
_log.warning('Bad val "%s" on %s\n\t%s' %
1006+
(val, error_details, msg))
10071007
elif key in _deprecated_ignore_map:
10081008
version, alt_key = _deprecated_ignore_map[key]
10091009
cbook.warn_deprecated(
@@ -1345,10 +1345,9 @@ def use(arg, warn=True, force=False):
13451345
# If we are going to force the switch, never warn, else, if warn
13461346
# is True, then direct users to `plt.switch_backend`
13471347
if (not force) and warn:
1348-
warnings.warn(
1348+
cbook._warn_external(
13491349
("matplotlib.pyplot as already been imported, "
1350-
"this call will have no effect."),
1351-
stacklevel=2)
1350+
"this call will have no effect."))
13521351

13531352
# if we are going to force switching the backend, pull in
13541353
# `switch_backend` from pyplot. This will only happen if
@@ -1428,7 +1427,7 @@ def _init_tests():
14281427
from matplotlib import ft2font
14291428
if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or
14301429
ft2font.__freetype_build_type__ != 'local'):
1431-
warnings.warn(
1430+
_log.warning(
14321431
"Matplotlib is not built with the correct FreeType version to run "
14331432
"tests. Set local_freetype=True in setup.cfg and rebuild. "
14341433
"Expect many image comparison failures below. "
@@ -1437,9 +1436,7 @@ def _init_tests():
14371436
"Freetype build type is {2}local".format(
14381437
LOCAL_FREETYPE_VERSION,
14391438
ft2font.__freetype_version__,
1440-
"" if ft2font.__freetype_build_type__ == 'local' else "not "
1441-
)
1442-
)
1439+
"" if ft2font.__freetype_build_type__ == 'local' else "not "))
14431440

14441441
try:
14451442
import pytest
@@ -1769,12 +1766,12 @@ def inner(ax, *args, data=None, **kwargs):
17691766
elif label_namer in kwargs:
17701767
kwargs['label'] = get_label(kwargs[label_namer], label)
17711768
else:
1772-
warnings.warn(
1769+
cbook._warn_external(
17731770
"Tried to set a label via parameter %r in func %r but "
1774-
"couldn't find such an argument.\n"
1775-
"(This is a programming error, please report to "
1776-
"the Matplotlib list!)" % (label_namer, func.__name__),
1777-
RuntimeWarning, stacklevel=2)
1771+
"couldn't find such an argument.\n(This is a "
1772+
"programming error, please report to the Matplotlib "
1773+
"list!)" % (label_namer, func.__name__),
1774+
RuntimeWarning)
17781775
return func(ax, *args, **kwargs)
17791776

17801777
inner.__doc__ = _add_data_doc(inner.__doc__,

lib/matplotlib/_constrained_layout.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@
4545
# Todo: AnchoredOffsetbox connected to gridspecs or axes. This would
4646
# be more general way to add extra-axes annotations.
4747

48-
import numpy as np
4948
import logging
50-
import warnings
5149

50+
import numpy as np
51+
52+
import matplotlib.cbook as cbook
5253
import matplotlib._layoutbox as layoutbox
5354

5455
_log = logging.getLogger(__name__)
@@ -153,9 +154,9 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
153154
if gs._layoutbox is not None:
154155
gss.add(gs)
155156
if len(gss) == 0:
156-
warnings.warn('There are no gridspecs with layoutboxes. '
157-
'Possibly did not call parent GridSpec with the figure= '
158-
'keyword')
157+
cbook._warn_external('There are no gridspecs with layoutboxes. '
158+
'Possibly did not call parent GridSpec with the'
159+
' figure= keyword')
159160

160161
if fig._layoutbox.constrained_layout_called < 1:
161162
for gs in gss:
@@ -221,8 +222,8 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
221222
# so this does the same w/o zeroing layout.
222223
ax._set_position(newpos, which='original')
223224
else:
224-
warnings.warn('constrained_layout not applied. At least '
225-
'one axes collapsed to zero width or height.')
225+
cbook._warn_external('constrained_layout not applied. At least '
226+
'one axes collapsed to zero width or height.')
226227

227228

228229
def _make_ghost_gridspec_slots(fig, gs):

lib/matplotlib/artist.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from collections import OrderedDict, namedtuple
22
from functools import wraps
33
import inspect
4+
import logging
45
import re
56
import warnings
67

@@ -12,6 +13,8 @@
1213
from .transforms import (Bbox, IdentityTransform, Transform, TransformedBbox,
1314
TransformedPatchPath, TransformedPath)
1415

16+
_log = logging.getLogger(__name__)
17+
1518

1619
def allow_rasterization(draw):
1720
"""
@@ -400,7 +403,7 @@ def contains(self, mouseevent):
400403
"""
401404
if callable(self._contains):
402405
return self._contains(self, mouseevent)
403-
warnings.warn("'%s' needs 'contains' method" % self.__class__.__name__)
406+
_log.warning("'%s' needs 'contains' method" % self.__class__.__name__)
404407
return False, {}
405408

406409
def set_contains(self, picker):
@@ -850,7 +853,8 @@ def set_rasterized(self, rasterized):
850853
rasterized : bool or None
851854
"""
852855
if rasterized and not hasattr(self.draw, "_supports_rasterization"):
853-
warnings.warn("Rasterization of '%s' will be ignored" % self)
856+
cbook._warn_external(
857+
"Rasterization of '%s' will be ignored" % self)
854858

855859
self._rasterized = rasterized
856860

lib/matplotlib/axes/_axes.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4623,8 +4623,9 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None,
46234623
# Set normalizer if bins is 'log'
46244624
if bins == 'log':
46254625
if norm is not None:
4626-
warnings.warn("Only one of 'bins' and 'norm' arguments can be "
4627-
"supplied, ignoring bins={}".format(bins))
4626+
cbook._warn_external("Only one of 'bins' and 'norm' "
4627+
"arguments can be supplied, ignoring "
4628+
"bins={}".format(bins))
46284629
else:
46294630
norm = mcolors.LogNorm()
46304631
bins = None

0 commit comments

Comments
 (0)