This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eric.smith
Recipients barry, eli.bendersky, eric.smith, ethan.furman, serhiy.storchaka
Date 2013-08-19.12:45:37
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1376916338.02.0.276331604909.issue18738@psf.upfronthosting.co.za>
In-reply-to
Content
Oh, I don't feel my time has been wasted. Where else can I have a discussion of __format__?

With this patch, given this:

class UpperString(str):
  def __format__(self, fmt):
    return str.__format__(self, fmt).upper()

class UpperEnum(UpperString, Enum):
  pass

class S(UpperEnum):
  a = 'a'
  b = 'b'

this gives the (to me) surprising results of:

>>> format(S.a)
'S.a'
>>> format(S.a, '10')
'S.a       '
>>> format(S.a, '10s')
'A         '

I'd expect this to always use UpperString.__format__, since it understands all str format specs.

And before you say UpperString is contrived, I've used classes like it in the past: they're just like a string, but the __format__ method does something special after calling through to str.__format__. 

Which is why I think __format__ has to go in the derived type (IntEnum, in the originally reported case): only it can decide whether to call str.__format__ or the mix-in class's __format__.

Now, whether or not Enum needs to support such classes with specialized __format___, I can't say. I suppose it's not super-important. But it will be difficult to explain all of this.

Also, the patch give this:

>>> class E(IntEnum):
...   one = 1
...   two = 2
... 
>>> format(E.one)
'E.one'
>>> format(E.one, 's')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/eric/local/python/cpython/Lib/enum.py", line 463, in __format__
    return obj.__format__(val, format_spec)
ValueError: Unknown format code 's' for object of type 'int'

I can't format it using the 's' presentation type, despite the fact it looks like a string. I think you need to add 's' to your _remove_plain_format_chars.

And consider this valid (but arguably pathological) code:

>>> format(datetime.datetime.now(), '10')
'10'

Despite this being a valid datetime format spec, your code would consider it a str spec.

tl;dr: I think __format__ belongs in the class that understands how the subclass handles format specs.
History
Date User Action Args
2013-08-19 12:45:38eric.smithsetrecipients: + eric.smith, barry, eli.bendersky, ethan.furman, serhiy.storchaka
2013-08-19 12:45:38eric.smithsetmessageid: <1376916338.02.0.276331604909.issue18738@psf.upfronthosting.co.za>
2013-08-19 12:45:38eric.smithlinkissue18738 messages
2013-08-19 12:45:37eric.smithcreate