The __index__() special method was introduced to make other integer-like types which are not int subclasses to be accepted as integer arguments.
It is supported by all PyArg_Parse format units for integers, except k (long sized bitfield) and K (long long sized bitfield). Argument Clinic has the same behavior for unsigned_long(bitwise=True) and unsigned_long_long(bitwise=True). It supports also non-bitwise unsigned integer converters, all of them do not support __index__().
Note that making PyLong_AsUnsignedLong() and PyLong_AsUnsignedLongLong() to support __index__() is potentially unsafe. But the higher level code that uses them, can be changed.
The following PRs change the code which do not use PyArg_Parse or Argument Clinic, but directly call PyLong_AsUnsignedLong(), PyLong_AsUnsignedLongLong() or PyLong_AsSize_t(). In many case, the simplest way is to use PyLong_AsNativeBytes() or converters like _PyLong_UnsignedLongLong_Converter(), but the side effect is that ValueError is now raised instead of OverflowError for negative values. See also #74020.
Some code left in the ctypes module, but I left it for later. This is a large issue, and not in all cases we may automatically use __index__. For example, int.__add__ does not use __index__, they look similar.
Activity
pythongh-132987: Support __index__() for "k" and "K" formats in PyArg…
pythongh-132987: Support __index__() for "k" and "K" formats in PyArg…
pythongh-132987: Support __index__() for "k" and "K" formats in PyArg…
gh-132987: Support __index__() for "k" and "K" formats in PyArg_Parse (…
pythongh-132987: Support __index__() for unsigned integers in Argumen…
pythongh-132987: Support __index__() for unsigned integers in Argumen…
gh-132987: Support __index__() for unsigned integers in Argument Clin…
pythongh-132987: Support __index__() in the socket module
pythongh-132987: Support __index__() in the select.kqueue_event const…
pythongh-132987: Support __index__() in the posix module
pythongh-132987: Support __index__() in the stat module
pythongh-132987: Support __index__() in the ssl.SSLContext.options se…
pythongh-132987: Support __index__() in the lzma module
pythongh-132987: Support __index__() in hashlibi.scrypt()
serhiy-storchaka commented on Apr 28, 2025
The following PRs change the code which do not use PyArg_Parse or Argument Clinic, but directly call PyLong_AsUnsignedLong(), PyLong_AsUnsignedLongLong() or PyLong_AsSize_t(). In many case, the simplest way is to use PyLong_AsNativeBytes() or converters like _PyLong_UnsignedLongLong_Converter(), but the side effect is that ValueError is now raised instead of OverflowError for negative values. See also #74020.
gh-132987: Support __index__() in the posix module (GH-133096)
gh-132987: Support __index__() in hashlib.scrypt() (GH-133100)
gh-132987: Support __index__() in the ssl.SSLContext.options setter (G…
gh-132987: Support __index__() in the select.kqueue_event constructor (…
gh-132987: Support __index__() in the lzma module (GH-133099)
gh-132987: Support __index__() in the stat module (GH-133097)
gh-132987: Support __index__() in the socket module (GH-133093)
serhiy-storchaka commented on May 13, 2025
Some code left in the ctypes module, but I left it for later. This is a large issue, and not in all cases we may automatically use __index__. For example, int.__add__ does not use __index__, they look similar.