This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: SyntaxWarning for 'is '
Type: behavior Stage: resolved
Components: IDLE Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: terry.reedy Nosy List: Dennis Sweeney, garylitvin, rhettinger, steven.daprano, terry.reedy
Priority: normal Keywords:

Created on 2021-02-07 04:40 by garylitvin, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
idle_vs_console.jpg Dennis Sweeney, 2021-02-07 08:37
idle_stderr.jpg Dennis Sweeney, 2021-02-07 08:41
Messages (10)
msg386575 - (view) Author: Gary Litvin (garylitvin) Date: 2021-02-07 04:40
>>> x = 'a'
>>> x is 'a'
True
>>> if x is 'a':
        print(x)

SyntaxError: "is" with a literal. Did you mean "=="?

How come?
msg386579 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2021-02-07 05:40
This was a very intentional change from the commit 3bcbedc9f1471d957a30a90f9d1251516b422416

It's not safe to check `x is y` when x and y are strings.
You should always use `x == y` for strings instead.
In CPython, if the names x and y both refer to the same underlying object, then `x is y` will return True.
In CPython, if the names x and y refer to two distinct string objects with equal values, then `x is y` will return False.
Which case happens is an implementation detail, and alternate Python implementations like PyPy could behave unexpectedly with such code.
As such, to prevent more incorrect code, this was changed to emit a SyntaxWarning in Python 3.8.

This is documented here:
https://docs.python.org/3/whatsnew/3.8.html#changes-in-python-behavior

In a python REPL, I believe SyntaxWarnings are by default promoted to SyntaxErrors. But when running a file with `python -Wa`, you just get the warning:

$ python -Wa ./a.py
.../a.py:2: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if x is 'a':
a
msg386580 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2021-02-07 05:49
As Dennis says, this is an intentional behavior and will help you avoid bugs.
msg386581 - (view) Author: Gary Litvin (garylitvin) Date: 2021-02-07 06:02
Thank you for your responses. I understand the difference between == 
and "is" and the intentional change in 3.8. My question is about what 
seems to be inconsistent treatment in x is 'a' and if a is 'a': ...

At 12:49 AM 2/7/2021, Raymond Hettinger wrote:

>Raymond Hettinger <raymond.hettinger@gmail.com> added the comment:
>
>As Dennis says, this is an intentional behavior and will help you avoid bugs.
>
>----------
>nosy: +rhettinger
>resolution:  -> not a bug
>stage:  -> resolved
>status: open -> closed
>
>_______________________________________
>Python tracker <report@bugs.python.org>
><https://bugs.python.org/issue43151>
>_______________________________________
msg386584 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2021-02-07 07:39
Gary, I cannot replicate that inconsistency in 3.9.0.


>>> x = "abc"
>>> x is "abc"
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> if x is "abc": pass
... 
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?


I don't believe that you should be getting a SyntaxError at all, and both cases should give the same warning. Can you double-check your code, and if you confirm that they give a different result or a SyntaxError, let us know here. Otherwise Raymond and Dennis are correct: this is working correctly.
msg386585 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2021-02-07 08:37
There may be reason to re-open this.

With Python 3.9.0, I see the inconsistent behavior that Gary describes only when using IDLE. So this is likely an IDLE issue.

I attached a screenshot of the difference.
msg386586 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2021-02-07 08:41
I think the strangeness is happening because sometimes, the warning is printed to stderr, while other times, IDLE's parser notices the "is <literal>" anti-pattern and raises a SyntaxError.

See the attached screenshot for the IDLE output versus the console output for a recent 3.10 build.
msg386592 - (view) Author: Gary Litvin (garylitvin) Date: 2021-02-07 14:41
I noticed it in IDLE 3.8. I installed 3.8 because it is a fairly 
recent release described as "stable." Thanks to everyone for considering this.

At 03:41 AM 2/7/2021, you wrote:

