diff -r f2d955afad8a Lib/operator.py --- a/Lib/operator.py Sat Aug 17 21:43:47 2013 +0200 +++ b/Lib/operator.py Sun Aug 18 10:30:33 2013 +0300 @@ -87,7 +87,20 @@ def index(a): "Same as a.__index__()." - return a.__index__() + if isinstance(a, int): + return a + from inspect import getattr_static + try: + descr = getattr_static(a.__class__, '__index__') + except AttributeError: + msg = ("'%s' object cannot be interpreted as an integer" % + type(a).__name__) + raise TypeError(msg) + n = descr.__get__(a)() + if not isinstance(n, int): + msg = ('__index__ returned non-int (type %s)' % type(n).__name__) + raise TypeError(msg) + return n def inv(a): "Same as ~a." @@ -142,7 +155,10 @@ def concat(a, b): "Same as a + b, for a and b sequences." - if not hasattr(a, '__getitem__'): + from inspect import getattr_static + try: + getattr_static(a.__class__, '__getitem__') + except AttributeError: msg = "'%s' object can't be concatenated" % type(a).__name__ raise TypeError(msg) return a + b @@ -198,13 +214,15 @@ except TypeError: pass + from inspect import getattr_static try: - hint = type(obj).__length_hint__ + descr = getattr_static(obj.__class__, '__length_hint__') except AttributeError: return default + hint = descr.__get__(obj) try: - val = hint(obj) + val = hint() except TypeError: return default if val is NotImplemented: @@ -301,7 +319,10 @@ def iconcat(a, b): "Same as a += b, for a and b sequences." - if not hasattr(a, '__getitem__'): + from inspect import getattr_static + try: + getattr_static(a.__class__, '__getitem__') + except AttributeError: msg = "'%s' object can't be concatenated" % type(a).__name__ raise TypeError(msg) a += b diff -r f2d955afad8a Lib/test/test_operator.py --- a/Lib/test/test_operator.py Sat Aug 17 21:43:47 2013 +0200 +++ b/Lib/test/test_operator.py Sun Aug 18 10:30:33 2013 +0300 @@ -170,6 +170,35 @@ self.assertRaises(TypeError, operator.getitem, a, None) self.assertTrue(operator.getitem(a, 2) == 2) + def test_index(self): + operator = self.module + self.assertRaises(TypeError, operator.index) + self.assertRaises(TypeError, operator.index, 1, 1) + self.assertEqual(operator.index(42), 42) + self.assertEqual(operator.index(True), 1) + self.assertRaises(TypeError, operator.index, '42') + self.assertRaises(TypeError, operator.index, 42.0) + class A: + def __index__(self): + return 42 + a = A() + a.__index__ = lambda: 1729 + self.assertEqual(operator.index(a), 42) + class F: + def __index__(self): + return 42.0 + self.assertRaises(TypeError, operator.index, F()) + class I(int): + def __index__(): + return 42 + i = I() + self.assertIs(operator.index(i), i) + class S: + @staticmethod + def __index__(): + return 42 + self.assertEqual(operator.index(S()), 42) + def test_indexOf(self): operator = self.module self.assertRaises(TypeError, operator.indexOf)