Merged revisions 62774-62775,62785,62787-62788 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r62774 | georg.brandl | 2008-05-06 19:11:42 +0200 (Tue, 06 May 2008) | 2 lines

  #2773: fix description of 'g' and 'G' formatting spec.
........
  r62775 | georg.brandl | 2008-05-06 19:20:54 +0200 (Tue, 06 May 2008) | 2 lines

  > != (!<).
........
  r62785 | benjamin.peterson | 2008-05-07 00:18:11 +0200 (Wed, 07 May 2008) | 2 lines

  Fix logic error in Python/_warnings.c and add a test to verify
........
  r62787 | benjamin.peterson | 2008-05-07 00:31:52 +0200 (Wed, 07 May 2008) | 2 lines

  Make the Python implementation of warnings compatible with the C implementation regarding non-callable showwarning
........
  r62788 | christian.heimes | 2008-05-07 00:41:46 +0200 (Wed, 07 May 2008) | 1 line

  Implemented PEP 370
........
diff --git a/Python/_warnings.c b/Python/_warnings.c
index d03b452..12b1021 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -378,15 +378,47 @@
             show_warning(filename, lineno, text, category, sourceline);
         }
         else {
-            PyObject *res;
-            
-            res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
+            const char *msg = "functions overriding warnings.showwarning() "
+                                "must support the 'line' argument";
+            const char *text_char = PyUnicode_AsString(text);
+
+            if (strcmp(msg, text_char) == 0) {
+                /* Prevent infinite recursion by using built-in implementation
+                   of showwarning(). */
+                show_warning(filename, lineno, text, category, sourceline);
+            }
+            else {
+                PyObject *check_fxn;
+                PyObject *defaults;
+                PyObject *res;
+
+                if (PyMethod_Check(show_fxn))
+                    check_fxn = PyMethod_Function(show_fxn);
+                else if (PyFunction_Check(show_fxn))
+                    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)) {
+                    if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) < 0)
+                        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;
+                Py_DECREF(show_fxn);
+                Py_XDECREF(res);
+                if (res == NULL)
+                    goto cleanup;
+            }
         }
     }
     else /* if (rc == -1) */