Index: Python/bltinmodule.c =================================================================== --- Python/bltinmodule.c (revision 50623) +++ Python/bltinmodule.c (working copy) @@ -2365,14 +2365,19 @@ { PyObject *result; Py_ssize_t i, j; - Py_ssize_t len = PyTuple_Size(tuple); + Py_ssize_t len; - if (len == 0) { - if (PyTuple_CheckExact(tuple)) - Py_INCREF(tuple); - else - tuple = PyTuple_New(0); - return tuple; + if (PyTuple_CheckExact(tuple)) { + len = PyTuple_Size(tuple); + if (len == 0) { + Py_INCREF(tuple); + return tuple; + } + } + else { + len = PyObject_Length(tuple); + if (len == 0) + return PyTuple_New(0); } if ((result = PyTuple_New(len)) == NULL) @@ -2435,20 +2440,23 @@ filterstring(PyObject *func, PyObject *strobj) { PyObject *result; - Py_ssize_t i, j; - Py_ssize_t len = PyString_Size(strobj); - Py_ssize_t outlen = len; - - if (func == Py_None) { - /* If it's a real string we can return the original, + Py_ssize_t i, j, len, outlen; + + if (PyString_CheckExact(strobj)) { + /* If it's a real string we can return the original, * as no character is ever false and __getitem__ * does return this character. If it's a subclass * we must go through the __getitem__ loop */ - if (PyString_CheckExact(strobj)) { - Py_INCREF(strobj); - return strobj; - } - } + if (func == Py_None) { + Py_INCREF(strobj); + return strobj; + } + len = PyString_Size(strobj); + } + else + len = PyObject_Length(strobj); + outlen = len; + if ((result = PyString_FromStringAndSize(NULL, len)) == NULL) return NULL; @@ -2531,19 +2539,23 @@ { PyObject *result; register Py_ssize_t i, j; - Py_ssize_t len = PyUnicode_GetSize(strobj); - Py_ssize_t outlen = len; + Py_ssize_t len, outlen; - if (func == Py_None) { - /* If it's a real string we can return the original, + if (PyUnicode_CheckExact(strobj)) { + /* If it's a real string we can return the original, * as no character is ever false and __getitem__ * does return this character. If it's a subclass * we must go through the __getitem__ loop */ - if (PyUnicode_CheckExact(strobj)) { - Py_INCREF(strobj); - return strobj; - } - } + if (func == Py_None) { + Py_INCREF(strobj); + return strobj; + } + len = PyUnicode_GetSize(strobj); + } + else + len = PyObject_Length(strobj); + outlen = len; + if ((result = PyUnicode_FromUnicode(NULL, len)) == NULL) return NULL; Index: Lib/test/test_builtin.py =================================================================== --- Lib/test/test_builtin.py (revision 50623) +++ Lib/test/test_builtin.py (working copy) @@ -508,25 +508,24 @@ def test_filter_subclasses(self): # test that filter() never returns tuple, str or unicode subclasses - # and that the result always goes through __getitem__ + # and that the result always goes through __getitem__ and __len__ funcs = (None, bool, lambda x: True) - class tuple2(tuple): - def __getitem__(self, index): - return 2*tuple.__getitem__(self, index) - class str2(str): - def __getitem__(self, index): - return 2*str.__getitem__(self, index) + + def lying(superclass, item): + class lyingsubclass(superclass): + def __len__(self): + return 5 + def __getitem__(self, index): + return item + return lyingsubclass + inputs = { - tuple2: {(): (), (1, 2, 3): (2, 4, 6)}, - str2: {"": "", "123": "112233"} + lying(tuple, "a"): {(1, 2, 3): ("a", "a", "a", "a", "a")}, + lying(str, "a"): {"123": "aaaaa"} } if have_unicode: - class unicode2(unicode): - def __getitem__(self, index): - return 2*unicode.__getitem__(self, index) - inputs[unicode2] = { - unicode(): unicode(), - unicode("123"): unicode("112233") + inputs[lying(unicode, u"a")] = { + unicode("123"): unicode("aaaaa") } for (cls, inps) in inputs.iteritems(): @@ -534,8 +533,8 @@ # make sure the output goes through __getitem__ # even if func is None self.assertEqual( - filter(funcs[0], cls(inp)), - filter(funcs[1], cls(inp)) + filter(None, cls(inp)), + filter(bool, cls(inp)) ) for func in funcs: outp = filter(func, cls(inp))