Skip to content

Commit 6fdd3dc

Browse files
committed
DeprecationWarning is now silent by default.
This was originally suggested by Guido, discussed on the stdlib-sig mailing list, and given the OK by Guido directly to me. What this change essentially means is that Python has taken a policy of silencing warnings that are only of interest to developers by default. This should prevent users from seeing warnings which are triggered by an application being run against a new interpreter before the app developer has a chance to update their code. Closes issue #7319. Thanks to Antoine Pitrou, Ezio Melotti, and Brian Curtin for helping with the issue.
1 parent 3ad57e2 commit 6fdd3dc

6 files changed

Lines changed: 65 additions & 31 deletions

File tree

‎Doc/library/warnings.rst‎

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ following warnings category classes are currently defined:
5959
| :exc:`UserWarning` | The default category for :func:`warn`. |
6060
+----------------------------------+-----------------------------------------------+
6161
| :exc:`DeprecationWarning` | Base category for warnings about deprecated |
62-
| | features. |
62+
| | features (ignored by default). |
6363
+----------------------------------+-----------------------------------------------+
6464
| :exc:`SyntaxWarning` | Base category for warnings about dubious |
6565
| | syntactic features. |
@@ -89,6 +89,9 @@ User code can define additional warning categories by subclassing one of the
8989
standard warning categories. A warning category must always be a subclass of
9090
the :exc:`Warning` class.
9191

92+
.. versionchanged:: 2.7
93+
:exc:`DeprecationWarning` is ignored by default.
94+
9295

9396
.. _warning-filter:
9497

@@ -148,14 +151,6 @@ interpreter command line. The interpreter saves the arguments for all
148151
:mod:`warnings` module parses these when it is first imported (invalid options
149152
are ignored, after printing a message to ``sys.stderr``).
150153

151-
The warnings that are ignored by default may be enabled by passing :option:`-Wd`
152-
to the interpreter. This enables default handling for all warnings, including
153-
those that are normally ignored by default. This is particular useful for
154-
enabling ImportWarning when debugging problems importing a developed package.
155-
ImportWarning can also be enabled explicitly in Python code using::
156-
157-
warnings.simplefilter('default', ImportWarning)
158-
159154

160155
.. _warning-suppress:
161156

@@ -226,6 +221,37 @@ continues to increase after each operation, or else delete the previous
226221
entries from the warnings list before each new operation).
227222

228223

224+
Updating Code For New Versions of Python
225+
----------------------------------------
226+
227+
Warnings that are only of interest to the developer are ignored by default. As
228+
such you should make sure to test your code with typically ignored warnings
229+
made visible. You can do this from the command-line by passing :option:`-Wd`
230+
to the interpreter (this is shorthand for :option:`-W default`). This enables
231+
default handling for all warnings, including those that are ignored by default.
232+
To change what action is taken for encountered warnings you simply change what
233+
argument is passed to :option:`-W`, e.g. :option:`-W error`. See the
234+
:option:`-W` flag for more details on what is possible.
235+
236+
To programmatically do the same as :option:`-Wd`, use::
237+
238+
warnings.simplefilter('default')
239+
240+
Make sure to execute this code as soon as possible. This prevents the
241+
registering of what warnings have been raised from unexpectedly influencing how
242+
future warnings are treated.
243+
244+
Having certain warnings ignored by default is done to prevent a user from
245+
seeing warnings that are only of interest to the developer. As you do not
246+
necessarily have control over what interpreter a user uses to run their code,
247+
it is possible that a new version of Python will be released between your
248+
release cycles. The new interpreter release could trigger new warnings in your
249+
code that were not there in an older interpreter, e.g.
250+
:exc:`DeprecationWarning` for a module that you are using. While you as a
251+
developer want to be notified that your code is using a deprecated module, to a
252+
user this information is essentially noise and provides no benefit to them.
253+
254+
229255
.. _warning-functions:
230256

231257
Available Functions

‎Lib/test/test_ascii_formatd.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import unittest
66
from test_support import check_warnings, run_unittest, cpython_only
7+
import warnings
78

89

910
class FormatDeprecationTests(unittest.TestCase):
@@ -17,6 +18,7 @@ def testFormatDeprecation(self):
1718
buf = create_string_buffer(' ' * 100)
1819

1920
with check_warnings() as w:
21+
warnings.simplefilter('default')
2022
PyOS_ascii_formatd(byref(buf), sizeof(buf), '%+.10f',
2123
c_double(10.0))
2224
self.assertEqual(buf.value, '+10.0000000000')

‎Lib/test/test_exceptions.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ def testDeprecatedMessageAttribute(self):
309309
# BaseException.__init__ triggers a deprecation warning.
310310
exc = BaseException("foo")
311311
with warnings.catch_warnings(record=True) as w:
312+
warnings.simplefilter('default')
312313
self.assertEquals(exc.message, "foo")
313314
self.assertEquals(len(w), 1)
314315
self.assertEquals(w[0].category, DeprecationWarning)

