GeezerVison is showing github.com — `~bool` deprecation not reported for literals · Issue #134280 · python/cpython
~bool deprecation not reported for literals #134280
Labels 3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DescriptionBug report
Bug description:
Related to: #103487
# literal.py
print(~False)
print(~True)
# var.py
a = True
print(~a)
b = False
print(~b)
A DeprecationWarning is reported for var.py, but not for literal.py.
$ python -c 'import sys; print(sys.version)'
3.15.0a0 (heads/main:42d03f3, May 19 2025, 23:32:01) [GCC 15.1.1 20250425 (Red Hat 15.1.1-1)]
$ python literal.py
-1
-2
$ python var.py
/tmp/scratch/var.py:2: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
print(~a)
-2
/tmp/scratch/var.py:5: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
print(~b)
-1
What's interesting is that there's a test for this:
|
with self.assertWarns(DeprecationWarning): |
|
# also check that the warning is issued in case of constant |
|
# folding at compile time |
|
self.assertEqual(eval("~False"), -1) |
and the DeprecationWarning is raised if eval("~True") is used instead of just ~True
$ python -c 'print(~True)'
-2
$ python -c 'print(eval("~True"))'
<string>:1: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2
CPython versions tested on:
CPython main branch, 3.13
Operating systems tested on:
Linux
Linked PRs
ActivityStanFromIreland commented on May 19, 2025 It seems to warn for me on 3.15 and 3.14:
$ python3.15 -c 'print(~True)'
<sys>:0: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2
This is 3.13 only. decorator-factory commented on May 19, 2025 ContributorAuthor More actions @StanFromIreland I ran it in a container (https://hub.docker.com/_/python/) on 3.14 for reproducibility:
$ podman run -ti --rm python:3.14.0b1-slim bash
root@a9edb8be24cb:/# python -c 'print(~True)'
-2
root@a9edb8be24cb:/# python -c 'print(eval("~True"))'
<string>:1: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2
root@a9edb8be24cb:/# python
Python 3.14.0b1 (main, May 9 2025, 23:49:24) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ~True
-2
>>> ~False
-1
>>>
On 3.15 in debug mode, I do get a warning:
$ ./configure --with-pydebug
...
$ make -j 12
...
$ ./python -c 'print(~True)'
<sys>:0: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
-2
$ ./python
Python 3.15.0a0 (heads/main:42d03f3, May 20 2025, 00:35:04) [GCC 15.1.1 20250425 (Red Hat 15.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ~True
/home/df/clones/cpython/Lib/codeop.py:117: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
codeob = compile(source, filename, symbol, flags, True)
-2
>>>
EDIT: seems like the warning is displayed in 3.13 and 3.14 if the -X dev flag is enabled AA-Turner commented on May 20, 2025 timhoffm commented on May 20, 2025 serhiy-storchaka commented on May 31, 2025 This works as intended. By default, DeprecationWarning is only reported for the __main__ module in the Python development mode or in the debug build.
Run Python with -W always or -X dev to see them. decorator-factory commented on May 31, 2025 ContributorAuthor More actions So in this case, the operation is considered to be in the __main__ module
if __name__ == "__main__":
a = True
print(~a) # prints -2, with DeprecationWarning
but here it's considered to be outside of __main__?
if __name__ == "__main__":
print(~True) # prints -2, no DeprecationWarning
(from the docs (https://docs.python.org/3/library/exceptions.html#DeprecationWarning) and PEP 565 I'm assuming that you meant that deprecation warnings are only active in __main__ by default
default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning
) serhiy-storchaka commented on May 31, 2025 Well, this is obviously related to the fact that ~True is calculated at the compile time.
If warnings are ignored in the constant folding, this is a bug. serhiy-storchaka commented on May 31, 2025 #134982 disables constant folding for ~bool. This moves the deprecation warning from compile time to runtime.
Ideally, we could also emit a SyntaxWarning at compile time, like we do for ()(), but this is rather an additional feature with low benefit/cost ratio.
We narrowly avoided a bullet with not NotImplemented. Reacted by decorator-factory and Tim Hoffmann
MetadataMetadata3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DevelopmentNo branches or pull requestsIssue actions
|