Make subclasses of int, long, complex, float, and unicode perform type
conversion using the proper magic slot (e.g., __int__()).  Also move conversion
code out of PyNumber_*() functions in the C API into the nb_* function.

Applied patch #1109424.  Thanks Walter Doewald.
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 4e8ffe5..103d1a3 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -545,6 +545,37 @@
             self.assertEqual(float(unicode("  3.14  ")), 3.14)
             self.assertEqual(float(unicode("  \u0663.\u0661\u0664  ",'raw-unicode-escape')), 3.14)
 
+    def test_floatconversion(self):
+        # Make sure that calls to __float__() work properly
+        class Foo0:
+            def __float__(self):
+                return 42.
+
+        class Foo1(object):
+            def __float__(self):
+                return 42.
+
+        class Foo2(float):
+            def __float__(self):
+                return 42.
+
+        class Foo3(float):
+            def __new__(cls, value=0.):
+                return float.__new__(cls, 2*value)
+
+            def __float__(self):
+                return self
+
+        class Foo4(float):
+            def __float__(self):
+                return 42
+
+        self.assertAlmostEqual(float(Foo0()), 42.)
+        self.assertAlmostEqual(float(Foo1()), 42.)
+        self.assertAlmostEqual(float(Foo2()), 42.)
+        self.assertAlmostEqual(float(Foo3(21)), 42.)
+        self.assertRaises(TypeError, float, Foo4(42))
+
     def test_getattr(self):
         import sys
         self.assert_(getattr(sys, 'stdout') is sys.stdout)
@@ -650,6 +681,39 @@
 
         self.assertEqual(int('0123', 0), 83)
 
+    def test_intconversion(self):
+        # Test __int__()
+        class Foo0:
+            def __int__(self):
+                return 42
+
+        class Foo1(object):
+            def __int__(self):
+                return 42
+
+        class Foo2(int):
+            def __int__(self):
+                return 42
+
+        class Foo3(int):
+            def __int__(self):
+                return self
+
+        class Foo4(int):
+            def __int__(self):
+                return 42L
+
+        class Foo5(int):
+            def __int__(self):
+                return 42.
+
+        self.assertEqual(int(Foo0()), 42)
+        self.assertEqual(int(Foo1()), 42)
+        self.assertEqual(int(Foo2()), 42)
+        self.assertEqual(int(Foo3()), 0)
+        self.assertEqual(int(Foo4()), 42L)
+        self.assertRaises(TypeError, int, Foo5())
+
     def test_intern(self):
         self.assertRaises(TypeError, intern)
         s = "never interned before"
@@ -810,6 +874,39 @@
         self.assertRaises(ValueError, long, '53', 40)
         self.assertRaises(TypeError, long, 1, 12)
 
