You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SystemError on calling len() if __len__() doesn't return an int #47979
len_check3.diff: patch fixing the SystemError and clipping to sys.maxsize, adds tests
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2009-02-10.12:52:53.722>created_at=<Date2008-08-29.14:59:07.938>labels= ['type-bug']
title="SystemError on calling len() if __len__() doesn't return an int"updated_at=<Date2009-02-10.12:52:53.716>user='https://bugs.python.org/hagen'
>>> classC:
... def__len__(self): return"foo"
...
>>> len(C())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: Objects/longobject.c:433: bad argument to internal function
On Python 2.6 the behaviour is different for old and new-style classes,
with old-style classes giving the more informative error message and
both accepting (and truncating) floats.
I attached a patch for Python 3.0, which refuses everything but ints and
gives an informative error message. Or does the float-truncating
behaviour of Python 2.x need to be preserved?
What about using PyNumber_AsSsize_t? it uses PyNumber_Index to accept
integral-like types, and refuses floats.
hagen commented on Aug 29, 2008
hagenmannequin
MannequinAuthor
More actions
Sounds ok, but then you get a more generic "object cannot be interpreted
as an integer" at the point where len() is called, instead of the
clearer "__len__() should return an int". I'm not sure if this could be
confusing.
hagen commented on Aug 29, 2008
hagenmannequin
MannequinAuthor
More actions
Of course we can do both: Accept integral-like types and reset the
exception text. The new patch does this and adds a test for the new
behaviour.
It's better to avoid the "expensive" call to PyErr_Occurred() when
possible. Here, an exception is set if (and only if) len==-1.
For example, it is enough to add these lines after the "__len__() should
return >= 0" message:
+ else if (PyErr_ExceptionMatches(PyExc_TypeError))
+ PyErr_SetString(PyExc_TypeError,
+ "__len__() should return an int");
Please clarify (that is: add tests for) the case where __len__ returns
1<<50 or -1<<50. If I remember correctly, PyNumber_AsSsize_t(res, NULL)
clips the values to MAXINT. Is this wanted?
That is *not* wanted. We had a discussion on the list about changing the
return value of the sq_length slot to allow larger lengths to be
reported, and while I don't recall why this wasn't done, I do recall
that the consensus was that if Py_ssize_t remains, len() should raise
rather than lie for larger values-
hagen commented on Aug 30, 2008
hagenmannequin
MannequinAuthor
More actions
In the latest list message I could find Guido wanted len() to lie:
Activity
hagen commentedon Aug 29, 2008
On Python 3.0:
On Python 2.6 the behaviour is different for old and new-style classes,
with old-style classes giving the more informative error message and
both accepting (and truncating) floats.
I attached a patch for Python 3.0, which refuses everything but ints and
gives an informative error message. Or does the float-truncating
behaviour of Python 2.x need to be preserved?
amauryfa commentedon Aug 29, 2008
What about using PyNumber_AsSsize_t? it uses PyNumber_Index to accept
integral-like types, and refuses floats.
hagen commentedon Aug 29, 2008
Sounds ok, but then you get a more generic "object cannot be interpreted
as an integer" at the point where len() is called, instead of the
clearer "__len__() should return an int". I'm not sure if this could be
confusing.
hagen commentedon Aug 29, 2008
Of course we can do both: Accept integral-like types and reset the
exception text. The new patch does this and adds a test for the new
behaviour.
Review carefully - I'm a newbie! ;-)
amauryfa commentedon Aug 29, 2008
Not bad! some remarks though:
possible. Here, an exception is set if (and only if) len==-1.
For example, it is enough to add these lines after the "__len__() should
return >= 0" message:
+ else if (PyErr_ExceptionMatches(PyExc_TypeError))
+ PyErr_SetString(PyExc_TypeError,
+ "__len__() should return an int");
1<<50 or -1<<50. If I remember correctly, PyNumber_AsSsize_t(res, NULL)
clips the values to MAXINT. Is this wanted?
birkenfeld commentedon Aug 29, 2008
That is *not* wanted. We had a discussion on the list about changing the
return value of the sq_length slot to allow larger lengths to be
reported, and while I don't recall why this wasn't done, I do recall
that the consensus was that if Py_ssize_t remains, len() should raise
rather than lie for larger values-
hagen commentedon Aug 30, 2008
In the latest list message I could find Guido wanted len() to lie:
http://mail.python.org/pipermail/python-3000/2008-May/013387.html
Has this been resolved in bpo-2723?
birkenfeld commentedon Aug 30, 2008
True. However, it's no pronouncement either. I suggest bringing it up on
the list again; probably other people would want to voice their opinions
too.
hagen commentedon Sep 2, 2008
There seems to be a pronouncement now
(http://mail.python.org/pipermail/python-3000/2008-September/014692.html),
so I'm attaching a patch which clips to sys.maxsize and includes
Amaury's suggestions.
benjaminp commentedon Feb 10, 2009
Fixed in bpo-5137.