Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 50b46c5

Browse filesBrowse files
Merge python#21
21: warn for keys/items/values/range r=ltratt a=nanjekyejoannah I think I was over-thinking the solution with flags at synbol table generation. I found a simple check at the AST that checks correctness of values assigned to wanr for things like "True" and other keywords and used this check to warn for these calls. This warns for `keys/values/items/range`: Accurate when the statement is in an assignment: `x = range(20)` ` y = d.keys()` Co-authored-by: Joannah Nanjekye <jnanjeky@unb.ca>
2 parents 94c3759 + d27ada2 commit 50b46c5
Copy full SHA for 50b46c5

File tree

Expand file treeCollapse file tree

3 files changed

+47
-1
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+47
-1
lines changed

‎Lib/test/test_py3kwarn.py

Copy file name to clipboardExpand all lines: Lib/test/test_py3kwarn.py
+26-1Lines 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

Copy file name to clipboardExpand all lines: Lib/test/test_regrtest.py
+6Lines 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

Copy file name to clipboardExpand all lines: Python/ast.c
+15Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.