>Dennis Sweeney <sweeney.dennis650@gmail.com> added the comment:
>
>I think the strangeness is happening because sometimes, the warning 
>is printed to stderr, while other times, IDLE's parser notices the 
>"is <literal>" anti-pattern and raises a SyntaxError.
>
>See the attached screenshot for the IDLE output versus the console 
>output for a recent 3.10 build.
>
>----------
>Added file: https://bugs.python.org/file49796/idle_stderr.jpg
>
>_______________________________________
>Python tracker <report@bugs.python.org>
><https://bugs.python.org/issue43151>
>_______________________________________
msg386609 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2021-02-07 20:57
Terry, this may be an IDLE issue, can you confirm whether or not the difference in behaviour is intentional?
msg386621 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-02-08 08:20
I verified that there are two discrepancies in IDLE versus the standard REPL on Windows with 3.10.0a5.  The latter first (which does not converted warnings to errors).

Python 3.10.0a4+ (heads/master:0332e569c1, Feb  1 2021, 09:19:58) [MSC v.1900 64 bit (AMD64)] on win32

>>> x = 'a'
>>> x is 'a'
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> if x is 'a': print('executed')
...
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
executed

versus, with IDLE, 

>>> x = 'a'
>>> x is 'a'  # No warning, also executed.
True
>>> if x is 'a': pass  # Error instead of warning, hence not executed.
SyntaxError: "is" with a literal. Did you mean "=="?

There is no "IDLE parser" for interactive input.  IDLE's Shell uses a subclass of code.InteractiveInterpreter, which calls codeop.CommandCompiler.  The latter calls codeop._maybe_compile, which calls compile() 3 times for the source as is, with '\n' appended, and with '\n\n' appended.  #40807 fixed the issue of getting 3 warnings instead of 1.

For the comparison "x is 'a'", all three compiles emit SyntaxWarning before _maybe_compile returns a code object.  The last two warnings are suppressed.  IDLE not printing Shell input warnings it is the subject of #37824.

Compiling the if statement without a final \n raises
SyntaxError: unexpected EOF while parsing
Adding '\n' results in the warning (converted to error in _maybe_compile) and a code object.


I think there is a bug in the revised _maybe_compile but I need to add prints or breakpoints to properly understand it.  And have someone locate and explain the REPL C code. If I decide _maybe_compile should be patched, I will open a new issue.

---
PS Gary, when replying by email, please delete what you are responding to, except possibly for a line or two.  When posted on the web page below what you respond to, the full quote is redundant noise.

Also, questions like 'How come?' should better be asked on python-list (or other question-asking forums).  Discussion there can lead to specific issues here.
History
Date User Action Args
2022-04-11 14:59:41adminsetgithub: 87317
2021-02-08 08:20:06terry.reedysetstatus: open -> closed

type: behavior
assignee: terry.reedy
components: + IDLE
title: is with literals in 3.8 release -> SyntaxWarning for 'is <literal>'
messages: + msg386621
versions: + Python 3.10
resolution: not a bug
stage: resolved
2021-02-07 20:57:23steven.dapranosetstatus: closed -> open

nosy: + terry.reedy
messages: + msg386609

resolution: not a bug -> (no value)
stage: resolved -> (no value)
2021-02-07 14:41:48garylitvinsetmessages: + msg386592
2021-02-07 08:41:14Dennis Sweeneysetfiles: + idle_stderr.jpg

messages: + msg386586
2021-02-07 08:37:01Dennis Sweeneysetfiles: + idle_vs_console.jpg

messages: + msg386585
2021-02-07 07:39:36steven.dapranosetnosy: + steven.daprano
messages: + msg386584
2021-02-07 06:02:03garylitvinsetmessages: + msg386581
2021-02-07 05:49:33rhettingersetstatus: open -> closed

nosy: + rhettinger
messages: + msg386580

resolution: not a bug
stage: resolved
2021-02-07 05:40:26Dennis Sweeneysetnosy: + Dennis Sweeney
messages: + msg386579
2021-02-07 04:40:13garylitvincreate