summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Dörwald <walter@livinglogic.de>2002-11-19 20:49:15 (GMT)
committerWalter Dörwald <walter@livinglogic.de>2002-11-19 20:49:15 (GMT)
commitf171540ab8d816a996c34db3f6aa4bf9cf147fba (patch)
tree001d1ff0bdea449058218d2debf6d6f8dbbcb220
parent7a3bae410df3dd0032509b97077d0c4d98276fdd (diff)
downloadcpython-f171540ab8d816a996c34db3f6aa4bf9cf147fba.zip
cpython-f171540ab8d816a996c34db3f6aa4bf9cf147fba.tar.gz
cpython-f171540ab8d816a996c34db3f6aa4bf9cf147fba.tar.bz2
Change int() so that passing a string, unicode, float or long argument
that is outside the integer range no longer raises OverflowError, but returns a long object instead. This fixes SF bug http://www.python.org/sf/635115
-rw-r--r--Doc/api/abstract.tex5
-rw-r--r--Doc/lib/libfuncs.tex2
-rw-r--r--Lib/test/test_b1.py14
-rw-r--r--Lib/test/test_long.py24
-rw-r--r--Lib/test/test_types.py12
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/floatobject.c20
-rw-r--r--Objects/intobject.c20
-rw-r--r--Objects/longobject.c29
9 files changed, 81 insertions, 48 deletions
diff --git a/Doc/api/abstract.tex b/Doc/api/abstract.tex
index 6bf96b2..c5939b2 100644
--- a/Doc/api/abstract.tex
+++ b/Doc/api/abstract.tex
@@ -650,8 +650,9 @@ determination.
\begin{cfuncdesc}{PyObject*}{PyNumber_Int}{PyObject *o}
Returns the \var{o} converted to an integer object on success, or
- \NULL{} on failure. This is the equivalent of the Python expression
- \samp{int(\var{o})}.\bifuncindex{int}
+ \NULL{} on failure. If the argument is outside the integer range
+ a long object will be returned instead. This is the equivalent
+ of the Python expression \samp{int(\var{o})}.\bifuncindex{int}
\end{cfuncdesc}
\begin{cfuncdesc}{PyObject*}{PyNumber_Long}{PyObject *o}
diff --git a/Doc/lib/libfuncs.tex b/Doc/lib/libfuncs.tex
index f6b01d1..9fab9ba 100644
--- a/Doc/lib/libfuncs.tex
+++ b/Doc/lib/libfuncs.tex
@@ -507,6 +507,8 @@ def my_import(name):
Otherwise, the argument may be a plain or
long integer or a floating point number. Conversion of floating
point numbers to integers truncates (towards zero).
+ If the argument is outside the integer range a long object will
+ be returned instead.
\end{funcdesc}
\begin{funcdesc}{intern}{string}
diff --git a/Lib/test/test_b1.py b/Lib/test/test_b1.py
index 249f1fa..3033667 100644
--- a/Lib/test/test_b1.py
+++ b/Lib/test/test_b1.py
@@ -438,17 +438,19 @@ try:
except:
raise TestFailed, "int(%s)" % `s[1:]` + " should return long"
try:
- int(1e100)
+ x = int(1e100)
except OverflowError:
- pass
+ raise TestFailed("int(1e100) mustn't raise OverflowError")
else:
- raise TestFailed("int(1e100) expected OverflowError")
+ if not isinstance(x, long):
+ raise TestFailed("int(1e100) should have returned long")
try:
- int(-1e100)
+ x = int(-1e100)
except OverflowError:
- pass
+ raise TestFailed("int(-1e100) mustn't raise OverflowError")
else:
- raise TestFailed("int(-1e100) expected OverflowError")
+ if not isinstance(x, long):
+ raise TestFailed("int(-1e100) should have returned long")
# SF bug 434186: 0x80000000/2 != 0x80000000>>1.
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index 9319734..9cab2de 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -267,22 +267,26 @@ def test_misc(maxdigits=MAXDIGITS):
# but long -> int should overflow for hugepos+1 and hugeneg-1
x = hugepos_aslong + 1
try:
- int(x)
- raise ValueError
+ y = int(x)
except OverflowError:
- pass
- except:
- raise TestFailed, "int(long(sys.maxint) + 1) didn't overflow"
+ raise TestFailed, "int(long(sys.maxint) + 1) mustn't overflow"
+ if not isinstance(y, long):
+ raise TestFailed("int(long(sys.maxint) + 1) should have returned long")
x = hugeneg_aslong - 1
try:
- int(x)
- raise ValueError
+ y = int(x)
except OverflowError:
- pass
- except:
- raise TestFailed, "int(long(-sys.maxint-1) - 1) didn't overflow"
+ raise TestFailed, "int(long(-sys.maxint-1) - 1) mustn't overflow"
+ if not isinstance(y, long):
+ raise TestFailed("int(long(-sys.maxint-1) - 1) should have returned long")
+ class long2(long):
+ pass
+ x = long2(1L<<100)
+ y = int(x)
+ if type(y) is not long:
+ raise TestFailed("overflowing int conversion must return long not long subtype")
# ----------------------------------- tests of auto int->long conversion
def test_auto_overflow():
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index d075d94..c20af2e 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -138,16 +138,16 @@ if not 12L < 24L: raise TestFailed, 'long op'
if not -24L < -12L: raise TestFailed, 'long op'
x = sys.maxint
if int(long(x)) != x: raise TestFailed, 'long op'
-try: int(long(x)+1L)
-except OverflowError: pass
-else:raise TestFailed, 'long op'
+try: y = int(long(x)+1L)
+except OverflowError: raise TestFailed, 'long op'
+if not isinstance(y, long): raise TestFailed, 'long op'
x = -x
if int(long(x)) != x: raise TestFailed, 'long op'
x = x-1
if int(long(x)) != x: raise TestFailed, 'long op'
-try: int(long(x)-1L)
-except OverflowError: pass
-else:raise TestFailed, 'long op'
+try: y = int(long(x)-1L)
+except OverflowError: raise TestFailed, 'long op'
+if not isinstance(y, long): raise TestFailed, 'long op'
try: 5 << -5
except ValueError: pass
diff --git a/Misc/NEWS b/Misc/NEWS
index 3129276..73ee64a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -11,6 +11,9 @@ What's New in Python 2.3 alpha 1?
Type/class unification and new-style classes
--------------------------------------------
+- int() now returns a long object if the argument is outside the
+ integer range, so int("4"*1000), int(1e200) and int(1L<<1000) will
+ all return long objects instead of raising an OverflowError.
- Assignment to __class__ is disallowed if either the old or the new
class is a statically allocated type object (such as defined by an
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 924b312..129f5bd 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -642,6 +642,13 @@ float_coerce(PyObject **pv, PyObject **pw)
}
static PyObject *
+float_long(PyObject *v)
+{
+ double x = PyFloat_AsDouble(v);
+ return PyLong_FromDouble(x);
+}
+
+static PyObject *
float_int(PyObject *v)
{
double x = PyFloat_AsDouble(v);
@@ -652,8 +659,7 @@ float_int(PyObject *v)
#ifdef RISCOS
/* conversion from floating to integral type would raise exception */
if (wholepart>LONG_MAX || wholepart<LONG_MIN) {
- PyErr_SetString(PyExc_OverflowError, "float too large to convert");
- return NULL;
+ return float_long(v);
}
#endif
/* doubles may have more bits than longs, or vice versa; and casting
@@ -663,15 +669,7 @@ float_int(PyObject *v)
aslong = (long)wholepart;
if ((double)aslong == wholepart)
return PyInt_FromLong(aslong);
- PyErr_SetString(PyExc_OverflowError, "float too large to convert");
- return NULL;
-}
-
-static PyObject *
-float_long(PyObject *v)
-{
- double x = PyFloat_AsDouble(v);
- return PyLong_FromDouble(x);
+ return float_long(v);
}
static PyObject *
diff --git a/Objects/intobject.c b/Objects/intobject.c
index e339085..7242dd0 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -166,9 +166,20 @@ PyInt_AsLong(register PyObject *op)
if (io == NULL)
return -1;
if (!PyInt_Check(io)) {
- PyErr_SetString(PyExc_TypeError,
- "nb_int should return int object");
- return -1;
+ if (PyLong_Check(io)) {
+ /* got a long? => retry int conversion */
+ val = PyLong_AsLong((PyObject *)io);
+ if (PyErr_Occurred()) {
+ Py_DECREF(io);
+ return -1;
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "nb_int should return int object");
+ return -1;
+ }
}
val = PyInt_AS_LONG(io);
@@ -892,7 +903,8 @@ Convert a string or number to an integer, if possible. A floating point\n\
argument will be truncated towards zero (this does not include a string\n\
representation of a floating point number!) When converting a string, use\n\
the optional base. It is an error to supply a base when converting a\n\
-non-string.");
+non-string. If the argument is outside the integer range a long object\n\
+will be returned instead.");
static PyNumberMethods int_as_number = {
(binaryfunc)int_add, /*nb_add*/
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 7374fce..5038823 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -2517,20 +2517,31 @@ long_coerce(PyObject **pv, PyObject **pw)
}
static PyObject *
-long_int(PyObject *v)
+long_long(PyObject *v)
{
- long x;
- x = PyLong_AsLong(v);
- if (PyErr_Occurred())
- return NULL;
- return PyInt_FromLong(x);
+ Py_INCREF(v);
+ return v;
}
static PyObject *
-long_long(PyObject *v)
+long_int(PyObject *v)
{
- Py_INCREF(v);
- return v;
+ long x;
+ x = PyLong_AsLong(v);
+ if (PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
+ PyErr_Clear();
+ if (PyLong_CheckExact(v)) {
+ Py_INCREF(v);
+ return v;
+ }
+ else
+ return _PyLong_Copy((PyLongObject *)v);
+ }
+ else
+ return NULL;
+ }
+ return PyInt_FromLong(x);
}
static PyObject *