[Python-checkins] r71754 - in python/branches/py3k: Lib/test/test_struct.py Misc/NEWS Modules/_struct.c

mark.dickinson python-checkins at python.org
Sun Apr 19 22:40:34 CEST 2009


Author: mark.dickinson
Date: Sun Apr 19 22:40:33 2009
New Revision: 71754
Log:
Issue #5463: Remove deprecated float coercion from struct module, along
with the _PY_STRUCT_FLOAT_COERCE constant. Simplify tests accordingly,
and reenable (now-fixed) broken tests.
Modified:
 python/branches/py3k/Lib/test/test_struct.py
 python/branches/py3k/Misc/NEWS
 python/branches/py3k/Modules/_struct.c
Modified: python/branches/py3k/Lib/test/test_struct.py
==============================================================================
--- python/branches/py3k/Lib/test/test_struct.py	(original)
+++ python/branches/py3k/Lib/test/test_struct.py	Sun Apr 19 22:40:33 2009
@@ -11,13 +11,6 @@
 IS32BIT = sys.maxsize == 0x7fffffff
 del sys
 
-try:
- import _struct
-except ImportError:
- PY_STRUCT_FLOAT_COERCE = 2
-else:
- PY_STRUCT_FLOAT_COERCE = getattr(_struct, '_PY_STRUCT_FLOAT_COERCE', 0)
-
 def string_reverse(s):
 return s[::-1]
 
@@ -27,40 +20,7 @@
 else:
 return string_reverse(value)
 
-def with_warning_restore(func):
- @wraps(func)
- def decorator(*args, **kw):
- with warnings.catch_warnings():
- # We need this function to warn every time, so stick an
- # unqualifed 'always' at the head of the filter list
- warnings.simplefilter("always")
- warnings.filterwarnings("error", category=DeprecationWarning)
- return func(*args, **kw)
- return decorator
-
 class StructTest(unittest.TestCase):
-
- @with_warning_restore
- def check_float_coerce(self, format, number):
- # SF bug 1530559. struct.pack raises TypeError where it used to convert.
- if PY_STRUCT_FLOAT_COERCE == 2:
- # Test for pre-2.5 struct module
- packed = struct.pack(format, number)
- floored = struct.unpack(format, packed)[0]
- self.assertEqual(floored, int(number),
- "did not correcly coerce float to int")
- return
- try:
- struct.pack(format, number)
- except (struct.error, TypeError):
- if PY_STRUCT_FLOAT_COERCE:
- self.fail("expected DeprecationWarning for float coerce")
- except DeprecationWarning:
- if not PY_STRUCT_FLOAT_COERCE:
- self.fail("expected to raise struct.error for float coerce")
- else:
- self.fail("did not raise error for float coerce")
-
 def test_isbigendian(self):
 self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
 
@@ -270,10 +230,8 @@
 
 else:
 # x is out of range -- verify pack realizes that.
- self.assertRaises((struct.error, OverflowError),
- pack, ">" + code, x)
- self.assertRaises((struct.error, OverflowError),
- pack, "<" + code, x)
+ self.assertRaises(struct.error, pack, ">" + code, x)
+ self.assertRaises(struct.error, pack, "<" + code, x)
 
 # Much the same for unsigned.
 code = self.unsigned_code
@@ -317,10 +275,8 @@
 
 else:
 # x is out of range -- verify pack realizes that.
- self.assertRaises((struct.error, OverflowError),
- pack, ">" + code, x)
- self.assertRaises((struct.error, OverflowError),
- pack, "<" + code, x)
+ self.assertRaises(struct.error, pack, ">" + code, x)
+ self.assertRaises(struct.error, pack, "<" + code, x)
 
 def run(self):
 from random import randrange
@@ -353,10 +309,10 @@
 # Some error cases.
 for direction in "<>":
 for code in self.formatpair:
- for badobject in "a string", 3+42j, randrange:
- self.assertRaises((struct.error, TypeError),
- struct.pack, direction + code,
- badobject)
+ for badobject in "a string", 3+42j, randrange, -1729.0:
+ self.assertRaises(struct.error,
+ struct.pack, direction + code,
+ badobject)
 
 for args in [("bB", 1),
 ("hH", 2),
@@ -437,13 +393,14 @@
 self.assertRaises((struct.error, OverflowError), struct.pack,
 endian + 'L', sys.maxsize * 4)
 
- def XXXtest_1530559(self):
- # XXX This is broken: see the bug report
- # SF bug 1530559. struct.pack raises TypeError where it used to convert.
+ def test_1530559(self):
 for endian in ('', '>', '<'):
- for fmt in ('B', 'H', 'I', 'L', 'b', 'h', 'i', 'l'):
- self.check_float_coerce(endian + fmt, 1.0)
- self.check_float_coerce(endian + fmt, 1.5)
+ for fmt in ('B', 'H', 'I', 'L', 'Q', 'b', 'h', 'i', 'l', 'q'):
+ self.assertRaises(struct.error, struct.pack, endian + fmt, 1.0)
+ self.assertRaises(struct.error, struct.pack, endian + fmt, 1.5)
+ self.assertRaises(struct.error, struct.pack, 'P', 1.0)
+ self.assertRaises(struct.error, struct.pack, 'P', 1.5)
+
 
 def test_unpack_from(self):
 test_string = b'abcd01234'
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sun Apr 19 22:40:33 2009
@@ -87,6 +87,11 @@
 Extension Modules
 -----------------
 
+- Issue #5463: In struct module, remove deprecated float coercion
+ for integer type codes: struct.pack('L', 0.3) should now raise
+ an error. The _PY_STRUCT_FLOAT_COERCE constant has been removed.
+ The version number has been bumped to 0.3.
+
 - Issue #5359: Readd the Berkley-DB detection code to allow _dbm be built
 using Berkley-DB.
 
Modified: python/branches/py3k/Modules/_struct.c
==============================================================================
--- python/branches/py3k/Modules/_struct.c	(original)
+++ python/branches/py3k/Modules/_struct.c	Sun Apr 19 22:40:33 2009
@@ -12,17 +12,6 @@
 
 static PyTypeObject PyStructType;
 
-/* If PY_STRUCT_FLOAT_COERCE is defined, the struct module will allow float
- arguments for integer formats with a warning for backwards
- compatibility. */
-
-#define PY_STRUCT_FLOAT_COERCE 1
-
-#ifdef PY_STRUCT_FLOAT_COERCE
-#define FLOAT_COERCE "integer argument expected, got float"
-#endif
-
-
 /* The translation function for each format character is table driven */
 typedef struct _formatdef {
 	char format;
@@ -100,58 +89,40 @@
 #pragma options align=reset
 #endif
 
-/* Helper to get a PyLongObject by hook or by crook. Caller should decref. */
+/* Helper to get a PyLongObject. Caller should decref. */
 
 static PyObject *
 get_pylong(PyObject *v)
 {
-	PyNumberMethods *m;
-
 	assert(v != NULL);
-	if (PyLong_Check(v)) {
-		Py_INCREF(v);
-		return v;
-	}
-	m = Py_TYPE(v)->tp_as_number;
-	if (m != NULL && m->nb_int != NULL) {
-		v = m->nb_int(v);
-		if (v == NULL)
-			return NULL;
-		if (PyLong_Check(v))
-			return v;
-		Py_DECREF(v);
+	if (!PyLong_Check(v)) {
+		PyErr_SetString(StructError,
+				"required argument is not an integer");
+		return NULL;
 	}
-	PyErr_SetString(StructError,
-			"cannot convert argument to long");
-	return NULL;
+
+	Py_INCREF(v);
+	return v;
 }
 
-/* Helper routine to get a Python integer and raise the appropriate error
- if it isn't one */
+/* Helper routine to get a C long and raise the appropriate error if it isn't
+ one */
 
 static int
 get_long(PyObject *v, long *p)
 {
-	long x = PyLong_AsLong(v);
+	long x;
+
+	if (!PyLong_Check(v)) {
+		PyErr_SetString(StructError,
+				"required argument is not an integer");
+		return -1;
+	}
+	x = PyLong_AsLong(v);
 	if (x == -1 && PyErr_Occurred()) {
-#ifdef PY_STRUCT_FLOAT_COERCE
-		if (PyFloat_Check(v)) {
-			PyObject *o;
-			int res;
-			PyErr_Clear();
-			if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0)
-				return -1;
-			o = PyNumber_Long(v);
-			if (o == NULL)
-				return -1;
-			res = get_long(o, p);
-			Py_DECREF(o);
-			return res;
-		}
-#endif
-		if (PyErr_ExceptionMatches(PyExc_TypeError))
+		if (PyErr_ExceptionMatches(PyExc_OverflowError))
 			PyErr_SetString(StructError,
-					"required argument is not an integer");
+					"argument out of range");
 		return -1;
 	}
 	*p = x;
@@ -164,20 +135,21 @@
 static int
 get_ulong(PyObject *v, unsigned long *p)
 {
-	if (PyLong_Check(v)) {
-		unsigned long x = PyLong_AsUnsignedLong(v);
-		if (x == (unsigned long)(-1) && PyErr_Occurred())
-			return -1;
-		*p = x;
-		return 0;
-	}
-	if (get_long(v, (long *)p) < 0)
-		return -1;
-	if (((long)*p) < 0) {
+	unsigned long x;
+
+	if (!PyLong_Check(v)) {
 		PyErr_SetString(StructError,
-				"unsigned argument is < 0");
+				"required argument is not an integer");
 		return -1;
 	}
+	x = PyLong_AsUnsignedLong(v);
+	if (x == (unsigned long)-1 && PyErr_Occurred()) {
+		if (PyErr_ExceptionMatches(PyExc_OverflowError))
+			PyErr_SetString(StructError,
+					"argument out of range");
+		return -1;
+	}
+	*p = x;
 	return 0;
 }
 
@@ -189,15 +161,18 @@
 get_longlong(PyObject *v, PY_LONG_LONG *p)
 {
 	PY_LONG_LONG x;
-
-	v = get_pylong(v);
-	if (v == NULL)
+	if (!PyLong_Check(v)) {
+		PyErr_SetString(StructError,
+				"required argument is not an integer");
 		return -1;
-	assert(PyLong_Check(v));
+	}
 	x = PyLong_AsLongLong(v);
-	Py_DECREF(v);
-	if (x == (PY_LONG_LONG)-1 && PyErr_Occurred())
+	if (x == -1 && PyErr_Occurred()) {
+		if (PyErr_ExceptionMatches(PyExc_OverflowError))
+			PyErr_SetString(StructError,
+					"argument out of range");
 		return -1;
+	}
 	*p = x;
 	return 0;
 }
@@ -208,15 +183,18 @@
 get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
 {
 	unsigned PY_LONG_LONG x;
-
-	v = get_pylong(v);
-	if (v == NULL)
+	if (!PyLong_Check(v)) {
+		PyErr_SetString(StructError,
+				"required argument is not an integer");
 		return -1;
-	assert(PyLong_Check(v));
+	}
 	x = PyLong_AsUnsignedLongLong(v);
-	Py_DECREF(v);
-	if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
+	if (x == -1 && PyErr_Occurred()) {
+		if (PyErr_ExceptionMatches(PyExc_OverflowError))
+			PyErr_SetString(StructError,
+					"argument out of range");
 		return -1;
+	}
 	*p = x;
 	return 0;
 }
@@ -1962,7 +1940,7 @@
 {
 	PyObject *ver, *m;
 
-	ver = PyBytes_FromString("0.2");
+	ver = PyBytes_FromString("0.3");
 	if (ver == NULL)
 		return NULL;
 
@@ -2028,9 +2006,5 @@
 
 	PyModule_AddObject(m, "__version__", ver);
 
-#ifdef PY_STRUCT_FLOAT_COERCE
-	PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1);
-#endif
 	return m;
-
 }


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /