From 74b38b190faae988b4951cf46d83f853589aa530 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 7 Oct 2012 10:29:32 +0200 Subject: Issue #16148: Small improvements and cleanup. Added version information to docs. --- Doc/c-api/object.rst | 2 ++ Doc/library/operator.rst | 2 ++ Doc/reference/datamodel.rst | 9 +++++++++ Include/abstract.h | 4 +++- Lib/test/test_enumerate.py | 1 - Objects/abstract.c | 15 ++++++++------- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 8458fe8..e4769b3 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -349,6 +349,8 @@ is considered sufficient for this determination. returning the default value. On error ``-1`` is returned. This is the equivalent to the Python expression ``operator.length_hint(o, default)``. + .. versionadded:: 3.4 + .. c:function:: PyObject* PyObject_GetItem(PyObject *o, PyObject *key) Return element of *o* corresponding to the object *key* or *NULL* on failure. diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst index 93f33ff..1cd87fc 100644 --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -241,6 +241,8 @@ their character equivalents. actual length, then an estimate using ``__length_hint__``, and finally returning the default value. + .. versionadded:: 3.4 + The :mod:`operator` module also defines tools for generalized attribute and item lookups. These are useful for making fast field extractors as arguments for :func:`map`, :func:`sorted`, :meth:`itertools.groupby`, or other functions that diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 6b23d3f..111ad8b 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1805,6 +1805,15 @@ through the container; for mappings, :meth:`__iter__` should be the same as considered to be false in a Boolean context. +.. method:: object.__length_hint__(self) + + Called to implement ``operator.length_hint``. Should return an estimated + length for the object (which may be greater or less than the actual length). + The length must be an integer ``>=`` 0. This method is purely an + optimization and is never required for correctness. + + .. versionadded:: 3.4 + .. note:: Slicing is done exclusively with the following three methods. A call like :: diff --git a/Include/abstract.h b/Include/abstract.h index 8148675..e2b0750 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -403,7 +403,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ PyAPI_FUNC(Py_ssize_t) PyObject_Length(PyObject *o); #define PyObject_Length PyObject_Size -PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); +#ifndef Py_LIMITED_API + PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); +#endif PyAPI_FUNC(Py_ssize_t) PyObject_LengthHint(PyObject *o, Py_ssize_t); /* diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py index c0560fe..a2d18d0 100644 --- a/Lib/test/test_enumerate.py +++ b/Lib/test/test_enumerate.py @@ -170,7 +170,6 @@ class TestReversed(unittest.TestCase, PickleTest): self.assertEqual(type(reversed(x)), type(iter(x))) def test_len(self): - # This is an implementation detail, not an interface requirement for s in ('hello', tuple('hello'), list('hello'), range(5)): self.assertEqual(operator.length_hint(reversed(s)), len(s)) r = reversed(s) diff --git a/Objects/abstract.c b/Objects/abstract.c index 84e827a..4326cfa 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -71,8 +71,9 @@ _PyObject_HasLen(PyObject *o) { } /* The length hint function returns a non-negative value from o.__len__() - or o.__length_hint__(). If those methods aren't found. If one of the calls - fails this function returns -1. + or o.__length_hint__(). If those methods aren't found the defaultvalue is + returned. If one of the calls fails with an exception other than TypeError + this function returns -1. */ Py_ssize_t @@ -112,21 +113,21 @@ PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue) return defaultvalue; } if (!PyLong_Check(result)) { - PyErr_Format(PyExc_TypeError, "Length hint must be an integer, not %s", + PyErr_Format(PyExc_TypeError, "__length_hint__ must be an integer, not %.100s", Py_TYPE(result)->tp_name); Py_DECREF(result); return -1; } - defaultvalue = PyLong_AsSsize_t(result); + res = PyLong_AsSsize_t(result); Py_DECREF(result); - if (defaultvalue < 0 && PyErr_Occurred()) { + if (res < 0 && PyErr_Occurred()) { return -1; } - if (defaultvalue < 0) { + if (res < 0) { PyErr_Format(PyExc_ValueError, "__length_hint__() should return >= 0"); return -1; } - return defaultvalue; + return res; } PyObject * -- cgit v0.12