Commit 6c4cff0f authored by Brett Cannon's avatar Brett Cannon

Require implementations for warnings.showwarning() support the 'line' argument.

Was a DeprecationWarning for not supporting it since Python 2.6.

Closes issue #3652.
parent 8f19598f
...@@ -291,9 +291,8 @@ Available Functions ...@@ -291,9 +291,8 @@ Available Functions
message; if *line* is not supplied, :func:`showwarning` will message; if *line* is not supplied, :func:`showwarning` will
try to read the line specified by *filename* and *lineno*. try to read the line specified by *filename* and *lineno*.
.. versionchanged:: 2.6 .. versionchanged:: 2.7
Added the *line* argument. Implementations that lack the new argument The *line* argument is required to be supported.
will trigger a :exc:`DeprecationWarning`.
.. function:: formatwarning(message, category, filename, lineno[, line]) .. function:: formatwarning(message, category, filename, lineno[, line])
......
...@@ -605,41 +605,6 @@ class PyCatchWarningTests(CatchWarningTests): ...@@ -605,41 +605,6 @@ class PyCatchWarningTests(CatchWarningTests):
module = py_warnings module = py_warnings
class ShowwarningDeprecationTests(BaseTest):
"""Test the deprecation of the old warnings.showwarning() API works."""
@staticmethod
def bad_showwarning(message, category, filename, lineno, file=None):
pass
@staticmethod
def ok_showwarning(*args):
pass
def test_deprecation(self):
# message, category, filename, lineno[, file[, line]]
args = ("message", UserWarning, "file name", 42)
with original_warnings.catch_warnings(module=self.module):
self.module.filterwarnings("error", category=DeprecationWarning)
self.module.showwarning = self.bad_showwarning
self.assertRaises(DeprecationWarning, self.module.warn_explicit,
*args)
self.module.showwarning = self.ok_showwarning
try:
self.module.warn_explicit(*args)
except DeprecationWarning as exc:
self.fail('showwarning(*args) should not trigger a '
'DeprecationWarning')
class CShowwarningDeprecationTests(ShowwarningDeprecationTests):
module = c_warnings
class PyShowwarningDeprecationTests(ShowwarningDeprecationTests):
module = py_warnings
def test_main(): def test_main():
py_warnings.onceregistry.clear() py_warnings.onceregistry.clear()
c_warnings.onceregistry.clear() c_warnings.onceregistry.clear()
...@@ -649,8 +614,6 @@ def test_main(): ...@@ -649,8 +614,6 @@ def test_main():
_WarningsTests, _WarningsTests,
CWarningsDisplayTests, PyWarningsDisplayTests, CWarningsDisplayTests, PyWarningsDisplayTests,
CCatchWarningTests, PyCatchWarningTests, CCatchWarningTests, PyCatchWarningTests,
CShowwarningDeprecationTests,
PyShowwarningDeprecationTests,
) )
......
...@@ -262,24 +262,6 @@ def warn_explicit(message, category, filename, lineno, ...@@ -262,24 +262,6 @@ def warn_explicit(message, category, filename, lineno,
raise RuntimeError( raise RuntimeError(
"Unrecognized action (%r) in warnings.filters:\n %s" % "Unrecognized action (%r) in warnings.filters:\n %s" %
(action, item)) (action, item))
# Warn if showwarning() does not support the 'line' argument.
# Don't use 'inspect' as it relies on an extension module, which break the
# build thanks to 'warnings' being imported by setup.py.
fxn_code = None
if hasattr(showwarning, 'func_code'):
fxn_code = showwarning.func_code
elif hasattr(showwarning, '__func__'):
fxn_code = showwarning.__func__.func_code
if fxn_code:
args = fxn_code.co_varnames[:fxn_code.co_argcount]
CO_VARARGS = 0x4
if 'line' not in args and not fxn_code.co_flags & CO_VARARGS:
showwarning_msg = ("functions overriding warnings.showwarning() "
"must support the 'line' argument")
if message == showwarning_msg:
_show_warning(message, category, filename, lineno)
else:
warn(showwarning_msg, DeprecationWarning)
# Print message and context # Print message and context
showwarning(message, category, filename, lineno) showwarning(message, category, filename, lineno)
......
...@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1 ...@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #3652: Make the 'line' argument for warnings.showwarning() a
requirement. Means the DeprecationWarning from Python 2.6 can go away.
- Issue #5247: Improve error message when unknown format codes are - Issue #5247: Improve error message when unknown format codes are
used when using str.format() with str, unicode, long, int, and used when using str.format() with str, unicode, long, int, and
float arguments. float arguments.
......
#include "Python.h" #include "Python.h"
#include "code.h" /* For DeprecationWarning about adding 'line'. */
#include "frameobject.h" #include "frameobject.h"
#define MODULE_NAME "_warnings" #define MODULE_NAME "_warnings"
...@@ -387,54 +386,23 @@ warn_explicit(PyObject *category, PyObject *message, ...@@ -387,54 +386,23 @@ warn_explicit(PyObject *category, PyObject *message,
show_warning(filename, lineno, text, category, sourceline); show_warning(filename, lineno, text, category, sourceline);
} }
else { else {
const char *msg = "functions overriding warnings.showwarning() " PyObject *res;
"must support the 'line' argument";
const char *text_char = PyString_AS_STRING(text); if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) {
PyErr_SetString(PyExc_TypeError,
if (strcmp(msg, text_char) == 0) { "warnings.showwarning() must be set to a "
/* Prevent infinite recursion by using built-in implementation "function or method");
of showwarning(). */ Py_DECREF(show_fxn);
show_warning(filename, lineno, text, category, sourceline); goto cleanup;
} }
else {
PyObject *check_fxn; res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
PyObject *defaults; filename, lineno_obj,
PyObject *res; NULL);
Py_DECREF(show_fxn);
if (PyMethod_Check(show_fxn)) Py_XDECREF(res);
check_fxn = PyMethod_Function(show_fxn); if (res == NULL)
else if (PyFunction_Check(show_fxn)) goto cleanup;
check_fxn = show_fxn;
else {
PyErr_SetString(PyExc_TypeError,
"warnings.showwarning() must be set to a "
"function or method");
Py_DECREF(show_fxn);
goto cleanup;
}
defaults = PyFunction_GetDefaults(check_fxn);
/* A proper implementation of warnings.showwarning() should
have at least two default arguments. */
if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) {
PyCodeObject *code = (PyCodeObject *)
PyFunction_GetCode(check_fxn);
if (!(code->co_flags & CO_VARARGS)) {
if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) <
0) {
Py_DECREF(show_fxn);
goto cleanup;
}
}
}
res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
filename, lineno_obj,
NULL);
Py_DECREF(show_fxn);
Py_XDECREF(res);
if (res == NULL)
goto cleanup;
}
} }
} }
else /* if (rc == -1) */ else /* if (rc == -1) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment