diff --git a/Include/warnings.h b/Include/warnings.h index ef6005e93ebd37..47e920daf56750 100644 --- a/Include/warnings.h +++ b/Include/warnings.h @@ -7,6 +7,7 @@ extern "C" { PyAPI_FUNC(void) _PyWarnings_Init(void); PyAPI_FUNC(int) PyErr_WarnEx(PyObject *, const char *, Py_ssize_t); +PyAPI_FUNC(int) PyErr_WarnEx_WithFix(PyObject *, const char *, const char *, Py_ssize_t); PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *, const char *, int, const char *, PyObject *); PyAPI_FUNC(int) PyErr_WarnExplicit_WithFix(PyObject *, const char *, const char *, const char *, int, diff --git a/Lib/test/test_sort.py b/Lib/test/test_sort.py index d75abc49173f40..590f6f4a4d693d 100644 --- a/Lib/test/test_sort.py +++ b/Lib/test/test_sort.py @@ -278,6 +278,11 @@ def test_main(verbose=None): ("the cmp argument is not supported", DeprecationWarning)): test_support.run_unittest(*test_classes) + with test_support.check_py3k_warnings( + ("the cmp method is not supported in 3.x" + "implement the function to a utility library", Py3xWarning)): + test_support.run_unittest(*test_classes) + # verify reference counting if verbose and hasattr(sys, "gettotalrefcount"): import gc diff --git a/Objects/object.c b/Objects/object.c index 65366b0b351b4c..825cfe0cb612ab 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -860,6 +860,13 @@ PyObject_Compare(PyObject *v, PyObject *w) { int result; + if (Py_Py3kWarningFlag && + PyErr_WarnEx_WithFix(PyExc_Py3xWarning, "the cmp method is not supported in 3.x", + "you can either provide your own alternative or use a third party library with a " + "backwards compatible fix", 1) < 0) { + return 0; + } + if (v == NULL || w == NULL) { PyErr_BadInternalCall(); return -1; diff --git a/Python/_warnings.c b/Python/_warnings.c index 47f3646e8ae7e1..4b9147880206b8 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -817,6 +817,23 @@ do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level) return res; } +static PyObject * +do_warn_with_fix(PyObject *message, PyObject *fix, PyObject *category, Py_ssize_t stack_level) +{ + PyObject *filename, *module, *registry, *res; + int lineno; + + if (!setup_context(stack_level, &filename, &lineno, &module, ®istry)) + return NULL; + + res = warn_explicit_with_fix(category, message, fix, filename, lineno, module, registry, + NULL); + Py_DECREF(filename); + Py_DECREF(registry); + Py_DECREF(module); + return res; +} + static PyObject * warnings_warn(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1029,8 +1046,28 @@ PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) return 0; } -/* PyErr_Warn is only for backwards compatibility and will be removed. - Use PyErr_WarnEx instead. */ +/* Function to issue a warning message; may raise an exception. */ +int +PyErr_WarnEx_WithFix(PyObject *category, const char *text, const char *fix_txt, Py_ssize_t stack_level) +{ + PyObject *res; + PyObject *message = PyString_FromString(text); + PyObject *fix = PyString_FromString(fix_txt); + if (message == NULL) + return -1; + + if (category == NULL) + category = PyExc_RuntimeWarning; + + res = do_warn_with_fix(message, fix, category, stack_level); + Py_DECREF(message); + Py_DECREF(fix); + if (res == NULL) + return -1; + Py_DECREF(res); + + return 0; +} #undef PyErr_Warn