[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-23 Thread Ethan Furman

Ethan Furman added the comment:

Thank you everyone for increasing my understanding.  :)

Terry J Reedy wrote:

 [snip everything I now agree with, which is most of Terry's comment]

 3. Every core usage of __int__ looks for __index__ also. Int() does not
 do this now, but '%d' does [...]
 
 The exact details would depend on whether we want to allow (or at least
 bless) classes with __int__ and __index__ returning different ints.

I think we should state that __int__ and __index__ are expected to return the 
same value (if both are defined) otherwise one is on one's own (otherwise known 
as: if it breaks, you own all the pieces ;) .

 Given things as they are, I would simply expand the domain of %x, etc,
 to that of %d without bothering to go through a deprecation process.

This is not correct.  `hex(3.14)` raises a TypeError, and so should `'%x' % 
3.14`

While Terry's option 2 would have to wait for 3.5, is there any reason why 
fixing the %-formating characters to use __index__ instead of __int__ can't go 
into 3.4?  That portion seems to be clearly a bug and not an enhancement (the 
enhancement portions of this ticket can be separated out into another issue).

--
nosy: +larry

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-20 Thread Terry J. Reedy

Terry J. Reedy added the comment:

It seems to me that anything that is an 'integer' that can be turned into an 
int without loss of information (has .__index__) is logically a 'number' that 
can be turned into an int possibly with loss of information (has .__int__).  So 
perhaps one of the following should be true:

1. The doc for .__index__ specifies that def __index__ 'must' be followed by 
__int__ = __index__ to make a coherent class. (So Ethan's Grade as written 
above would not qualify.)

2. The type constructor does this for us by adding __int__ as an alias for 
__index__ when the latter is present.

3. Every core usage of __int__ looks for __index__ also. Int() does not do this 
now, but '%d' does, so int(Grade.F) fails but int('%d' % Grade.f) works.

The exact details would depend on whether we want to allow (or at least bless) 
classes with __int__ and __index__ returning different ints.

The docs for bin/oct/hex(x) are clear. Convert an integer number to a 
binary/octal/hexadecimal string. The result is a valid Python expression. If x 
is not a Python int object, it has to define an __index__() method that returns 
an integer. This should not change.

If the domain of %x is going to be a subset of of the domain of %d, it seems to 
me that the exclusion should be of non-integers (such as floats) rather than of 
non-int integers. Given things as they are, I would simply expand the domain of 
%x, etc, to that of %d without bothering to go through a deprecation process.

--
nosy: +terry.reedy
stage:  - test needed
type:  - enhancement

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-17 Thread Guido van Rossum

Guido van Rossum added the comment:

AFAIK %i and %d are the same.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-17 Thread Eric V. Smith

Eric V. Smith added the comment:

Yes, looking through Objects/unicodeobject.c, 'u', 'i', and 'd' are treated the 
same everywhere.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

New submission from Ethan Furman:

Using Enum to illustrate:

-- class Grade(enum.Enum):
...   A = 4
...   B = 3
...   C = 2
...   D = 1
...   F = 0
...   def __index__(self):
... return self._value_

-- ['miserable'][Grade.F]
'miserable'

-- '%x' % Grade.F
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: %x format: a number is required, not Grade

-- hex(Grade.F)
'0x0'

I suggest that hex() and oct() have the same check that %x and %o do so that 
non-numbers are not representable as hex and octal.  

While we're at it, we should do the same for bin().  Are there any others?

I'll create a patch once we have a decision on which way to solve this issue.

--
assignee: ethan.furman
messages: 206290
nosy: ethan.furman, gvanrossum, mark.dickinson, pitrou, rhettinger, 
serhiy.storchaka, skrah
priority: normal
severity: normal
status: open
title: hex() and %x, oct() and %o do not behave the same
versions: Python 3.4

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread STINNER Victor

STINNER Victor added the comment:

Calls:
* hex()/oct() = PyNumber_ToBase() = PyNumber_Index().
* PyUnicode_Format() = mainformatlong() = PyNumber_Long()

I never understood the difference between long (__int__ method) and index 
(__index__ method). Is the difference on the behaviour of floating point 
numbers?

--
nosy: +haypo

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Eric V. Smith

Eric V. Smith added the comment:

It seems to me that by giving it an __index__ method, you're saying it can be 
used as an integer. It's not surprising to me that hex(), oct(), and bin() 
would work with a Grade.F object. If anything, I'd say that more places should 
use __index__ than currently do.