‎Lib/warnings.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ def __exit__(self, *exc_info):
383383
# Module initialization
384384
_processoptions(sys.warnoptions)
385385
if not _warnings_defaults:
386-
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
387-
simplefilter("ignore", category=ImportWarning, append=1)
386+
for cls in (DeprecationWarning, PendingDeprecationWarning, ImportWarning):
387+
simplefilter("ignore", category=cls, append=True)
388388
bytes_warning = sys.flags.bytes_warning
389389
if bytes_warning > 1:
390390
bytes_action = "error"

‎Misc/NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ What's New in Python 2.7 alpha 3?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #7319: Silence DeprecationWarning by default.
16+
1517
- Issue #2335: Backport set literals syntax from Python 3.x.
1618

1719
Library

‎Python/_warnings.c‎

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ get_default_action(void)
8585

8686
default_action = get_warnings_attr("defaultaction");
8787
if (default_action == NULL) {
88-
if (PyErr_Occurred()) {
89-
return NULL;
90-
}
91-
return _default_action;
88+
if (PyErr_Occurred()) {
89+
return NULL;
90+
}
91+
return _default_action;
9292
}
9393

9494
Py_DECREF(_default_action);
@@ -202,12 +202,12 @@ normalize_module(PyObject *filename)
202202

203203
mod_str = PyString_AsString(filename);
204204
if (mod_str == NULL)
205-
return NULL;
205+
return NULL;
206206
len = PyString_Size(filename);
207207
if (len < 0)
208208
return NULL;
209209
if (len >= 3 &&
210-
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
210+
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
211211
module = PyString_FromStringAndSize(mod_str, len-3);
212212
}
213213
else {
@@ -251,7 +251,7 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
251251

252252
name = PyObject_GetAttrString(category, "__name__");
253253
if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */
254-
return;
254+
return;
255255

256256
f_stderr = PySys_GetObject("stderr");
257257
if (f_stderr == NULL) {
@@ -341,7 +341,7 @@ warn_explicit(PyObject *category, PyObject *message,
341341
rc = already_warned(registry, key, 0);
342342
if (rc == -1)
343343
goto cleanup;
344-
else if (rc == 1)
344+
else if (rc == 1)
345345
goto return_none;
346346
/* Else this warning hasn't been generated before. */
347347
}
@@ -492,9 +492,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
492492
/* Setup filename. */
493493
*filename = PyDict_GetItemString(globals, "__file__");
494494
if (*filename != NULL) {
495-
Py_ssize_t len = PyString_Size(*filename);
495+
Py_ssize_t len = PyString_Size(*filename);
496496
const char *file_str = PyString_AsString(*filename);
497-
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
497+
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
498498
goto handle_error;
499499

500500
/* if filename.lower().endswith((".pyc", ".pyo")): */
@@ -506,10 +506,10 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
506506
tolower(file_str[len-1]) == 'o'))
507507
{
508508
*filename = PyString_FromStringAndSize(file_str, len-1);
509-
if (*filename == NULL)
510-
goto handle_error;
511-
}
512-
else
509+
if (*filename == NULL)
510+
goto handle_error;
511+
}
512+
else
513513
Py_INCREF(*filename);
514514
}
515515
else {
@@ -536,8 +536,8 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
536536
else {
537537
/* embedded interpreters don't have sys.argv, see bug #839151 */
538538
*filename = PyString_FromString("__main__");
539-
if (*filename == NULL)
540-
goto handle_error;
539+
if (*filename == NULL)
540+
goto handle_error;
541541
}
542542
}
543543
if (*filename == NULL) {
@@ -839,26 +839,29 @@ create_filter(PyObject *category, const char *action)
839839
static PyObject *
840840
init_filters(void)
841841
{
842-
PyObject *filters = PyList_New(3);
842+
PyObject *filters = PyList_New(4);
843843
const char *bytes_action;
844844
if (filters == NULL)
845845
return NULL;
846846

847847
PyList_SET_ITEM(filters, 0,
848+
create_filter(PyExc_DeprecationWarning, "ignore"));
849+
PyList_SET_ITEM(filters, 1,
848850
create_filter(PyExc_PendingDeprecationWarning, "ignore"));
849-
PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
851+
PyList_SET_ITEM(filters, 2, create_filter(PyExc_ImportWarning, "ignore"));
850852
if (Py_BytesWarningFlag > 1)
851853
bytes_action = "error";
852854
else if (Py_BytesWarningFlag)
853855
bytes_action = "default";
854856
else
855857
bytes_action = "ignore";
856-
PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
858+
PyList_SET_ITEM(filters, 3, create_filter(PyExc_BytesWarning,
857859
bytes_action));
858860

859861
if (PyList_GET_ITEM(filters, 0) == NULL ||
860862
PyList_GET_ITEM(filters, 1) == NULL ||
861-
PyList_GET_ITEM(filters, 2) == NULL) {
863+
PyList_GET_ITEM(filters, 2) == NULL ||
864+
PyList_GET_ITEM(filters, 3) == NULL) {
862865
Py_DECREF(filters);
863866
return NULL;
864867
}

0 commit comments

Comments
 (0)