bpo-32230: Set sys.warnoptions with -X dev (#4820)

Rather than supporting dev mode directly in the warnings module, this
instead adjusts the initialisation code to add an extra 'default'
entry to sys.warnoptions when dev mode is enabled.

This ensures that dev mode behaves *exactly* as if `-Wdefault` had
been passed on the command line, including in the way it interacts
with `sys.warnoptions`, and with other command line flags like `-bb`.

Fix also bpo-20361: have -b & -bb options take precedence over any
other warnings options.

Patch written by Nick Coghlan, with minor modifications of Victor Stinner.
This commit is contained in:
Victor Stinner 2017-12-12 22:59:48 +01:00 committed by GitHub
parent b748e3b258
commit 747f48e2e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 224 additions and 124 deletions

View file

@ -11,9 +11,9 @@ MODULE_NAME " provides basic warning filtering support.\n"
_Py_IDENTIFIER(argv);
_Py_IDENTIFIER(stderr);
#ifndef Py_DEBUG
_Py_IDENTIFIER(ignore);
_Py_IDENTIFIER(error);
_Py_static_string(PyId_default, "default");
#endif
static int
check_matched(PyObject *obj, PyObject *arg)
@ -1156,6 +1156,7 @@ static PyMethodDef warnings_functions[] = {
};
#ifndef Py_DEBUG
static PyObject *
create_filter(PyObject *category, _Py_Identifier *id)
{
@ -1168,61 +1169,31 @@ create_filter(PyObject *category, _Py_Identifier *id)
return PyTuple_Pack(5, action_str, Py_None,
category, Py_None, _PyLong_Zero);
}
#endif
static PyObject *
init_filters(const _PyCoreConfig *config)
{
int dev_mode = config->dev_mode;
Py_ssize_t count = 2;
if (dev_mode) {
count++;
}
#ifndef Py_DEBUG
if (!dev_mode) {
count += 3;
}
#endif
PyObject *filters = PyList_New(count);
if (filters == NULL)
#ifdef Py_DEBUG
/* Py_DEBUG builds show all warnings by default */
return PyList_New(0);
#else
/* Other builds ignore a number of warning categories by default */
PyObject *filters = PyList_New(4);
if (filters == NULL) {
return NULL;
}
size_t pos = 0; /* Post-incremented in each use. */
#ifndef Py_DEBUG
if (!dev_mode) {
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_DeprecationWarning, &PyId_ignore));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_PendingDeprecationWarning, &PyId_ignore));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ImportWarning, &PyId_ignore));
}
#endif
_Py_Identifier *bytes_action;
if (Py_BytesWarningFlag > 1)
bytes_action = &PyId_error;
else if (Py_BytesWarningFlag)
bytes_action = &PyId_default;
else
bytes_action = &PyId_ignore;
PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,
bytes_action));
_Py_Identifier *resource_action;
/* resource usage warnings are enabled by default in pydebug mode */
#ifdef Py_DEBUG
resource_action = &PyId_default;
#else
resource_action = (dev_mode ? &PyId_default: &PyId_ignore);
#endif
PyList_SET_ITEM(filters, pos++, create_filter(PyExc_ResourceWarning,
resource_action));
if (dev_mode) {
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_Warning, &PyId_default));
}
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_DeprecationWarning, &PyId_ignore));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_PendingDeprecationWarning, &PyId_ignore));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ImportWarning, &PyId_ignore));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ResourceWarning, &PyId_ignore));
for (size_t x = 0; x < pos; x++) {
if (PyList_GET_ITEM(filters, x) == NULL) {
@ -1230,8 +1201,8 @@ init_filters(const _PyCoreConfig *config)
return NULL;
}
}
return filters;
#endif
}
static struct PyModuleDef warningsmodule = {