Issue19995: issue deprecation warning for non-integer values to %c, %o, %x, %X

This commit is contained in:
Ethan Furman 2014-01-11 23:20:58 -08:00
parent 57bc1e21e7
commit f9bba9c67f
4 changed files with 49 additions and 9 deletions

View file

@ -142,6 +142,7 @@ class FormatTest(unittest.TestCase):
testformat("%#+027.23X", big, "+0X0001234567890ABCDEF12345") testformat("%#+027.23X", big, "+0X0001234567890ABCDEF12345")
# same, except no 0 flag # same, except no 0 flag
testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345") testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345")
testformat("%x", float(big), "123456_______________", 6)
big = 0o12345670123456701234567012345670 # 32 octal digits big = 0o12345670123456701234567012345670 # 32 octal digits
testformat("%o", big, "12345670123456701234567012345670") testformat("%o", big, "12345670123456701234567012345670")
testformat("%o", -big, "-12345670123456701234567012345670") testformat("%o", -big, "-12345670123456701234567012345670")
@ -181,6 +182,7 @@ class FormatTest(unittest.TestCase):
testformat("%034.33o", big, "0012345670123456701234567012345670") testformat("%034.33o", big, "0012345670123456701234567012345670")
# base marker shouldn't change that # base marker shouldn't change that
testformat("%0#34.33o", big, "0o012345670123456701234567012345670") testformat("%0#34.33o", big, "0o012345670123456701234567012345670")
testformat("%o", float(big), "123456__________________________", 6)
# Some small ints, in both Python int and flavors). # 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")
@ -191,6 +193,7 @@ class FormatTest(unittest.TestCase):
testformat("%#x", 1, "0x1") testformat("%#x", 1, "0x1")
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", 1, "0o1") testformat("%#o", 1, "0o1")
testformat("%#o", 0, "0o0") testformat("%#o", 0, "0o0")
@ -207,10 +210,12 @@ class FormatTest(unittest.TestCase):
testformat("%x", -0x42, "-42") testformat("%x", -0x42, "-42")
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", 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("%r", "\u0378", "'\\u0378'") # non printable
testformat("%a", "\u0378", "'\\u0378'") # non printable testformat("%a", "\u0378", "'\\u0378'") # non printable
testformat("%r", "\u0374", "'\u0374'") # printable testformat("%r", "\u0374", "'\u0374'") # printable

View file

@ -1139,6 +1139,13 @@ class UnicodeTest(string_tests.CommonTest,
self.value = float(value) self.value = float(value)
def __int__(self): def __int__(self):
return int(self.value) return int(self.value)
def check_depr(modifier, value):
with support.check_warnings(
("", DeprecationWarning),
quiet=False,
):
warnings.simplefilter('always')
modifier % value
pi = PsuedoFloat(3.1415) pi = PsuedoFloat(3.1415)
letter_m = PsuedoInt(109) letter_m = PsuedoInt(109)
self.assertEqual('%x' % 42, '2a') self.assertEqual('%x' % 42, '2a')
@ -1149,11 +1156,14 @@ class UnicodeTest(string_tests.CommonTest,
self.assertEqual('%X' % letter_m, '6D') self.assertEqual('%X' % letter_m, '6D')
self.assertEqual('%o' % letter_m, '155') self.assertEqual('%o' % letter_m, '155')
self.assertEqual('%c' % letter_m, 'm') self.assertEqual('%c' % letter_m, 'm')
self.assertRaises(TypeError, '%x'.__mod__, pi) for mod, value in (
self.assertRaises(TypeError, '%x'.__mod__, 3.14) ('%x', pi),
self.assertRaises(TypeError, '%X'.__mod__, 2.11) ('%x', 3.14),
self.assertRaises(TypeError, '%o'.__mod__, 1.79) ('%X', 2.11),
self.assertRaises(TypeError, '%c'.__mod__, pi) ('%o', 1.79),
('%c', pi),
):
check_depr(mod, value)
def test_formatting_with_enum(self): def test_formatting_with_enum(self):
# issue18780 # issue18780

View file

@ -117,8 +117,8 @@ Core and Builtins
- Issue #19969: PyBytes_FromFormatV() now raises an OverflowError if "%c" - Issue #19969: PyBytes_FromFormatV() now raises an OverflowError if "%c"
argument is not in range [0; 255]. argument is not in range [0; 255].
- Issue #19995: %c, %o, %x, and %X now raise TypeError on non-integer input; - Issue #19995: %c, %o, %x, and %X now issue a DeprecationWarning on non-integer
reworded docs to clarify that an integer type should define both __int__ input; reworded docs to clarify that an integer type should define both __int__
and __index__. and __index__.
- Issue #19787: PyThread_set_key_value() now always set the value. In Python - Issue #19787: PyThread_set_key_value() now always set the value. In Python

View file

@ -14004,12 +14004,25 @@ mainformatlong(PyObject *v,
if (!PyNumber_Check(v)) if (!PyNumber_Check(v))
goto wrongtype; goto wrongtype;
/* make sure number is a type of integer */
/* if not, issue depracation warning for now */
if (!PyLong_Check(v)) { if (!PyLong_Check(v)) {
if (type == 'o' || type == 'x' || type == 'X') { if (type == 'o' || type == 'x' || type == 'X') {
iobj = PyNumber_Index(v); iobj = PyNumber_Index(v);
if (iobj == NULL) { if (iobj == NULL) {
PyErr_Clear();
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"automatic int conversions have been deprecated",
1)) {
return -1; return -1;
} }
iobj = PyNumber_Long(v);
if (iobj == NULL ) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
goto wrongtype;
return -1;
}
}
} }
else { else {
iobj = PyNumber_Long(v); iobj = PyNumber_Long(v);
@ -14090,10 +14103,22 @@ formatchar(PyObject *v)
PyObject *iobj; PyObject *iobj;
long x; long x;
/* make sure number is a type of integer */ /* make sure number is a type of integer */
/* if not, issue depracation warning for now */
if (!PyLong_Check(v)) { if (!PyLong_Check(v)) {
iobj = PyNumber_Index(v); iobj = PyNumber_Index(v);
if (iobj == NULL) { if (iobj == NULL) {
PyErr_Clear();
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"automatic int conversions have been deprecated",
1)) {
return -1;
}
iobj = PyNumber_Long(v);
if (iobj == NULL ) {
if (PyErr_ExceptionMatches(PyExc_TypeError))
goto onError; goto onError;
return -1;
}
} }
v = iobj; v = iobj;
Py_DECREF(iobj); Py_DECREF(iobj);