Index: Lib/test/test_struct.py =================================================================== --- Lib/test/test_struct.py (revision 79716) +++ Lib/test/test_struct.py (working copy) @@ -289,6 +289,25 @@ def __long__(self): return -163L + # Objects with an '__index__' method should be allowed + # to pack as integers. That is assuming the implemented + # '__index__' method returns and 'int' or 'long'. + class Indexable(object): + def __init__(self, value): + self._value = value + + def __index__(self): + return self._value + + # If the '__index__' method raises a type error, then + # '__int__' should be used with a deprecation warning. + class BadIndex(object): + def __index__(self): + raise TypeError + + def __int__(self): + return 42 + self.assertRaises((TypeError, struct.error), struct.pack, self.format, "a string") @@ -304,7 +323,7 @@ # an attempt to convert a non-integer (with an # implicit conversion via __int__) should succeed, # with a DeprecationWarning - for nonint in NotAnIntNS(), NotAnIntOS(): + for nonint in NotAnIntNS(), NotAnIntOS(), BadIndex(): with check_warnings((".*integer argument expected, got non" "-integer", DeprecationWarning)) as w: got = struct.pack(self.format, nonint) @@ -315,15 +334,7 @@ expected = struct.pack(self.format, int(nonint)) self.assertEqual(got, expected) - # Objects with an '__index__' method should be allowed - # to pack as integers. - class Indexable(object): - def __init__(self, value): - self._value = value - - def __index__(self): - return self._value - + # Check for legitimate values from '__index__'. for obj in (Indexable(0), Indexable(10), Indexable(17), Indexable(42), Indexable(100), Indexable(127)): try: @@ -332,6 +343,12 @@ self.fail("integer code pack failed on object " "with '__index__' method") + # Check for bogus values from '__index__'. + for obj in (Indexable('a'), Indexable(u'b'), Indexable(None), + Indexable({'a': 1}), Indexable([1, 2, 3])): + self.assertRaises((TypeError, struct.error), + struct.pack, self.format, + obj) byteorders = '', '@', '=', '<', '>', '!' for code in integer_codes: Index: Modules/_struct.c =================================================================== --- Modules/_struct.c (revision 79716) +++ Modules/_struct.c (working copy) @@ -123,12 +123,6 @@ w = PyNumber_Index(v); if (w != NULL) { v = w; - if (!PyInt_Check(v) && !PyLong_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "__index__ method " - "returned non-integer"); - return NULL; - } /* successfully converted to an integer */ converted = 1; }