From f171540ab8d816a996c34db3f6aa4bf9cf147fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Walter=20D=C3=B6rwald?= Date: Tue, 19 Nov 2002 20:49:15 +0000 Subject: 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 --- Doc/api/abstract.tex | 5 +++-- Doc/lib/libfuncs.tex | 2 ++ Lib/test/test_b1.py | 14 ++++++++------ Lib/test/test_long.py | 24 ++++++++++++++---------- Lib/test/test_types.py | 12 ++++++------ Misc/NEWS | 3 +++ Objects/floatobject.c | 20 +++++++++----------- Objects/intobject.c | 20 ++++++++++++++++---- Objects/longobject.c | 29 ++++++++++++++++++++--------- 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 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 * -- cgit v0.12