Skip to content

Commit 6fcec45

Browse files
gh-62912: fix pure-Python operator.index()
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 74a82a2 commit 6fcec45

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

Doc/library/operator.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ The mathematical and bitwise operations are the most numerous:
122122
.. function:: index(a)
123123
__index__(a)
124124

125-
Return *a* converted to an integer. Equivalent to ``a.__index__()``.
125+
Return *a* converted to an integer. Equivalent to ``int(type(a).__index__(a))``.
126126

127127
.. versionchanged:: 3.10
128128
The result always has exact type :class:`int`. Previously, the result

Lib/operator.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,11 @@ def floordiv(a, b):
9393
return a // b
9494

9595
def index(a):
96-
"Same as a.__index__()."
97-
return a.__index__()
96+
"Same as int(type(a).__index__(a))."
97+
if hasattr(type(a), '__index__'):
98+
return int(a)
99+
raise TypeError(f"'{type(a).__name__}' object cannot be "
100+
"interpreted as an integer")
98101

99102
def inv(a):
100103
"Same as ~a."

Lib/test/test_operator.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,34 @@ def __index__(self):
570570
with self.assertRaises((AttributeError, TypeError)):
571571
operator.index(None)
572572

573+
self.assertRaises(TypeError, operator.index)
574+
self.assertRaises(TypeError, operator.index, 1, 1)
575+
self.assertEqual(operator.index(True), 1)
576+
self.assertRaises(TypeError, operator.index, '42')
577+
self.assertRaises(TypeError, operator.index, 42.0)
578+
x = X()
579+
x.__index__ = lambda: 1729
580+
self.assertEqual(operator.index(x), 1)
581+
class F:
582+
def __index__(self):
583+
return 42.0
584+
self.assertRaises(TypeError, operator.index, F())
585+
class I(int):
586+
def __index__():
587+
return 42
588+
i = I()
589+
self.assertIs(operator.index(i), int(i))
590+
class D:
591+
def __index__(self):
592+
return I(42)
593+
with self.assertWarns(DeprecationWarning):
594+
self.assertEqual(operator.index(D()), 42)
595+
class S:
596+
@staticmethod
597+
def __index__():
598+
return 42
599+
self.assertEqual(operator.index(S()), 42)
600+
573601
def test_not_(self):
574602
operator = self.module
575603
class C:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Correct pure-Python version of the :func:`operator.index` to behave like the
2+
C version. Patch by Sergey B Kirpichev.

0 commit comments

Comments
 (0)