mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
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:
parent
7a3bae410d
commit
f171540ab8
9 changed files with 82 additions and 49 deletions
|
@ -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):
|
||||||
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:
|
||||||
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):
|
||||||
# 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'
|
||||||
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?
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
#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)
|
||||||
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)
|
||||||
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\
|
||||||
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*/
|
||||||
|
|
|
@ -2516,16 +2516,6 @@ long_coerce(PyObject **pv, PyObject **pw)
|
||||||
return 1; /* Can't do it */
|
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 *
|
static PyObject *
|
||||||
long_long(PyObject *v)
|
long_long(PyObject *v)
|
||||||
{
|
{
|
||||||
|
@ -2533,6 +2523,27 @@ long_long(PyObject *v)
|
||||||
return 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 *
|
static PyObject *
|
||||||
long_float(PyObject *v)
|
long_float(PyObject *v)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue