Issue #5080: turn the DeprecationWarning from float arguments passed

to integer PyArg_Parse* format codes into a TypeError.  Add a
DeprecationWarning for floats passed with the 'L' format code, which
didn't previously have a warning.
This commit is contained in:
Mark Dickinson 2010-01-01 17:27:30 +00:00
parent edfe72f66f
commit 1b34d2552c
6 changed files with 65 additions and 28 deletions

View file

@ -752,7 +752,7 @@ if not _exists("urandom"):
raise NotImplementedError("/dev/urandom (or equivalent) not found")
try:
bs = b""
while n - len(bs) >= 1:
while n > len(bs):
bs += read(_urandomfd, n - len(bs))
finally:
close(_urandomfd)

View file

@ -1,16 +1,7 @@
import unittest
from test import test_support
from _testcapi import getargs_keywords
import warnings
warnings.filterwarnings("ignore",
category=DeprecationWarning,
message=".*integer argument expected, got float",
module=__name__)
warnings.filterwarnings("ignore",
category=DeprecationWarning,
message=".*integer argument expected, got float",
module="unittest")
"""
> How about the following counterproposal. This also changes some of
@ -68,7 +59,7 @@ class Unsigned_TestCase(unittest.TestCase):
def test_b(self):
from _testcapi import getargs_b
# b returns 'unsigned char', and does range checking (0 ... UCHAR_MAX)
self.assertEqual(3, getargs_b(3.14))
self.assertRaises(TypeError, getargs_b, 3.14)
self.assertEqual(99, getargs_b(Long()))
self.assertEqual(99, getargs_b(Int()))
@ -84,7 +75,7 @@ class Unsigned_TestCase(unittest.TestCase):
def test_B(self):
from _testcapi import getargs_B
# B returns 'unsigned char', no range checking
self.assertEqual(3, getargs_B(3.14))
self.assertRaises(TypeError, getargs_B, 3.14)
self.assertEqual(99, getargs_B(Long()))
self.assertEqual(99, getargs_B(Int()))
@ -101,7 +92,7 @@ class Unsigned_TestCase(unittest.TestCase):
def test_H(self):
from _testcapi import getargs_H
# H returns 'unsigned short', no range checking
self.assertEqual(3, getargs_H(3.14))
self.assertRaises(TypeError, getargs_H, 3.14)
self.assertEqual(99, getargs_H(Long()))
self.assertEqual(99, getargs_H(Int()))
@ -118,7 +109,7 @@ class Unsigned_TestCase(unittest.TestCase):
def test_I(self):
from _testcapi import getargs_I
# I returns 'unsigned int', no range checking
self.assertEqual(3, getargs_I(3.14))
self.assertRaises(TypeError, getargs_I, 3.14)
self.assertEqual(99, getargs_I(Long()))
self.assertEqual(99, getargs_I(Int()))
@ -154,7 +145,7 @@ class Signed_TestCase(unittest.TestCase):
def test_h(self):
from _testcapi import getargs_h
# h returns 'short', and does range checking (SHRT_MIN ... SHRT_MAX)
self.assertEqual(3, getargs_h(3.14))
self.assertRaises(TypeError, getargs_h, 3.14)
self.assertEqual(99, getargs_h(Long()))
self.assertEqual(99, getargs_h(Int()))
@ -170,7 +161,7 @@ class Signed_TestCase(unittest.TestCase):
def test_i(self):
from _testcapi import getargs_i
# i returns 'int', and does range checking (INT_MIN ... INT_MAX)
self.assertEqual(3, getargs_i(3.14))
self.assertRaises(TypeError, getargs_i, 3.14)
self.assertEqual(99, getargs_i(Long()))
self.assertEqual(99, getargs_i(Int()))
@ -186,7 +177,7 @@ class Signed_TestCase(unittest.TestCase):
def test_l(self):
from _testcapi import getargs_l
# l returns 'long', and does range checking (LONG_MIN ... LONG_MAX)
self.assertEqual(3, getargs_l(3.14))
self.assertRaises(TypeError, getargs_l, 3.14)
self.assertEqual(99, getargs_l(Long()))
self.assertEqual(99, getargs_l(Int()))
@ -203,7 +194,7 @@ class Signed_TestCase(unittest.TestCase):
from _testcapi import getargs_n
# n returns 'Py_ssize_t', and does range checking
# (PY_SSIZE_T_MIN ... PY_SSIZE_T_MAX)
self.assertEqual(3, getargs_n(3.14))
self.assertRaises(TypeError, getargs_n, 3.14)
self.assertEqual(99, getargs_n(Long()))
self.assertEqual(99, getargs_n(Int()))
@ -220,9 +211,24 @@ class Signed_TestCase(unittest.TestCase):
class LongLong_TestCase(unittest.TestCase):
def test_L(self):
from _testcapi import getargs_L
# L returns 'long long', and does range checking (LLONG_MIN ... LLONG_MAX)
# L returns 'long long', and does range checking (LLONG_MIN
# ... LLONG_MAX)
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
category=DeprecationWarning,
message=".*integer argument expected, got float",
module=__name__)
self.assertEqual(3, getargs_L(3.14))
with warnings.catch_warnings():
warnings.filterwarnings(
"error",
category=DeprecationWarning,
message=".*integer argument expected, got float",
module="unittest")
self.assertRaises(DeprecationWarning, getargs_L, 3.14)
self.assertRaises(TypeError, getargs_L, "Hello")
self.assertEqual(3, getargs_L(3.14))
self.assertEqual(99, getargs_L(Long()))
self.assertEqual(99, getargs_L(Int()))

View file

@ -502,11 +502,9 @@ class URandomTests (unittest.TestCase):
self.assertEqual(len(os.urandom(100)), 100)
self.assertEqual(len(os.urandom(1000)), 1000)
# see http://bugs.python.org/issue3708
with test_support.check_warnings():
# silence deprecation warnings about float arguments
self.assertEqual(len(os.urandom(0.9)), 0)
self.assertEqual(len(os.urandom(1.1)), 1)
self.assertEqual(len(os.urandom(2.0)), 2)
self.assertRaises(TypeError, os.urandom, 0.9)
self.assertRaises(TypeError, os.urandom, 1.1)
self.assertRaises(TypeError, os.urandom, 2.0)
except NotImplementedError:
pass

View file

@ -81,7 +81,7 @@ class XrangeTest(unittest.TestCase):
self.assertRaises(TypeError, xrange, 1, 2, 3, 4)
self.assertRaises(ValueError, xrange, 1, 2, 0)
self.assertRaises(OverflowError, xrange, 1e100, 1e101, 1e101)
self.assertRaises(OverflowError, xrange, 10**100, 10**101, 10**101)
self.assertRaises(TypeError, xrange, 0, "spam")
self.assertRaises(TypeError, xrange, 0, 42, "spam")

View file

@ -12,6 +12,14 @@ What's New in Python 2.7 alpha 2?
Core and Builtins
-----------------
- Issue #5080: A number of functions and methods previously produced a
DeprecationWarning when passed a float argument where an integer was
expected. These functions and methods now raise TypeError instead.
The majority of the effects of this change are in the extension
modules, but some core functions and methods are affected: notably
the 'chr', 'range' and 'xrange' builtins, and many unicode/str
methods.
- Issue #7604: Deleting an unset slotted attribute did not raise an
AttributeError.
@ -88,6 +96,14 @@ Library
C-API
-----
- Issue #5080: The argument parsing functions PyArg_ParseTuple,
PyArg_ParseTupleAndKeywords, PyArg_VaParse,
PyArg_VaParseTupleAndKeywords and PyArg_Parse no longer accept float
arguments for integer format codes (other than 'L'): previously an
attempt to pass a float resulted in a DeprecationWarning; now it
gives a TypeError. For the 'L' format code (which previously had no
warning) there is now a DeprecationWarning.
- Issue #7033: function ``PyErr_NewExceptionWithDoc()`` added.
Build

View file

@ -526,7 +526,7 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize)
/* explicitly check for float arguments when integers are expected. For now
* signal a warning. Returns true if an exception was raised. */
static int
float_argument_error(PyObject *arg)
float_argument_warning(PyObject *arg)
{
if (PyFloat_Check(arg) &&
PyErr_Warn(PyExc_DeprecationWarning,
@ -536,6 +536,20 @@ float_argument_error(PyObject *arg)
return 0;
}
/* explicitly check for float arguments when integers are expected. Raises
TypeError and returns true for float arguments. */
static int
float_argument_error(PyObject *arg)
{
if (PyFloat_Check(arg)) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float");
return 1;
}
else
return 0;
}
/* Convert a non-tuple argument. Return NULL if conversion went OK,
or a string with a message describing the failure. The message is
formatted as "must be <desired type>, not <actual type>".
@ -719,7 +733,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
#ifdef HAVE_LONG_LONG
case 'L': {/* PY_LONG_LONG */
PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * );
PY_LONG_LONG ival = PyLong_AsLongLong( arg );
PY_LONG_LONG ival;
if (float_argument_warning(arg))
return converterr("long<L>", arg, msgbuf, bufsize);
ival = PyLong_AsLongLong(arg);
if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) {
return converterr("long<L>", arg, msgbuf, bufsize);
} else {