diff -r b668c409c10a Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst Sat Dec 28 20:37:58 2013 +0100 +++ b/Doc/reference/datamodel.rst Sun Dec 29 01:14:37 2013 -0800 @@ -2077,20 +2077,26 @@ left undefined. :func:`int`, :func:`float` and :func:`round`. Should return a value of the appropriate type. .. method:: object.__index__(self) Called to implement :func:`operator.index`. Also called whenever Python needs an integer object (such as in slicing, or in the built-in :func:`bin`, :func:`hex` and :func:`oct` functions). Must return an integer. + .. note:: + + When :meth:`__index__` is defined, :meth:`__int__` should also be defined, + and both shuld return the same value, in order to have a coherent integer + type class. + .. _context-managers: With Statement Context Managers ------------------------------- A :dfn:`context manager` is an object that defines the runtime context to be established when executing a :keyword:`with` statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the diff -r b668c409c10a Lib/tarfile.py --- a/Lib/tarfile.py Sat Dec 28 20:37:58 2013 +0100 +++ b/Lib/tarfile.py Sun Dec 29 01:14:37 2013 -0800 @@ -189,21 +189,21 @@ def itn(n, digits=8, format=DEFAULT_FORM """ # POSIX 1003.1-1988 requires numbers to be encoded as a string of # octal digits followed by a null-byte, this allows values up to # (8**(digits-1))-1. GNU tar allows storing numbers greater than # that if necessary. A leading 0o200 or 0o377 byte indicate this # particular encoding, the following digits-1 bytes are a big-endian # base-256 representation. This allows values up to (256**(digits-1))-1. # A 0o200 byte indicates a positive number, a 0o377 byte a negative # number. if 0 <= n < 8 ** (digits - 1): - s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL + s = bytes("%0*o" % (digits - 1, int(n)), "ascii") + NUL elif format == GNU_FORMAT and -256 ** (digits - 1) <= n < 256 ** (digits - 1): if n >= 0: s = bytearray([0o200]) else: s = bytearray([0o377]) n = 256 ** digits + n for i in range(digits - 1): s.insert(1, n & 0o377) n >>= 8 diff -r b668c409c10a Lib/test/test_format.py --- a/Lib/test/test_format.py Sat Dec 28 20:37:58 2013 +0100 +++ b/Lib/test/test_format.py Sun Dec 29 01:14:37 2013 -0800 @@ -135,21 +135,20 @@ class FormatTest(unittest.TestCase): testformat("%#+.23X", big, "+0X001234567890ABCDEF12345") testformat("%#-+.23X", big, "+0X001234567890ABCDEF12345") testformat("%#-+26.23X", big, "+0X001234567890ABCDEF12345") testformat("%#-+27.23X", big, "+0X001234567890ABCDEF12345 ") testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345") # next one gets two leading zeroes from precision, and another from the # 0 flag and the width testformat("%#+027.23X", big, "+0X0001234567890ABCDEF12345") # same, except no 0 flag testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345") - testformat("%x", float(big), "123456_______________", 6) big = 0o12345670123456701234567012345670 # 32 octal digits testformat("%o", big, "12345670123456701234567012345670") testformat("%o", -big, "-12345670123456701234567012345670") testformat("%5o", -big, "-12345670123456701234567012345670") testformat("%33o", -big, "-12345670123456701234567012345670") testformat("%34o", -big, " -12345670123456701234567012345670") testformat("%-34o", -big, "-12345670123456701234567012345670 ") testformat("%034o", -big, "-012345670123456701234567012345670") testformat("%-034o", -big, "-12345670123456701234567012345670 ") testformat("%036o", -big, "-00012345670123456701234567012345670") @@ -175,54 +174,50 @@ class FormatTest(unittest.TestCase): # next one gets one leading zero from precision testformat("%.33o", big, "012345670123456701234567012345670") # base marker shouldn't change that, since "0" is redundant testformat("%#.33o", big, "0o012345670123456701234567012345670") # but reduce precision, and base marker should add a zero testformat("%#.32o", big, "0o12345670123456701234567012345670") # one leading zero from precision, and another from "0" flag & width testformat("%034.33o", big, "0012345670123456701234567012345670") # base marker shouldn't change that testformat("%0#34.33o", big, "0o012345670123456701234567012345670") - testformat("%o", float(big), "123456__________________________", 6) # Some small ints, in both Python int and flavors). testformat("%d", 42, "42") testformat("%d", -42, "-42") testformat("%d", 42, "42") testformat("%d", -42, "-42") testformat("%d", 42.0, "42") testformat("%#x", 1, "0x1") testformat("%#x", 1, "0x1") testformat("%#X", 1, "0X1") testformat("%#X", 1, "0X1") - testformat("%#x", 1.0, "0x1") testformat("%#o", 1, "0o1") testformat("%#o", 1, "0o1") testformat("%#o", 0, "0o0") testformat("%#o", 0, "0o0") testformat("%o", 0, "0") testformat("%o", 0, "0") testformat("%d", 0, "0") testformat("%d", 0, "0") testformat("%#x", 0, "0x0") testformat("%#x", 0, "0x0") testformat("%#X", 0, "0X0") testformat("%#X", 0, "0X0") testformat("%x", 0x42, "42") testformat("%x", -0x42, "-42") testformat("%x", 0x42, "42") testformat("%x", -0x42, "-42") - testformat("%x", float(0x42), "42") testformat("%o", 0o42, "42") testformat("%o", -0o42, "-42") testformat("%o", 0o42, "42") testformat("%o", -0o42, "-42") - testformat("%o", float(0o42), "42") testformat("%r", "\u0378", "'\\u0378'") # non printable testformat("%a", "\u0378", "'\\u0378'") # non printable testformat("%r", "\u0374", "'\u0374'") # printable testformat("%a", "\u0374", "'\\u0374'") # printable # alternate float formatting testformat('%g', 1.1, '1.1') testformat('%#g', 1.1, '1.10000') # Test exception for unknown format characters diff -r b668c409c10a Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py Sat Dec 28 20:37:58 2013 +0100 +++ b/Lib/test/test_unicode.py Sun Dec 29 01:14:37 2013 -0800 @@ -1119,20 +1119,49 @@ 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') + #issue 19995 + class PsuedoInt: + def __init__(self, value): + self.value = int(value) + def __int__(self): + return self.value + def __index__(self): + return self.value + class PsuedoFlaot: + def __init__(self, value): + self.value = float(value) + def __int__(self): + return int(self.value) + pi = PsuedoFlaot(3.1415) + letter_m = PsuedoInt(109) + self.assertEquals('%x' % 42, '2a') + self.assertEquals('%X' % 15, 'F') + self.assertEquals('%o' % 9, '11') + self.assertEquals('%c' % 109, 'm') + self.assertEquals('%x' % letter_m, '6d') + self.assertEquals('%X' % letter_m, '6D') + self.assertEquals('%o' % letter_m, '155') + self.assertEquals('%c' % letter_m, 'm') + self.assertRaises(TypeError, '%x'.__mod__, pi) + self.assertRaises(TypeError, '%x'.__mod__, 3.14) + self.assertRaises(TypeError, '%X'.__mod__, 2.11) + self.assertRaises(TypeError, '%o'.__mod__, 1.79) + self.assertRaises(TypeError, '%c'.__mod__, pi) + def test_formatting_with_enum(self): # issue18780 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... diff -r b668c409c10a Objects/unicodeobject.c --- a/Objects/unicodeobject.c Sat Dec 28 20:37:58 2013 +0100 +++ b/Objects/unicodeobject.c Sun Dec 29 01:14:37 2013 -0800 @@ -14008,42 +14008,50 @@ formatlong(PyObject *val, struct unicode Py_DECREF(result); result = unicode; } else if (len != PyUnicode_GET_LENGTH(result)) { if (PyUnicode_Resize(&result, len) < 0) Py_CLEAR(result); } return result; } -/* Format an integer. +/* Format an integer or a float as an integer. * Return 1 if the number has been formatted into the writer, * 0 if the number has been formatted into *p_output * -1 and raise an exception on error */ static int mainformatlong(PyObject *v, struct unicode_format_arg_t *arg, PyObject **p_output, _PyUnicodeWriter *writer) { PyObject *iobj, *res; char type = (char)arg->ch; if (!PyNumber_Check(v)) goto wrongtype; if (!PyLong_Check(v)) { - iobj = PyNumber_Long(v); - if (iobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - goto wrongtype; - return -1; + if (type == 'o' || type == 'x' || type == 'X') { + iobj = PyNumber_Index(v); + if (iobj == NULL) { + return -1; + } + } + else { + iobj = PyNumber_Long(v); + if (iobj == NULL ) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) + goto wrongtype; + return -1; + } } assert(PyLong_Check(iobj)); } else { iobj = v; Py_INCREF(iobj); } if (PyLong_CheckExact(v) && arg->width == -1 && arg->prec == -1 @@ -14099,22 +14107,32 @@ static Py_UCS4 formatchar(PyObject *v) { /* presume that the buffer is at least 3 characters long */ if (PyUnicode_Check(v)) { if (PyUnicode_GET_LENGTH(v) == 1) { return PyUnicode_READ_CHAR(v, 0); } goto onError; } else { + PyObject *iobj; + long x; + /* make sure number is a type of integer */ + if (!PyLong_Check(v)) { + iobj = PyNumber_Index(v); + if (iobj == NULL) { + goto onError; + } + v = iobj; + Py_DECREF(iobj); + } /* Integer input truncated to a character */ - long x; x = PyLong_AsLong(v); if (x == -1 && PyErr_Occurred()) goto onError; if (x < 0 || x > MAX_UNICODE) { PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)"); return (Py_UCS4) -1; } @@ -14302,21 +14320,22 @@ unicode_format_arg_parse(struct unicode_ return -1; } return 0; #undef FORMAT_READ } /* Format one argument. Supported conversion specifiers: - "s", "r", "a": any type - - "i", "d", "u", "o", "x", "X": int + - "i", "d", "u": int or float + - "o", "x", "X": int - "e", "E", "f", "F", "g", "G": float - "c": int or str (1 character) When possible, the output is written directly into the Unicode writer (ctx->writer). A string is created when padding is required. Return 0 if the argument has been formatted into *p_str, 1 if the argument has been written into ctx->writer, -1 on error. */ static int