mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Issue #16148: implemented PEP 424
This commit is contained in:
parent
ef08fb1f04
commit
aa9a79d279
14 changed files with 161 additions and 82 deletions
|
@ -64,49 +64,67 @@ PyObject_Length(PyObject *o)
|
|||
}
|
||||
#define PyObject_Length PyObject_Size
|
||||
|
||||
int
|
||||
_PyObject_HasLen(PyObject *o) {
|
||||
return (Py_TYPE(o)->tp_as_sequence && Py_TYPE(o)->tp_as_sequence->sq_length) ||
|
||||
(Py_TYPE(o)->tp_as_mapping && Py_TYPE(o)->tp_as_mapping->mp_length);
|
||||
}
|
||||
|
||||
/* The length hint function returns a non-negative value from o.__len__()
|
||||
or o.__length_hint__(). If those methods aren't found or return a negative
|
||||
value, then the defaultvalue is returned. If one of the calls fails,
|
||||
this function returns -1.
|
||||
or o.__length_hint__(). If those methods aren't found. If one of the calls
|
||||
fails this function returns -1.
|
||||
*/
|
||||
|
||||
Py_ssize_t
|
||||
_PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
|
||||
PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
|
||||
{
|
||||
_Py_IDENTIFIER(__length_hint__);
|
||||
PyObject *ro, *hintmeth;
|
||||
Py_ssize_t rv;
|
||||
|
||||
/* try o.__len__() */
|
||||
rv = PyObject_Size(o);
|
||||
if (rv >= 0)
|
||||
return rv;
|
||||
if (PyErr_Occurred()) {
|
||||
if (!PyErr_ExceptionMatches(PyExc_TypeError))
|
||||
Py_ssize_t res = PyObject_Length(o);
|
||||
if (res < 0 && PyErr_Occurred()) {
|
||||
if (!PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||
return -1;
|
||||
}
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
/* try o.__length_hint__() */
|
||||
hintmeth = _PyObject_LookupSpecial(o, &PyId___length_hint__);
|
||||
if (hintmeth == NULL) {
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
else
|
||||
return defaultvalue;
|
||||
else {
|
||||
return res;
|
||||
}
|
||||
ro = PyObject_CallFunctionObjArgs(hintmeth, NULL);
|
||||
Py_DECREF(hintmeth);
|
||||
if (ro == NULL) {
|
||||
if (!PyErr_ExceptionMatches(PyExc_TypeError))
|
||||
PyObject *hint = _PyObject_LookupSpecial(o, &PyId___length_hint__);
|
||||
if (hint == NULL) {
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
PyErr_Clear();
|
||||
}
|
||||
return defaultvalue;
|
||||
}
|
||||
rv = PyLong_Check(ro) ? PyLong_AsSsize_t(ro) : defaultvalue;
|
||||
Py_DECREF(ro);
|
||||
return rv;
|
||||
PyObject *result = PyObject_CallFunctionObjArgs(hint, NULL);
|
||||
Py_DECREF(hint);
|
||||
if (result == NULL) {
|
||||
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||
PyErr_Clear();
|
||||
return defaultvalue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else if (result == Py_NotImplemented) {
|
||||
Py_DECREF(result);
|
||||
return defaultvalue;
|
||||
}
|
||||
if (!PyLong_Check(result)) {
|
||||
PyErr_Format(PyExc_TypeError, "Length hint must be an integer, not %s",
|
||||
Py_TYPE(result)->tp_name);
|
||||
Py_DECREF(result);
|
||||
return -1;
|
||||
}
|
||||
defaultvalue = PyLong_AsSsize_t(result);
|
||||
Py_DECREF(result);
|
||||
if (defaultvalue < 0 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
if (defaultvalue < 0) {
|
||||
PyErr_Format(PyExc_ValueError, "__length_hint__() should return >= 0");
|
||||
return -1;
|
||||
}
|
||||
return defaultvalue;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
@ -1687,7 +1705,7 @@ PySequence_Tuple(PyObject *v)
|
|||
return NULL;
|
||||
|
||||
/* Guess result size and allocate space. */
|
||||
n = _PyObject_LengthHint(v, 10);
|
||||
n = PyObject_LengthHint(v, 10);
|
||||
if (n == -1)
|
||||
goto Fail;
|
||||
result = PyTuple_New(n);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue