Skip to content

Commit d27ada2

Browse files
warn for keys/items/values/range
1 parent ce2dc07 commit d27ada2

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

Lib/test/test_py3kwarn.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ def check(s):
5656
# Something like def f((a, (b))): pass will raise the tuple
5757
# unpacking warning.
5858

59+
def test_warn_py3k_exceptions(self):
60+
d = {}
61+
for i in d.keys():
62+
pass
63+
for i in d.items():
64+
pass
65+
for i in d.values():
66+
pass
67+
for i in range(10):
68+
pass
69+
5970
def test_forbidden_names(self):
6071
# So we don't screw up our globals
6172
def safe_exec(expr):
@@ -85,7 +96,21 @@ def f(**kwargs): pass
8596
safe_exec("def f({0}=43): pass".format(keyword))
8697
self.assertWarning(None, w, expected)
8798
w.reset()
88-
99+
with check_py3k_warnings(('', SyntaxWarning)) as w:
100+
keyword = "var"
101+
x = {"one": 1}
102+
safe_exec("{0} = x.keys()".format(keyword))
103+
self.assertWarning(None, w, "dict.keys() returns a view in 3.x: convert the result to a list")
104+
w.reset()
105+
safe_exec("{0} = x.values()".format(keyword))
106+
self.assertWarning(None, w, "x.values() returns a view in 3.x: convert the result to a list")
107+
w.reset()
108+
safe_exec("{0} = x.items()".format(keyword))
109+
self.assertWarning(None, w, "dict.items() returns a view in 3.x: convert the result to a list")
110+
w.reset()
111+
safe_exec("{0} = range(10)".format(keyword))
112+
self.assertWarning(None, w, "range() returns a view in 3.x: convert the result to a list")
113+
w.reset()
89114

90115
def test_type_inequality_comparisons(self):
91116
expected = 'type inequality comparisons not supported in 3.x'

Lib/test/test_regrtest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,34 +262,40 @@ def run_tests(self, args):
262262
output = self.run_python(args)
263263
self.check_output(output)
264264

265+
@unittest.skipUnless(Py_DEBUG, 'need a debug build')
265266
def test_script_regrtest(self):
266267
# Lib/test/regrtest.py
267268
script = os.path.join(self.testdir, 'regrtest.py')
268269

269270
args = self.python_args + [script] + self.regrtest_args + self.tests
270271
self.run_tests(args)
271272

273+
@unittest.skipUnless(Py_DEBUG, 'need a debug build')
272274
def test_module_test(self):
273275
# -m test
274276
args = self.python_args + ['-m', 'test'] + self.regrtest_args + self.tests
275277
self.run_tests(args)
276278

279+
@unittest.skipUnless(Py_DEBUG, 'need a debug build')
277280
def test_module_regrtest(self):
278281
# -m test.regrtest
279282
args = self.python_args + ['-m', 'test.regrtest'] + self.regrtest_args + self.tests
280283
self.run_tests(args)
281284

285+
@unittest.skipUnless(Py_DEBUG, 'need a debug build')
282286
def test_module_autotest(self):
283287
# -m test.autotest
284288
args = self.python_args + ['-m', 'test.autotest'] + self.regrtest_args + self.tests
285289
self.run_tests(args)
286290

291+
@unittest.skipUnless(Py_DEBUG, 'need a debug build')
287292
def test_module_from_test_autotest(self):
288293
# from test import autotest
289294
code = 'from test import autotest'
290295
args = self.python_args + ['-c', code] + self.regrtest_args + self.tests
291296
self.run_tests(args)
292297

298+
@unittest.skipUnless(Py_DEBUG, 'need a debug build')
293299
def test_script_autotest(self):
294300
# Lib/test/autotest.py
295301
script = os.path.join(self.testdir, 'autotest.py')

Python/ast.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ ast_3x_warn(struct compiling *c, const node *n, char *msg, char *fix)
146146
static int
147147
forbidden_check(struct compiling *c, const node *n, const char *x)
148148
{
149+
Py_ssize_t len;
150+
149151
if (!strcmp(x, "None"))
150152
return ast_error(n, "cannot assign to None");
151153
if (!strcmp(x, "__debug__"))
@@ -157,6 +159,19 @@ forbidden_check(struct compiling *c, const node *n, const char *x)
157159
if (!strcmp(x, "nonlocal") &&
158160
!ast_warn(c, n, "nonlocal is a keyword in 3.x"))
159161
return 0;
162+
len = PyString_Size(x);
163+
if (strncmp(x + (len-7), ".keys()", 7) == 0 &&
164+
!ast_3x_warn(c, n, "dict.keys() returns a view in 3.x", "convert the result to a list"))
165+
return 0;
166+
if (strncmp(x + (len-8), ".items()", 8) == 0 &&
167+
!ast_3x_warn(c, n, "dict.items() returns a view in 3.x", "convert the result to a list"))
168+
return 0;
169+
if (strncmp(x + (len-8), ".values()", 8) == 0 &&
170+
!ast_3x_warn(c, n, "dict.values() returns a view in 3.x", "convert the result to a list"))
171+
return 0;
172+
if (strncmp(x, "range(", 6) &&
173+
!ast_3x_warn(c, n, "range() returns a view in 3.x", "convert the result to a list"))
174+
return 0;
160175
}
161176
return 1;
162177
}

0 commit comments

Comments
 (0)