+    def test_longconversion(self):
+        # Test __long__()
+        class Foo0:
+            def __long__(self):
+                return 42L
+
+        class Foo1(object):
+            def __long__(self):
+                return 42L
+
+        class Foo2(long):
+            def __long__(self):
+                return 42L
+
+        class Foo3(long):
+            def __long__(self):
+                return self
+
+        class Foo4(long):
+            def __long__(self):
+                return 42
+
+        class Foo5(long):
+            def __long__(self):
+                return 42.
+
+        self.assertEqual(long(Foo0()), 42L)
+        self.assertEqual(long(Foo1()), 42L)
+        self.assertEqual(long(Foo2()), 42L)
+        self.assertEqual(long(Foo3()), 0)
+        self.assertEqual(long(Foo4()), 42)
+        self.assertRaises(TypeError, long, Foo5())
+
     def test_map(self):
         self.assertEqual(
             map(None, 'hello world'),
diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
index 15f4b65..70e91c1 100644
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -273,6 +273,28 @@
         self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
         self.assertRaises(TypeError, complex, float2(None))
 
+        class complex0(complex):
+            """Test usage of __complex__() when inheriting from 'complex'"""
+            def __complex__(self):
+                return 42j
+
+        class complex1(complex):
+            """Test usage of __complex__() with a __new__() method"""
+            def __new__(self, value=0j):
+                return complex.__new__(self, 2*value)
+            def __complex__(self):
+                return self
+
+        class complex2(complex):
+            """Make sure that __complex__() calls fail if anything other than a
+            complex is returned"""
+            def __complex__(self):
+                return None
+
+        self.assertAlmostEqual(complex(complex0(1j)), 42j)
+        self.assertAlmostEqual(complex(complex1(1j)), 2j)
+        self.assertRaises(TypeError, complex, complex2(1j))
+
     def test_hash(self):
         for x in xrange(-30, 30):
             self.assertEqual(hash(x), hash(complex(x, 0)))
diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py
index 82632f1..45942a6 100644
--- a/Lib/test/test_str.py
+++ b/Lib/test/test_str.py
@@ -19,6 +19,69 @@
         string_tests.MixinStrUnicodeUserStringTest.test_formatting(self)
         self.assertRaises(OverflowError, '%c'.__mod__, 0x1234)
 
+    def test_conversion(self):
+        # Make sure __str__() behaves properly
+        class Foo0:
+            def __unicode__(self):
+                return u"foo"
+
+        class Foo1:
+            def __str__(self):
+                return "foo"
+
+        class Foo2(object):
+            def __str__(self):
+                return "foo"
+
+        class Foo3(object):
+            def __str__(self):
+                return u"foo"
+
+        class Foo4(unicode):
+            def __str__(self):
+                return u"foo"
+
+        class Foo5(str):
+            def __str__(self):
+                return u"foo"
+
+        class Foo6(str):
+            def __str__(self):
+                return "foos"
+
+            def __unicode__(self):
+                return u"foou"
+
+        class Foo7(unicode):
+            def __str__(self):
+                return "foos"
+            def __unicode__(self):
+                return u"foou"
+
+        class Foo8(str):
+            def __new__(cls, content=""):
+                return str.__new__(cls, 2*content)
+            def __str__(self):
+                return self
+
+        class Foo9(str):
+            def __str__(self):
+                return "string"
+            def __unicode__(self):
+                return "not unicode"
+
+        self.assert_(str(Foo0()).startswith("<")) # this is different from __unicode__
+        self.assertEqual(str(Foo1()), "foo")
+        self.assertEqual(str(Foo2()), "foo")
+        self.assertEqual(str(Foo3()), "foo")
+        self.assertEqual(str(Foo4("bar")), "foo")
+        self.assertEqual(str(Foo5("bar")), "foo")
+        self.assertEqual(str(Foo6("bar")), "foos")
+        self.assertEqual(str(Foo7("bar")), "foos")
+        self.assertEqual(str(Foo8("foo")), "foofoo")
+        self.assertEqual(str(Foo9("foo")), "string")
+        self.assertEqual(unicode(Foo9("foo")), u"not unicode")
+
 def test_main():
     test_support.run_unittest(StrTest)
 
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index 69244f0..80242d5 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -389,7 +389,6 @@
         self.assertEqual('%i%s %*.*s' % (10, 3, 5, 3, u'abc',), u'103   abc')
         self.assertEqual('%c' % u'a', u'a')
 
-
     def test_constructor(self):
         # unicode(obj) tests (this maps to PyObject_Unicode() at C level)
 
@@ -725,6 +724,69 @@
         y = x.encode("raw-unicode-escape").decode("raw-unicode-escape")
         self.assertEqual(x, y)
 
+    def test_conversion(self):
+        # Make sure __unicode__() works properly
+        class Foo0:
+            def __str__(self):
+                return "foo"
+
+        class Foo1:
+            def __unicode__(self):
+                return u"foo"
+
+        class Foo2(object):
+            def __unicode__(self):
+                return u"foo"
+
+        class Foo3(object):
+            def __unicode__(self):
+                return "foo"
+
+        class Foo4(str):
+            def __unicode__(self):
+                return "foo"
+
+        class Foo5(unicode):
+            def __unicode__(self):
+                return "foo"
+
+        class Foo6(str):
+            def __str__(self):
+                return "foos"
+
+            def __unicode__(self):
+                return u"foou"
+
+        class Foo7(unicode):
+            def __str__(self):
+                return "foos"
+            def __unicode__(self):
+                return u"foou"
+
+        class Foo8(unicode):
+            def __new__(cls, content=""):
+                return unicode.__new__(cls, 2*content)
+            def __unicode__(self):
+                return self
+
+        class Foo9(unicode):
+            def __str__(self):
+                return "string"
+            def __unicode__(self):
+                return "not unicode"
+
+        self.assertEqual(unicode(Foo0()), u"foo")
+        self.assertEqual(unicode(Foo1()), u"foo")
+        self.assertEqual(unicode(Foo2()), u"foo")
+        self.assertEqual(unicode(Foo3()), u"foo")
+        self.assertEqual(unicode(Foo4("bar")), u"foo")
+        self.assertEqual(unicode(Foo5("bar")), u"foo")
+        self.assertEqual(unicode(Foo6("bar")), u"foou")
+        self.assertEqual(unicode(Foo7("bar")), u"foou")
+        self.assertEqual(unicode(Foo8("foo")), u"foofoo")
+        self.assertEqual(str(Foo9("foo")), "string")
+        self.assertEqual(unicode(Foo9("foo")), u"not unicode")
+
 def test_main():
     test_support.run_unittest(UnicodeTest)