--
nosy: +eric.smith

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Victor Stinner commented:
-
 I never understood the difference between long (__int__ method)
 and index (__index__ method). Is the difference on the behaviour
 of floating point numbers?

__index__ was originally added so that non-int integers, such as NumPy's int16, 
int32, etc, integer types could be used as indices and slices.

Now it means if your type can produce a lossless integer, use __index__, 
which is why float and similar types don't define it.

The current meaning is unfortunate in that it is possible to want a type that 
can be used as an index or slice but that is still not a number, and in fact 
won't be used as a number in any scenario _except_ bin(), hex(), and oct().

It seems to me that by having those three functions check that the argument is 
a number, and bailing if it is not, is a decent way to ensure consistency.

One question I do have, since I don't have NumPy installed, is what happens 
with:

  -- NumPy's int's work here? %x % uint16(7)

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread STINNER Victor

STINNER Victor added the comment:

$ python
Python 2.7.5 (default, Nov 12 2013, 16:18:42) 
 import numpy
 hex(numpy.uint16(257))
'0x101'
 %x % numpy.uint16(257)
'101'
 x=numpy.uint16(257)
 x.__int__()
257
 x.__index__()
257

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Stefan Krah

Stefan Krah added the comment:

Ethan Furman rep...@bugs.python.org wrote:
 The current meaning is unfortunate in that it is possible to want a type that
 can be used as an index or slice but that is still not a number, and in fact
 won't be used as a number in any scenario _except_ bin(), hex(), and oct().

memoryview, struct and probably also array.array accept __index__.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Did I mention __index__ is an unfortunate name for the current trend for this 
method?

Stefan Krah commented:
--
 memoryview, struct and probably also array.array accept __index__.

When you say accept __index__ do you mean for use as indices, or for use as 
values in the data structure itself?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Stefan Krah

Stefan Krah added the comment:

 Did I mention __index__ is an unfortunate name for the current trend for this 
 method?

Yes, but it's probably too late to change that now.  Also, a fully precise
name would be something like:

  __to_int_exact_iff_object_has_integer_nature__ :)

 When you say accept __index__ do you mean for use as indices, or for use as
 values in the data structure itself?

The latter, see Lib/test/test_buffer.py:2489 .

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Hmmm...

Well, much as I hate to say it, it's sounding like the correct solution here is 
to have %o and %x work when __index__ is available, instead of the other way 
around.  :(

.format is not an issue because one must specify one's own if inheriting from 
object.

So the complete list of spcecifiers then is d, i, o, u, U, and c [1], and they 
should work if __index__ works.

Are we in agreement?


[1] 
http://docs.python.org/dev/library/stdtypes.html#printf-style-string-formatting

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread STINNER Victor

STINNER Victor added the comment:

 Are we in agreement?

Start maybe on writing unit tests :-)

IMO all int-like objects should behave the same. I don't see any good
reason why hex(value) would succeed whereas %x % value fails. Both
should succeed (or both should fail).

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

  Did I mention __index__ is an unfortunate name for the current trend for
  this method?
 Yes, but it's probably too late to change that now.  Also, a fully precise
 name would be something like:
 
   __to_int_exact_iff_object_has_integer_nature__ :)

Perhaps in future (may be in 4.0) __index__ should be renamed to __int__ and 
__int__ to __trunc__.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Eric V. Smith

Eric V. Smith added the comment:

Yes, I think adding __index__ to d, i, o, u, U, and c is the correct thing to 
do here.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Guido van Rossum

Guido van Rossum added the comment:

Not so fast.  Currently, even in Python 3, '%d' % 3.14 returns '3'.  Fixing 
this will likely break a huge amount of code.

--
versions: +Python 3.5 -Python 3.4

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Guido van Rossum

Guido van Rossum added the comment:

Also (the tracker email interface swallowed this):

 it is possible to want a type that can be used as an index or slice but that 
 is still not a number

I'm sorry, but this requirement is absurd. An index *is* a number. You
have to make up your mind. (I know, in the context of the example that
started this, this is funny, but I still stand by it.)

---

Finally, the correct name should perhaps have been __integer__ but I don't see 
enough reason to change it now.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Eric V. Smith

Eric V. Smith added the comment:

If you were going to make this change, I'd think you'd have to look for 
__index__ and then __int__. But I'll admit I haven't thought through all of the 
ramifications. It would be interesting to see what tests would break.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Eric V. Smith commented:

 If you were going to make this change, I'd think you'd have to look
 for __index__ and then __int__.

Does the order matter?  Are there any types (and should there be) that would 
have both and return different answers for each?

