diff --git a/Lib/test/test_bool.py b/Lib/test/test_bool.py index c5a1f1f..ed47037 100644 --- a/Lib/test/test_bool.py +++ b/Lib/test/test_bool.py @@ -344,6 +344,16 @@ class BoolTest(unittest.TestCase): except (Exception) as e_len: self.assertEqual(str(e_bool), str(e_len)) + def test_len_overflow(self): + self.assertIs(bool(range(1 << 1000)), True) + class A: + def __len__(self): + return length + length = 1 << 1000 + self.assertIs(bool(A()), True) + length = -1 << 1000 + self.assertRaises(ValueError, bool, A()) + def test_blocked(self): class A: __bool__ = None diff --git a/Misc/NEWS b/Misc/NEWS index 651d175..7d85dd1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,10 @@ What's New in Python 3.7.0 alpha 1? Core and Builtins ----------------- -- bpo-12414: sys.getsizeof() on a code object now returns the sizes +- bpo-29840: bool() no longer raises OverflowError for objects without defined + __bool__ when __len__() returned a large integer or raised OverflowError. + +- bpo-12414: sys.getsizeof() on a code object now returns the sizes which includes the code struct and sizes of objects which it references. Patch by Dong-hee Na. diff --git a/Objects/object.c b/Objects/object.c index 2d79e2f..1084911 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1313,26 +1313,35 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context) int PyObject_IsTrue(PyObject *v) { - Py_ssize_t res; + Py_ssize_t len; if (v == Py_True) return 1; if (v == Py_False) return 0; if (v == Py_None) return 0; - else if (v->ob_type->tp_as_number != NULL && - v->ob_type->tp_as_number->nb_bool != NULL) - res = (*v->ob_type->tp_as_number->nb_bool)(v); - else if (v->ob_type->tp_as_mapping != NULL && - v->ob_type->tp_as_mapping->mp_length != NULL) - res = (*v->ob_type->tp_as_mapping->mp_length)(v); + if (v->ob_type->tp_as_number != NULL && + v->ob_type->tp_as_number->nb_bool != NULL) + return (*v->ob_type->tp_as_number->nb_bool)(v); + + if (v->ob_type->tp_as_mapping != NULL && + v->ob_type->tp_as_mapping->mp_length != NULL) + len = (*v->ob_type->tp_as_mapping->mp_length)(v); else if (v->ob_type->tp_as_sequence != NULL && v->ob_type->tp_as_sequence->sq_length != NULL) - res = (*v->ob_type->tp_as_sequence->sq_length)(v); + len = (*v->ob_type->tp_as_sequence->sq_length)(v); else return 1; - /* if it is negative, it should be either -1 or -2 */ - return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int); + if (len > 0) + return 1; + if (len == 0) + return 0; + assert(PyErr_Occurred()); + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_Clear(); + return 1; + } + return -1; } /* equivalent of 'not v'