Index: Python/_warnings.c =================================================================== --- Python/_warnings.c (revision 65970) +++ Python/_warnings.c (working copy) @@ -258,6 +258,8 @@ /* Print " source_line\n" */ if (sourceline) { char *source_line_str = _PyUnicode_AsString(sourceline); + if (source_line_str == NULL) + return; while (*source_line_str == ' ' || *source_line_str == '\t' || *source_line_str == '\014') source_line_str++; @@ -266,8 +268,9 @@ PyFile_WriteString("\n", f_stderr); } else - _Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename), - lineno, 2); + if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename), + lineno, 2) < 0) + return; PyErr_Clear(); } @@ -366,8 +369,11 @@ PyObject *to_str = PyObject_Str(item); const char *err_str = "???"; - if (to_str != NULL) + if (to_str != NULL) { err_str = _PyUnicode_AsString(to_str); + if (err_str == NULL) + goto cleanup; + } PyErr_Format(PyExc_RuntimeError, "Unrecognized action (%s) in warnings.filters:\n %s", action, err_str); @@ -388,9 +394,15 @@ else { const char *msg = "functions overriding warnings.showwarning() " "must support the 'line' argument"; - const char *text_char = _PyUnicode_AsString(text); + const char *text_char = NULL; + + if (PyUnicode_Check(text)) { + text_char = _PyUnicode_AsString(text); + if (text_char == NULL) + goto cleanup; + } - if (strcmp(msg, text_char) == 0) { + if (text_char && strcmp(msg, text_char) == 0) { /* Prevent infinite recursion by using built-in implementation of showwarning(). */ show_warning(filename, lineno, text, category, sourceline); @@ -524,7 +536,9 @@ } else { const char *module_str = _PyUnicode_AsString(*module); - if (module_str && strcmp(module_str, "__main__") == 0) { + if (module_str == NULL) + goto handle_error; + if (strcmp(module_str, "__main__") == 0) { PyObject *argv = PySys_GetObject("argv"); if (argv != NULL && PyList_Size(argv) > 0) { int is_true; Index: Lib/test/test_warnings.py =================================================================== --- Lib/test/test_warnings.py (revision 65970) +++ Lib/test/test_warnings.py (working copy) @@ -203,6 +203,16 @@ self.assertEqual(str(w.message), text) self.assert_(w.category is UserWarning) + # Issue 3639 + def test_warn_nonstandard_types(self): + # warn() should handle non-standard types without issue. + for ob in (Warning, None, 42): + with support.catch_warning(self.module) as w: + self.module.warn(ob) + # Don't directly compare objects since + # ``Warning() != Warning()``. + self.assertEquals(str(w.message), str(UserWarning(ob))) + def test_filename(self): with warnings_state(self.module): with support.catch_warning(self.module) as w: @@ -317,7 +327,6 @@ None, Warning, None, 1, registry=42) - class CWarnTests(BaseTest, WarnTests): module = c_warnings