Kaydet (Commit) fdaaa9c9 authored tarafından Mark Dickinson's avatar Mark Dickinson

Issue #8300 (__index__ handling in struct.pack): Remove redundant check

and improve test coverage.  Thanks Meador Inge for the patch.
üst 0d57caa2
...@@ -289,6 +289,25 @@ class StructTest(unittest.TestCase): ...@@ -289,6 +289,25 @@ class StructTest(unittest.TestCase):
def __long__(self): def __long__(self):
return -163L 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), self.assertRaises((TypeError, struct.error),
struct.pack, self.format, struct.pack, self.format,
"a string") "a string")
...@@ -304,7 +323,7 @@ class StructTest(unittest.TestCase): ...@@ -304,7 +323,7 @@ class StructTest(unittest.TestCase):
# an attempt to convert a non-integer (with an # an attempt to convert a non-integer (with an
# implicit conversion via __int__) should succeed, # implicit conversion via __int__) should succeed,
# with a DeprecationWarning # with a DeprecationWarning
for nonint in NotAnIntNS(), NotAnIntOS(): for nonint in NotAnIntNS(), NotAnIntOS(), BadIndex():
with check_warnings((".*integer argument expected, got non" with check_warnings((".*integer argument expected, got non"
"-integer", DeprecationWarning)) as w: "-integer", DeprecationWarning)) as w:
got = struct.pack(self.format, nonint) got = struct.pack(self.format, nonint)
...@@ -315,15 +334,7 @@ class StructTest(unittest.TestCase): ...@@ -315,15 +334,7 @@ class StructTest(unittest.TestCase):
expected = struct.pack(self.format, int(nonint)) expected = struct.pack(self.format, int(nonint))
self.assertEqual(got, expected) self.assertEqual(got, expected)
# Objects with an '__index__' method should be allowed # Check for legitimate values from '__index__'.
# to pack as integers.
class Indexable(object):
def __init__(self, value):
self._value = value
def __index__(self):
return self._value
for obj in (Indexable(0), Indexable(10), Indexable(17), for obj in (Indexable(0), Indexable(10), Indexable(17),
Indexable(42), Indexable(100), Indexable(127)): Indexable(42), Indexable(100), Indexable(127)):
try: try:
...@@ -332,6 +343,12 @@ class StructTest(unittest.TestCase): ...@@ -332,6 +343,12 @@ class StructTest(unittest.TestCase):
self.fail("integer code pack failed on object " self.fail("integer code pack failed on object "
"with '__index__' method") "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 = '', '@', '=', '<', '>', '!' byteorders = '', '@', '=', '<', '>', '!'
for code in integer_codes: for code in integer_codes:
......
...@@ -123,12 +123,6 @@ get_pylong(PyObject *v) ...@@ -123,12 +123,6 @@ get_pylong(PyObject *v)
w = PyNumber_Index(v); w = PyNumber_Index(v);
if (w != NULL) { if (w != NULL) {
v = w; 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 */ /* successfully converted to an integer */
converted = 1; converted = 1;
} }
...@@ -175,6 +169,7 @@ get_pylong(PyObject *v) ...@@ -175,6 +169,7 @@ get_pylong(PyObject *v)
/* Ensure we own a reference to v. */ /* Ensure we own a reference to v. */
Py_INCREF(v); Py_INCREF(v);
assert(PyInt_Check(v) || PyLong_Check(v));
if (PyInt_Check(v)) { if (PyInt_Check(v)) {
r = PyLong_FromLong(PyInt_AS_LONG(v)); r = PyLong_FromLong(PyInt_AS_LONG(v));
Py_DECREF(v); Py_DECREF(v);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment