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
This commit is contained in:
Walter Dörwald 2002-11-19 20:49:15 +00:00
parent 7a3bae410d
commit f171540ab8
9 changed files with 82 additions and 49 deletions

View File

@ -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}

View File

@ -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}

View File

@ -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.

View File

@ -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():

View File

@ -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

View File

@ -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

View File

@ -641,6 +641,13 @@ float_coerce(PyObject **pv, PyObject **pw)
return 1; /* Can't do it */
}
static PyObject *
float_long(PyObject *v)
{
double x = PyFloat_AsDouble(v);
return PyLong_FromDouble(x);
}
static PyObject *
float_int(PyObject *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 *

View File

@ -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*/

View File

@ -2516,16 +2516,6 @@ long_coerce(PyObject **pv, PyObject **pw)
return 1; /* Can't do it */
}
static PyObject *
long_int(PyObject *v)
{
long x;
x = PyLong_AsLong(v);
if (PyErr_Occurred())
return NULL;
return PyInt_FromLong(x);
}
static PyObject *
long_long(PyObject *v)
{
@ -2533,6 +2523,27 @@ long_long(PyObject *v)
return v;
}
static PyObject *
long_int(PyObject *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 *
long_float(PyObject *v)
{