The _warnings module did not properly handle cases where strings were not being
passed in as the message to use for a warning. Fixed along with making the code
more robust against other errors where return values were not checked.

Closes issue 3639.
Code review by Benjamin Peterson.
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
index cd408cf..087bf3d 100644
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -202,6 +202,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:
@@ -315,7 +325,6 @@
                             self.module.warn_explicit,
                             None, Warning, None, 1, registry=42)
 
-
 class CWarnTests(BaseTest, WarnTests):
     module = c_warnings