Skip to content

Commit

Permalink
pythongh-103492: Clarify SyntaxWarning with literal comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
hauntsaninja committed Apr 13, 2023
1 parent d034590 commit 5247c04
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
20 changes: 13 additions & 7 deletions Lib/test/test_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ def check(test, error=False):
check(f"{num}spam", error=True)

with warnings.catch_warnings():
warnings.filterwarnings('ignore', '"is" with a literal',
warnings.filterwarnings('ignore', '"is" with int literal',
SyntaxWarning)
with self.assertWarnsRegex(SyntaxWarning,
r'invalid \w+ literal'):
Expand Down Expand Up @@ -1467,21 +1467,27 @@ def test_comparison(self):
if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in x is x is not x: pass

def test_comparison_is_literal(self):
def check(test, msg='"is" with a literal'):
def check(test, msg):
self.check_syntax_warning(test, msg)

check('x is 1')
check('x is "thing"')
check('1 is x')
check('x is y is 1')
check('x is not 1', '"is not" with a literal')
check('x is 1', '"is" with int literal')
check('x is "thing"', '"is" with str literal')
check('1 is x', '"is" with int literal')
check('x is y is 1', '"is" with int literal')
check('x is not 1', '"is not" with int literal')
check('x is not (1, 2)', '"is not" with tuple literal')
check('(1, 2) is not x', '"is not" with tuple literal')

with warnings.catch_warnings():
warnings.simplefilter('error', SyntaxWarning)
compile('x is None', '<testcase>', 'exec')
compile('x is False', '<testcase>', 'exec')
compile('x is True', '<testcase>', 'exec')
compile('x is ...', '<testcase>', 'exec')
compile('None is x', '<testcase>', 'exec')
compile('False is x', '<testcase>', 'exec')
compile('True is x', '<testcase>', 'exec')
compile('... is x', '<testcase>', 'exec')

def test_warn_missed_comma(self):
def check(test):
Expand Down
12 changes: 8 additions & 4 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,8 @@ check_is_arg(expr_ty e)
|| value == Py_Ellipsis);
}

static PyTypeObject * infer_type(expr_ty e);

/* Check operands of identity checks ("is" and "is not").
Emit a warning if any operand is a constant except named singletons.
*/
Expand All @@ -2356,13 +2358,15 @@ check_compare(struct compiler *c, expr_ty e)
n = asdl_seq_LEN(e->v.Compare.ops);
for (i = 0; i < n; i++) {
cmpop_ty op = (cmpop_ty)asdl_seq_GET(e->v.Compare.ops, i);
bool right = check_is_arg((expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
expr_ty right_expr = (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i);
bool right = check_is_arg(right_expr);
if (op == Is || op == IsNot) {
if (!right || !left) {
const char *msg = (op == Is)
? "\"is\" with a literal. Did you mean \"==\"?"
: "\"is not\" with a literal. Did you mean \"!=\"?";
return compiler_warn(c, LOC(e), msg);
? "\"is\" with %.200s literal. Did you mean \"==\"?"
: "\"is not\" with %.200s literal. Did you mean \"!=\"?";
expr_ty literal = !left ? e->v.Compare.left : right_expr;
return compiler_warn(c, LOC(e), msg, infer_type(literal)->tp_name);
}
}
left = right;
Expand Down

0 comments on commit 5247c04

Please sign in to comment.