From 58d23e68068996c76cac78887ec67dee68cdbc72 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 Mar 2017 00:53:39 +0200 Subject: [PATCH] bpo-29695: Deprecated using bad named keyword arguments in builtings: (#486) int(), bool(), float(), list() and tuple(). Specify the value as a positional argument instead. --- Doc/whatsnew/3.7.rst | 5 +++++ Lib/test/test_bool.py | 4 ++++ Lib/test/test_float.py | 4 ++++ Lib/test/test_int.py | 6 ++++-- Lib/test/test_list.py | 7 +++++++ Lib/test/test_tuple.py | 7 +++++++ Misc/NEWS | 4 ++++ Objects/boolobject.c | 6 ++++++ Objects/floatobject.c | 6 ++++++ Objects/listobject.c | 6 ++++++ Objects/longobject.c | 6 ++++++ Objects/tupleobject.c | 6 ++++++ 12 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 1f5aa79c87a1..5c5ca147e3ad 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -169,6 +169,11 @@ Deprecated both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`. (Contributed by Matthias Bussonnier in :issue:`29576`) +- Using *x* as a keyword argument in :func:`int`, :func:`bool` and + :func:`float` and using *sequence* as a keyword argument in :func:`list` + and :func:`tuple` are deprecated. Specify the value as a positional argument + instead. (Contributed by Serhiy Storchaka in :issue:`29695`.) + Removed ======= diff --git a/Lib/test/test_bool.py b/Lib/test/test_bool.py index 9f8f0e122c8d..1e6ec1983758 100644 --- a/Lib/test/test_bool.py +++ b/Lib/test/test_bool.py @@ -170,6 +170,10 @@ def test_convert(self): self.assertIs(bool(""), False) self.assertIs(bool(), False) + def test_keyword_args(self): + with self.assertWarns(DeprecationWarning): + self.assertIs(bool(x=10), True) + def test_format(self): self.assertEqual("%d" % False, "0") self.assertEqual("%d" % True, "1") diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index ac8473db503b..91e3b7ab49d4 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -208,6 +208,10 @@ def __float__(self): with self.assertWarns(DeprecationWarning): self.assertIs(type(FloatSubclass(F())), FloatSubclass) + def test_keyword_args(self): + with self.assertWarns(DeprecationWarning): + self.assertEqual(float(x='3.14'), 3.14) + def test_is_integer(self): self.assertFalse((1.1).is_integer()) self.assertTrue((1.).is_integer()) diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py index 14bbd6192a05..db969672e492 100644 --- a/Lib/test/test_int.py +++ b/Lib/test/test_int.py @@ -246,9 +246,11 @@ def test_no_args(self): def test_keyword_args(self): # Test invoking int() using keyword arguments. - self.assertEqual(int(x=1.2), 1) + with self.assertWarns(DeprecationWarning): + self.assertEqual(int(x=1.2), 1) self.assertEqual(int('100', base=2), 4) - self.assertEqual(int(x='100', base=2), 4) + with self.assertWarns(DeprecationWarning): + self.assertEqual(int(x='100', base=2), 4) self.assertRaises(TypeError, int, base=10) self.assertRaises(TypeError, int, base=0) diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py index aee62dca1c41..48c36913c0c0 100644 --- a/Lib/test/test_list.py +++ b/Lib/test/test_list.py @@ -16,6 +16,8 @@ def test_basic(self): self.assertEqual(list((0, 1, 2, 3)), [0, 1, 2, 3]) self.assertEqual(list(''), []) self.assertEqual(list('spam'), ['s', 'p', 'a', 'm']) + self.assertEqual(list(x for x in range(10) if x % 2), + [1, 3, 5, 7, 9]) if sys.maxsize == 0x7fffffff: # This test can currently only work on 32-bit machines. @@ -39,6 +41,11 @@ def test_basic(self): x.extend(-y for y in x) self.assertEqual(x, []) + def test_keyword_args(self): + with self.assertWarns(DeprecationWarning): + self.assertEqual(list(sequence=(x for x in range(10) if x % 2)), + [1, 3, 5, 7, 9]) + def test_truth(self): super().test_truth() self.assertTrue(not []) diff --git a/Lib/test/test_tuple.py b/Lib/test/test_tuple.py index 5d1fcf68a880..d3663acfd49c 100644 --- a/Lib/test/test_tuple.py +++ b/Lib/test/test_tuple.py @@ -23,6 +23,13 @@ def test_constructors(self): self.assertEqual(tuple([0, 1, 2, 3]), (0, 1, 2, 3)) self.assertEqual(tuple(''), ()) self.assertEqual(tuple('spam'), ('s', 'p', 'a', 'm')) + self.assertEqual(tuple(x for x in range(10) if x % 2), + (1, 3, 5, 7, 9)) + + def test_keyword_args(self): + with self.assertWarns(DeprecationWarning): + self.assertEqual(tuple(sequence=(x for x in range(10) if x % 2)), + (1, 3, 5, 7, 9)) def test_truth(self): super().test_truth() diff --git a/Misc/NEWS b/Misc/NEWS index 3ff3cb5b8b65..d542cf1032e5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ What's New in Python 3.7.0 alpha 1? Core and Builtins ----------------- +- bpo-29695: Using "x" as a keyword argument in int(), bool() and float() and + using "sequence" as a keyword argument in list() and tuple() are deprecated. + Specify the value as a positional argument instead. + - bpo-28893: Set correct __cause__ for errors about invalid awaitables returned from __aiter__ and __anext__. diff --git a/Objects/boolobject.c b/Objects/boolobject.c index 31510bb07d56..b54b0525dfc8 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -48,6 +48,12 @@ bool_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:bool", kwlist, &x)) return NULL; + if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "Using 'x' as a keyword argument is deprecated; " + "specify the value as a positional argument instead") < 0) + return NULL; + } ok = PyObject_IsTrue(x); if (ok < 0) return NULL; diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 17a55dd114d4..3a881c3358b4 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -1569,6 +1569,12 @@ float_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return float_subtype_new(type, args, kwds); /* Wimp out */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x)) return NULL; + if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "Using 'x' as a keyword argument is deprecated; " + "specify the value as a positional argument instead") < 0) + return NULL; + } /* If it's a string, but not a string subclass, use PyFloat_FromString. */ if (PyUnicode_CheckExact(x)) diff --git a/Objects/listobject.c b/Objects/listobject.c index edd4a15068ad..59f68819d490 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2297,6 +2297,12 @@ list_init(PyListObject *self, PyObject *args, PyObject *kw) if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg)) return -1; + if (arg != NULL && PyTuple_GET_SIZE(args) == 0) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "Using 'sequence' as a keyword argument is deprecated; " + "specify the value as a positional argument instead") < 0) + return -1; + } /* Verify list invariants established by PyType_GenericAlloc() */ assert(0 <= Py_SIZE(self)); diff --git a/Objects/longobject.c b/Objects/longobject.c index 0bf6cee6c172..6c4760207752 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4811,6 +4811,12 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } return PyLong_FromLong(0L); } + if (PyTuple_GET_SIZE(args) == 0) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "Using 'x' as a keyword argument is deprecated; " + "specify the value as a positional argument instead") < 0) + return NULL; + } if (obase == NULL) return PyNumber_Long(x); diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 5bcadeb9f645..c2696c7dfb79 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -654,6 +654,12 @@ tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return tuple_subtype_new(type, args, kwds); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg)) return NULL; + if (arg != NULL && PyTuple_GET_SIZE(args) == 0) { + if (PyErr_Warn(PyExc_DeprecationWarning, + "Using 'sequence' as a keyword argument is deprecated; " + "specify the value as a positional argument instead") < 0) + return NULL; + } if (arg == NULL) return PyTuple_New(0);