Commit f171540a authored by Walter Dörwald's avatar Walter Dörwald

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
parent 7a3bae41
...@@ -650,8 +650,9 @@ determination. ...@@ -650,8 +650,9 @@ determination.
\begin{cfuncdesc}{PyObject*}{PyNumber_Int}{PyObject *o} \begin{cfuncdesc}{PyObject*}{PyNumber_Int}{PyObject *o}
Returns the \var{o} converted to an integer object on success, or Returns the \var{o} converted to an integer object on success, or
\NULL{} on failure. This is the equivalent of the Python expression \NULL{} on failure. If the argument is outside the integer range
\samp{int(\var{o})}.\bifuncindex{int} a long object will be returned instead. This is the equivalent
of the Python expression \samp{int(\var{o})}.\bifuncindex{int}
\end{cfuncdesc} \end{cfuncdesc}
\begin{cfuncdesc}{PyObject*}{PyNumber_Long}{PyObject *o} \begin{cfuncdesc}{PyObject*}{PyNumber_Long}{PyObject *o}
......
...@@ -507,6 +507,8 @@ def my_import(name): ...@@ -507,6 +507,8 @@ def my_import(name):
Otherwise, the argument may be a plain or Otherwise, the argument may be a plain or
long integer or a floating point number. Conversion of floating long integer or a floating point number. Conversion of floating
point numbers to integers truncates (towards zero). point numbers to integers truncates (towards zero).
If the argument is outside the integer range a long object will
be returned instead.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{intern}{string} \begin{funcdesc}{intern}{string}
......
...@@ -438,17 +438,19 @@ try: ...@@ -438,17 +438,19 @@ try:
except: except:
raise TestFailed, "int(%s)" % `s[1:]` + " should return long" raise TestFailed, "int(%s)" % `s[1:]` + " should return long"
try: try:
int(1e100) x = int(1e100)
except OverflowError: except OverflowError:
pass raise TestFailed("int(1e100) mustn't raise OverflowError")
else: else:
raise TestFailed("int(1e100) expected OverflowError") if not isinstance(x, long):
raise TestFailed("int(1e100) should have returned long")
try: try:
int(-1e100) x = int(-1e100)
except OverflowError: except OverflowError:
pass raise TestFailed("int(-1e100) mustn't raise OverflowError")
else: 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. # SF bug 434186: 0x80000000/2 != 0x80000000>>1.
......
...@@ -267,22 +267,26 @@ def test_misc(maxdigits=MAXDIGITS): ...@@ -267,22 +267,26 @@ def test_misc(maxdigits=MAXDIGITS):
# but long -> int should overflow for hugepos+1 and hugeneg-1 # but long -> int should overflow for hugepos+1 and hugeneg-1
x = hugepos_aslong + 1 x = hugepos_aslong + 1
try: try:
int(x) y = int(x)
raise ValueError
except OverflowError: except OverflowError:
pass raise TestFailed, "int(long(sys.maxint) + 1) mustn't overflow"
except: if not isinstance(y, long):
raise TestFailed, "int(long(sys.maxint) + 1) didn't overflow" raise TestFailed("int(long(sys.maxint) + 1) should have returned long")
x = hugeneg_aslong - 1 x = hugeneg_aslong - 1
try: try:
int(x) y = int(x)
raise ValueError
except OverflowError: except OverflowError:
pass raise TestFailed, "int(long(-sys.maxint-1) - 1) mustn't overflow"
except: if not isinstance(y, long):
raise TestFailed, "int(long(-sys.maxint-1) - 1) didn't overflow" 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 # ----------------------------------- tests of auto int->long conversion
def test_auto_overflow(): def test_auto_overflow():
......
...@@ -138,16 +138,16 @@ if not 12L < 24L: raise TestFailed, 'long op' ...@@ -138,16 +138,16 @@ if not 12L < 24L: raise TestFailed, 'long op'
if not -24L < -12L: raise TestFailed, 'long op' if not -24L < -12L: raise TestFailed, 'long op'
x = sys.maxint x = sys.maxint
if int(long(x)) != x: raise TestFailed, 'long op' if int(long(x)) != x: raise TestFailed, 'long op'
try: int(long(x)+1L) try: y = int(long(x)+1L)
except OverflowError: pass except OverflowError: raise TestFailed, 'long op'
else:raise TestFailed, 'long op' if not isinstance(y, long): raise TestFailed, 'long op'
x = -x x = -x
if int(long(x)) != x: raise TestFailed, 'long op' if int(long(x)) != x: raise TestFailed, 'long op'
x = x-1 x = x-1
if int(long(x)) != x: raise TestFailed, 'long op' if int(long(x)) != x: raise TestFailed, 'long op'
try: int(long(x)-1L) try: y = int(long(x)-1L)
except OverflowError: pass except OverflowError: raise TestFailed, 'long op'
else:raise TestFailed, 'long op' if not isinstance(y, long): raise TestFailed, 'long op'
try: 5 << -5 try: 5 << -5
except ValueError: pass except ValueError: pass
......
...@@ -11,6 +11,9 @@ What's New in Python 2.3 alpha 1? ...@@ -11,6 +11,9 @@ What's New in Python 2.3 alpha 1?
Type/class unification and new-style classes 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 - Assignment to __class__ is disallowed if either the old or the new
class is a statically allocated type object (such as defined by an class is a statically allocated type object (such as defined by an
......
...@@ -641,6 +641,13 @@ float_coerce(PyObject **pv, PyObject **pw) ...@@ -641,6 +641,13 @@ float_coerce(PyObject **pv, PyObject **pw)
return 1; /* Can't do it */ return 1; /* Can't do it */
} }
static PyObject *
float_long(PyObject *v)
{
double x = PyFloat_AsDouble(v);
return PyLong_FromDouble(x);
}
static PyObject * static PyObject *
float_int(PyObject *v) float_int(PyObject *v)
{ {
...@@ -652,8 +659,7 @@ float_int(PyObject *v) ...@@ -652,8 +659,7 @@ float_int(PyObject *v)
#ifdef RISCOS #ifdef RISCOS
/* conversion from floating to integral type would raise exception */ /* conversion from floating to integral type would raise exception */
if (wholepart>LONG_MAX || wholepart<LONG_MIN) { if (wholepart>LONG_MAX || wholepart<LONG_MIN) {
PyErr_SetString(PyExc_OverflowError, "float too large to convert"); return float_long(v);
return NULL;
} }
#endif #endif
/* doubles may have more bits than longs, or vice versa; and casting /* doubles may have more bits than longs, or vice versa; and casting
...@@ -663,15 +669,7 @@ float_int(PyObject *v) ...@@ -663,15 +669,7 @@ float_int(PyObject *v)
aslong = (long)wholepart; aslong = (long)wholepart;
if ((double)aslong == wholepart) if ((double)aslong == wholepart)
return PyInt_FromLong(aslong); return PyInt_FromLong(aslong);
PyErr_SetString(PyExc_OverflowError, "float too large to convert"); return float_long(v);
return NULL;
}
static PyObject *
float_long(PyObject *v)
{
double x = PyFloat_AsDouble(v);
return PyLong_FromDouble(x);
} }
static PyObject * static PyObject *
......
...@@ -166,9 +166,20 @@ PyInt_AsLong(register PyObject *op) ...@@ -166,9 +166,20 @@ PyInt_AsLong(register PyObject *op)
if (io == NULL) if (io == NULL)
return -1; return -1;
if (!PyInt_Check(io)) { if (!PyInt_Check(io)) {
PyErr_SetString(PyExc_TypeError, if (PyLong_Check(io)) {
"nb_int should return int object"); /* got a long? => retry int conversion */
return -1; 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); val = PyInt_AS_LONG(io);
...@@ -892,7 +903,8 @@ Convert a string or number to an integer, if possible. A floating point\n\ ...@@ -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\ 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\ 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\ 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 = { static PyNumberMethods int_as_number = {
(binaryfunc)int_add, /*nb_add*/ (binaryfunc)int_add, /*nb_add*/
......
...@@ -2517,20 +2517,31 @@ long_coerce(PyObject **pv, PyObject **pw) ...@@ -2517,20 +2517,31 @@ long_coerce(PyObject **pv, PyObject **pw)
} }
static PyObject * static PyObject *
long_int(PyObject *v) long_long(PyObject *v)
{ {
long x; Py_INCREF(v);
x = PyLong_AsLong(v); return v;
if (PyErr_Occurred())
return NULL;
return PyInt_FromLong(x);
} }
static PyObject * static PyObject *
long_long(PyObject *v) long_int(PyObject *v)
{ {
Py_INCREF(v); long x;
return v; 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 * static PyObject *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment