New submission from Josh Rosenberg <shadowranger+pyt...@gmail.com>:

In Python 2, making a user-defined class support formatting using the 
integer-specific type codes required that __int__ be defined and nothing else 
(that is, '%x' % Foo() only required Foo to provide a __int__ method). In 
Python 3, this was changed to perform the conversion via __index__ for the %o, 
%x and %X format types (to match how oct and hex behave), not __int__, but the 
pre-check for validity in unicodeobject.c's mainformatlong function is still 
based on PyNumber_Check, not PyIndex_Check, and PyNumber_Check is concerned 
solely with __int__ and __float__, not __index__.

This means that a class with __index__ but not __int__ can't be used with the 
%o/%x/%X format codes (even though hex(mytype) and oct(mytype) work just fine).

It seems to me that either:

1. PyNumber_Check should be a superset of PyIndex_Check (broader change, 
probably out of scope)

or

2. mainformatlong should restrict the scope of the PyNumber_Check test to only 
being used for the non-'o'/'x'/'X' tests (where it's needed to avoid coercing 
strings and the like to integer).

Change #2 should be safe, with no major side-effects; since PyLong and 
subclasses always passed the existing PyNumber_Check test anyway, and 
PyNumber_Index already performs PyIndex_Check, the only path that needs 
PyNumber_Check is the one that ends in calling PyNumber_Long.

----------
components: Interpreter Core
messages: 313285
nosy: josh.r
priority: normal
severity: normal
status: open
title: Making a class formattable as hex/oct integer requires both __int__ and 
__index__ for no good reason
versions: Python 3.7, Python 3.8

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue33002>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to