classification
Title: SyntaxWarning for "assertion is always true, perhaps remove parentheses?" does not work with constants
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.10, Python 3.9, Python 3.8, Python 3.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Mark.Shannon, darke, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2021-03-15 07:31 by darke, last changed 2021-07-28 22:58 by iritkatriel. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 24867 merged darke, 2021-03-15 07:48
Messages (5)
msg388711 - (view) Author: Greg Darke (darke) * Date: 2021-03-15 07:31
The following block of code does not produce a SyntaxWarning in python 3.7 and above (it does produce a warning in python 3.6 and below):

```
assert(False, 'msg')
```

If the tuple is not a constant (for example `(x, 'msg')`), then a warning is still produced.
msg388716 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-03-15 09:28
What is the use case for assert with a constant?
msg388718 - (view) Author: Greg Darke (darke) * Date: 2021-03-15 09:44
I would argue that there is none (especially if it is tuple/something that is always true) -- thus why I would assume that Python would provide a warning.

This bug comes from a discussion I was having with someone earlier today where they mentioned that it would be nice if the linter complained about the following::

  assert 'not reachable'

That code is incorrect (the assertion will never fire, due to the string evaluating to True). We remembered that python did complain about tuples, and tried to see what the warning looked like using a trivial example::

  assert(False, 'msg')

We noticed that this code did not produce a warning on python3.8, but did produce a warning on python2.7.

After much digging we found that the following did work on python3.8::

  assert(False, str())

This allowed us to deduce that something special was happening with constants (well, it also required us to look at the disassembly of the ops codes for the above two statements).

Going back to your original question, I have used `assert False` in code to "test" if a piece of code was being reached. I have also used it for things similar to the piece of code that started all of this::

  if some_expression:
    # ...
  elif some_other_expression:
    #...
  else:
    assert False, 'This code is unreachable'
msg388723 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-03-15 10:01
In such case I prefer to write

    assert not 'reachable'

It is shorter than writing False.

If I want to keep an exception even with -O, I write

    raise AssertionError
msg388835 - (view) Author: Mark Shannon (Mark.Shannon) * (Python committer) Date: 2021-03-16 11:14
New changeset a8ef4572a6b28bcfc0b10b34fa4204954b9dd761 by tsukasa-au in branch 'master':
bpo-43497: Emit SyntaxWarnings for assertions with tuple constants. (GH-24867)
https://github.com/python/cpython/commit/a8ef4572a6b28bcfc0b10b34fa4204954b9dd761
History
Date User Action Args
2021-07-28 22:58:30iritkatrielsetstatus: open -> closed
stage: patch review -> resolved
2021-03-17 00:13:41darkesetresolution: fixed
2021-03-16 11:14:48Mark.Shannonsetnosy: + Mark.Shannon
messages: + msg388835
2021-03-15 10:01:11serhiy.storchakasetmessages: + msg388723
2021-03-15 09:44:18darkesetmessages: + msg388718
2021-03-15 09:28:16serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg388716
2021-03-15 07:48:12darkesetkeywords: + patch
stage: patch review
pull_requests: + pull_request23629
2021-03-15 07:31:25darkecreate