Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SyntaxWarning for 'is <literal>' #87317

Closed
garylitvin mannequin opened this issue Feb 7, 2021 · 10 comments
Closed

SyntaxWarning for 'is <literal>' #87317

garylitvin mannequin opened this issue Feb 7, 2021 · 10 comments
Assignees
Labels
3.8 only security fixes 3.9 only security fixes 3.10 only security fixes topic-IDLE type-bug An unexpected behavior, bug, or error

Comments

@garylitvin
Copy link
Mannequin

garylitvin mannequin commented Feb 7, 2021

BPO 43151
Nosy @rhettinger, @terryjreedy, @stevendaprano, @sweeneyde
Files
  • idle_vs_console.jpg
  • idle_stderr.jpg
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/terryjreedy'
    closed_at = <Date 2021-02-08.08:20:06.915>
    created_at = <Date 2021-02-07.04:40:13.916>
    labels = ['type-bug', '3.8', '3.9', '3.10', 'expert-IDLE', 'invalid']
    title = "SyntaxWarning for 'is <literal>'"
    updated_at = <Date 2021-02-08.08:20:06.908>
    user = 'https://bugs.python.org/garylitvin'

    bugs.python.org fields:

    activity = <Date 2021-02-08.08:20:06.908>
    actor = 'terry.reedy'
    assignee = 'terry.reedy'
    closed = True
    closed_date = <Date 2021-02-08.08:20:06.915>
    closer = 'terry.reedy'
    components = ['IDLE']
    creation = <Date 2021-02-07.04:40:13.916>
    creator = 'garylitvin'
    dependencies = []
    files = ['49795', '49796']
    hgrepos = []
    issue_num = 43151
    keywords = []
    message_count = 10.0
    messages = ['386575', '386579', '386580', '386581', '386584', '386585', '386586', '386592', '386609', '386621']
    nosy_count = 5.0
    nosy_names = ['rhettinger', 'terry.reedy', 'steven.daprano', 'Dennis Sweeney', 'garylitvin']
    pr_nums = []
    priority = 'normal'
    resolution = 'not a bug'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue43151'
    versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']

    @garylitvin
    Copy link
    Mannequin Author

    garylitvin mannequin commented Feb 7, 2021

    >>> x = 'a'
    >>> x is 'a'
    True
    >>> if x is 'a':
            print(x)

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

    How come?

    @garylitvin garylitvin mannequin added 3.8 only security fixes 3.9 only security fixes labels Feb 7, 2021
    @sweeneyde
    Copy link
    Member

    This was a very intentional change from the commit 3bcbedc

    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

    @rhettinger
    Copy link
    Contributor

    As Dennis says, this is an intentional behavior and will help you avoid bugs.

    @garylitvin
    Copy link
    Mannequin Author

    garylitvin mannequin commented Feb 7, 2021

    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\>


    @stevendaprano
    Copy link
    Member

    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.

    @sweeneyde
    Copy link
    Member

    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.

    @sweeneyde
    Copy link
    Member

    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.

    @garylitvin
    Copy link
    Mannequin Author

    garylitvin mannequin commented Feb 7, 2021

    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\>


    @stevendaprano
    Copy link
    Member

    Terry, this may be an IDLE issue, can you confirm whether or not the difference in behaviour is intentional?

    @terryjreedy
    Copy link
    Member

    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. bpo-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 bpo-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.

    @terryjreedy terryjreedy added 3.10 only security fixes topic-IDLE labels Feb 8, 2021
    @terryjreedy terryjreedy changed the title is with literals in 3.8 release SyntaxWarning for 'is <literal>' Feb 8, 2021
    @terryjreedy terryjreedy self-assigned this Feb 8, 2021
    @terryjreedy terryjreedy added type-bug An unexpected behavior, bug, or error topic-IDLE labels Feb 8, 2021
    @terryjreedy terryjreedy changed the title is with literals in 3.8 release SyntaxWarning for 'is <literal>' Feb 8, 2021
    @terryjreedy terryjreedy self-assigned this Feb 8, 2021
    @terryjreedy terryjreedy added the type-bug An unexpected behavior, bug, or error label Feb 8, 2021
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.8 only security fixes 3.9 only security fixes 3.10 only security fixes topic-IDLE type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    4 participants