Merged revisions 80758 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r80758 | mark.dickinson | 2010-05-04 17:18:25 +0100 (Tue, 04 May 2010) | 9 lines

  Issue #1533: fix inconsistency in range function argument processing:
  any non-float non-integer argument is now converted to an integer (if
  possible) using its __int__ method.  Previously, only small arguments
  were treated this way; larger arguments (those whose __int__ was
  outside the range of a C long) would produce a TypeError.

  Patch by Alexander Belopolsky (with minor modifications).
........
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 04c2216..d1d2bd0 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -3,7 +3,7 @@
 import platform
 import test.test_support, unittest
 from test.test_support import fcmp, have_unicode, TESTFN, unlink, \
-                              run_unittest, run_with_locale
+    run_unittest, run_with_locale, check_warnings
 from operator import neg
 
 import sys, warnings, cStringIO, random, fractions, UserDict
@@ -1074,6 +1074,10 @@
         # Reject floats when it would require PyLongs to represent.
         # (smaller floats still accepted, but deprecated)
         self.assertRaises(TypeError, range, 1e100, 1e101, 1e101)
+        with check_warnings() as w:
+            warnings.simplefilter("always")
+            self.assertEqual(range(1.0), [0])
+            self.assertEqual(w.category, DeprecationWarning)
 
         self.assertRaises(TypeError, range, 0, "spam")
         self.assertRaises(TypeError, range, 0, 42, "spam")
@@ -1081,6 +1085,54 @@
         self.assertRaises(OverflowError, range, -sys.maxint, sys.maxint)
         self.assertRaises(OverflowError, range, 0, 2*sys.maxint)
 
+        bignum = 2*sys.maxint
+        smallnum = 42
+        # Old-style user-defined class with __int__ method
+        class I0:
+            def __init__(self, n):
+                self.n = int(n)
+            def __int__(self):
+                return self.n
+        self.assertEqual(range(I0(bignum), I0(bignum + 1)), [bignum])
+        self.assertEqual(range(I0(smallnum), I0(smallnum + 1)), [smallnum])
+
+        # New-style user-defined class with __int__ method
+        class I1(object):
+            def __init__(self, n):
+                self.n = int(n)
+            def __int__(self):
+                return self.n
+        self.assertEqual(range(I1(bignum), I1(bignum + 1)), [bignum])
+        self.assertEqual(range(I1(smallnum), I1(smallnum + 1)), [smallnum])
+
+        # New-style user-defined class with failing __int__ method
+        class IX(object):
+            def __int__(self):
+                raise RuntimeError
+        self.assertRaises(RuntimeError, range, IX())
+
+        # New-style user-defined class with invalid __int__ method
+        class IN(object):
+            def __int__(self):
+                return "not a number"
+        self.assertRaises(TypeError, range, IN())
+
+        # Exercise various combinations of bad arguments, to check
+        # refcounting logic
+        self.assertRaises(TypeError, range, 1e100)
+
+        self.assertRaises(TypeError, range, 0, 1e100)
+        self.assertRaises(TypeError, range, 1e100, 0)
+        self.assertRaises(TypeError, range, 1e100, 1e100)
+
+        self.assertRaises(TypeError, range, 0, 0, 1e100)
+        self.assertRaises(TypeError, range, 0, 1e100, 1)
+        self.assertRaises(TypeError, range, 0, 1e100, 1e100)
+        self.assertRaises(TypeError, range, 1e100, 0, 1)
+        self.assertRaises(TypeError, range, 1e100, 0, 1e100)
+        self.assertRaises(TypeError, range, 1e100, 1e100, 1)
+        self.assertRaises(TypeError, range, 1e100, 1e100, 1e100)
+
     def test_input_and_raw_input(self):
         self.write_testfile()
         fp = open(TESTFN, 'r')