diff -r df2fdd42b375 Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py Mon Aug 26 22:28:21 2013 +0200 +++ b/Lib/test/test_unicode.py Tue Aug 27 19:11:51 2013 -0700 @@ -1117,20 +1117,41 @@ class UnicodeTest(string_tests.CommonTes INF = float('inf') self.assertEqual('%f' % NAN, 'nan') self.assertEqual('%F' % NAN, 'NAN') self.assertEqual('%f' % INF, 'inf') self.assertEqual('%F' % INF, 'INF') # PEP 393 self.assertEqual('%.1s' % "a\xe9\u20ac", 'a') self.assertEqual('%.2s' % "a\xe9\u20ac", 'a\xe9') + def test_formatting_with_enum(self): + # issue18738 + import enum + class Float(float, enum.Enum): + PI = 3.1415926 + class Int(enum.IntEnum): + IDES = 15 + class Str(str, enum.Enum): + ABC = 'abc' + # Testing Unicode formatting strings... + self.assertEqual("%s, %s" % (Str.ABC, Str.ABC), 'Str.ABC, Str.ABC') + self.assertEqual("%s, %s, %d, %i, %u, %f, %5.2f" % (Str.ABC, Str.ABC, Int.IDES, Int.IDES, Int.IDES, Float.PI, Float.PI), 'Str.ABC, Str.ABC, 15, 15, 15, 3.141593, 3.14') + + # formatting jobs delegated from the string implementation: + self.assertEqual('...%(foo)s...' % {'foo':Str.ABC}, '...Str.ABC...') + self.assertEqual('...%(foo)s...' % {'foo':Int.IDES}, '...Int.IDES...') + self.assertEqual('...%(foo)i...' % {'foo':Int.IDES}, '...15...') + self.assertEqual('...%(foo)d...' % {'foo':Int.IDES}, '...15...') + self.assertEqual('...%(foo)u...' % {'foo':Int.IDES,'def':Float.PI}, '...15...') + self.assertEqual('...%(foo)f...' % {'foo':Float.PI,'def':123}, '...3.141593...') + @support.cpython_only def test_formatting_huge_precision(self): from _testcapi import INT_MAX format_string = "%.{}f".format(INT_MAX + 1) with self.assertRaises(ValueError): result = format_string % 2.34 def test_formatting_huge_width(self): format_string = "%{}f".format(sys.maxsize + 1) with self.assertRaises(ValueError): diff -r df2fdd42b375 Objects/unicodeobject.c --- a/Objects/unicodeobject.c Mon Aug 26 22:28:21 2013 +0200 +++ b/Objects/unicodeobject.c Tue Aug 27 19:11:51 2013 -0700 @@ -13560,24 +13560,22 @@ formatlong(PyObject *val, struct unicode assert(PyLong_Check(val)); switch (type) { default: assert(!"'type' not in [diuoxX]"); case 'd': case 'i': case 'u': /* Special-case boolean: we want 0/1 */ - if (PyBool_Check(val)) - result = PyNumber_ToBase(val, 10); - else - result = Py_TYPE(val)->tp_str(val); + /* on second thought, all int subclasses should behave this way */ + result = PyNumber_ToBase(val, 10); break; case 'o': numnondigits = 2; result = PyNumber_ToBase(val, 8); break; case 'x': case 'X': numnondigits = 2; result = PyNumber_ToBase(val, 16); break;