bpo-31975 (PEP 565): Show DeprecationWarning in __main__ (GH-4458)

- primary change is to add a new default filter entry for
  'default::DeprecationWarning:__main__'
- secondary change is an internal one to cope with plain
  strings in the warning module's internal filter list
  (this avoids the need to create a compiled regex object
  early on during interpreter startup)
- assorted documentation updates, including many more
  examples of configuring the warnings settings
- additional tests to ensure that both the pure Python and
  the C accelerated warnings modules have the expected
  default configuration
This commit is contained in:
Nick Coghlan 2018-01-08 12:45:02 +10:00 committed by GitHub
parent d13889214a
commit 9b99747386
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 329 additions and 120 deletions

View file

@ -12,6 +12,7 @@ MODULE_NAME " provides basic warning filtering support.\n"
_Py_IDENTIFIER(argv);
_Py_IDENTIFIER(stderr);
#ifndef Py_DEBUG
_Py_IDENTIFIER(default);
_Py_IDENTIFIER(ignore);
#endif
@ -22,8 +23,20 @@ check_matched(PyObject *obj, PyObject *arg)
_Py_IDENTIFIER(match);
int rc;
/* A 'None' filter always matches */
if (obj == Py_None)
return 1;
/* An internal plain text default filter must match exactly */
if (PyUnicode_CheckExact(obj)) {
int cmp_result = PyUnicode_Compare(obj, arg);
if (cmp_result == -1 && PyErr_Occurred()) {
return -1;
}
return !cmp_result;
}
/* Otherwise assume a regex filter and call its match() method */
result = _PyObject_CallMethodIdObjArgs(obj, &PyId_match, arg, NULL);
if (result == NULL)
return -1;
@ -1158,16 +1171,27 @@ static PyMethodDef warnings_functions[] = {
#ifndef Py_DEBUG
static PyObject *
create_filter(PyObject *category, _Py_Identifier *id)
create_filter(PyObject *category, _Py_Identifier *id, const char *modname)
{
PyObject *modname_obj = NULL;
PyObject *action_str = _PyUnicode_FromId(id);
if (action_str == NULL) {
return NULL;
}
/* Default to "no module name" for initial filter set */
if (modname != NULL) {
modname_obj = PyUnicode_InternFromString(modname);
if (modname_obj == NULL) {
return NULL;
}
} else {
modname_obj = Py_None;
}
/* This assumes the line number is zero for now. */
return PyTuple_Pack(5, action_str, Py_None,
category, Py_None, _PyLong_Zero);
category, modname_obj, _PyLong_Zero);
}
#endif
@ -1180,20 +1204,22 @@ init_filters(void)
return PyList_New(0);
#else
/* Other builds ignore a number of warning categories by default */
PyObject *filters = PyList_New(4);
PyObject *filters = PyList_New(5);
if (filters == NULL) {
return NULL;
}
size_t pos = 0; /* Post-incremented in each use. */
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_DeprecationWarning, &PyId_ignore));
create_filter(PyExc_DeprecationWarning, &PyId_default, "__main__"));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_PendingDeprecationWarning, &PyId_ignore));
create_filter(PyExc_DeprecationWarning, &PyId_ignore, NULL));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ImportWarning, &PyId_ignore));
create_filter(PyExc_PendingDeprecationWarning, &PyId_ignore, NULL));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ResourceWarning, &PyId_ignore));
create_filter(PyExc_ImportWarning, &PyId_ignore, NULL));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ResourceWarning, &PyId_ignore, NULL));
for (size_t x = 0; x < pos; x++) {
if (PyList_GET_ITEM(filters, x) == NULL) {