If not, pick an order, try one and, if that one fails, try the other.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Antoine Pitrou

Antoine Pitrou added the comment:

I'm with Guido: it doesn't really make sense to allow __index__ but not __int__ 
on a type. So trying __index__ in str.format() sounds like a distraction.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Arfrever Frehtes Taifersar Arahesis

Changes by Arfrever Frehtes Taifersar Arahesis arfrever@gmail.com:


--
nosy: +Arfrever

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Antoine Pitrou opined:
--
 I'm with Guido: it doesn't really make sense to allow __index__ but not 
 __int__ on
 a type. So trying __index__ in str.format() sounds like a distraction.

  -- hex(3.14)  # calls __index__
  Traceback (most recent call last):
File stdin, line 1, in module
  TypeError: 'float' object cannot be interpreted as an integer

  -- '%x' % 3.14  # calls __int__
  '3'

One of those behaviours is wrong.  Which?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Antoine Pitrou

Antoine Pitrou added the comment:

   -- '%x' % 3.14  # calls __int__
   '3'
 
 One of those behaviours is wrong.  Which?

For '%x' and '%o', it probably doesn't make sense to convert the float
to an int.
(however, it does make sense for other formatters, such as '%d')

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Ethan Furman previously stated:
---
 So the complete list of spcecifiers then is d, i, o, u, U, and c [1], and they
 should work if __index__ works.

Okay, so 'd' then should be considered a conversion operation, whilst the 
others should only work if the object is actually an integer type (which is 
implied by specifying __index__).

In other words

  - if %d or %u is specified, try __int__, then __index__
(according to the docs, u is obsolete and identical to d)

  - if %i, %o, %x, %X, or %c is specified, try only __index__

Agreed?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Antoine Pitrou

Antoine Pitrou added the comment:

 In other words
 
   - if %d or %u is specified, try __int__, then __index__
 (according to the docs, u is obsolete and identical to d)

Again, I don't think trying __index__ is useful.

   - if %i, %o, %x, %X, or %c is specified, try only __index__

I think everything yielding a decimal output should work with floats
(i.e. %i too).

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Antoine, if I understand you correctly, you are saying that any type that 
defines __index__ is an integer, and should therefore also define __int__, in 
which case Python can just use __int__ and not worry about __index__?

Here's the problem with that:

  -- '%x' % 3.14
  '3'

While I am beginning to agree that an integer type needs to implement both 
__int__ and __index__, it still remains true that Python needs to call 
__index__ if what it needs is already a real, true int, and not just something 
that can be truncated or otherwise converted into an int -- such as float.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Antoine Pitrou

Antoine Pitrou added the comment:

 Antoine, if I understand you correctly, you are saying that any type
 that defines __index__ is an integer, and should therefore also define
 __int__, in which case Python can just use __int__ and not worry about
 __index__?

... is an integer-like, yes.

 While I am beginning to agree that an integer type needs to implement
 both __int__ and __index__, it still remains true that Python needs to
 call __index__ if what it needs is already a real, true int, and not
 just something that can be truncated or otherwise converted into an
 int -- such as float.

Of course.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Antoine,

Does that mean you are reducing your previous statement of

 So trying __index__ in str.format() sounds like a distraction.

to using __index__ for %d, %i, and %u is not correct, but is correct for %c, 
%o, %x, and %X ?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Antoine Pitrou

Antoine Pitrou added the comment:

 Antoine,
 
 Does that mean you are reducing your previous statement of
 
  So trying __index__ in str.format() sounds like a distraction.
 
 to using __index__ for %d, %i, and %u is not correct, but is correct
 for %c, %o, %x, and %X ?

Ah, yes, sorry for the confusion :)

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Serhiy Storchaka

Serhiy Storchaka added the comment:

In addition, PyLong_AsLong() calls __int__, while PyLong_AsUnsignedLong() 
doesn't call __int__.

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue19995] hex() and %x, oct() and %o do not behave the same

2013-12-16 Thread Ethan Furman

Ethan Furman added the comment:

Thank you, Victor and Serhiy, for your pointers into the code.

I'm hoping we have general agreement about %c, %o, %x, and %X and having them 
use __index__ only (using __int__ would open the door to float conversions).

I still have a question about %i, though.  The docs say %u is exactly the same 
as %d and is therefore deprecated.  The docs do not say thay %i is the same as 
%d, but the descriptions are the same.

Are %i and %d the same, or is there some difference?

--

___
Python tracker rep...@bugs.python.org
http://bugs.python.org/issue19995
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com