PyCQA / flake8-bugbear

A plugin for Flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle.
MIT License
1.06k stars 104 forks source link

B907 crashes when bugbear is run on Python 3.12 #393

Closed AlexWaygood closed 1 year ago

AlexWaygood commented 1 year ago

Minimal repro: using Python 3.12 (with flake8-bugbear installed), run flake8 on a file containing just this:

f'"{var:}"'
Resulting stack trace: ```pytb Traceback (most recent call last): File "", line 198, in _run_module_as_main File "", line 88, in _run_code File "C:\Users\alexw\coding\slow-cpython-venv\Scripts\flake8.exe\__main__.py", line 7, in File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\main\cli.py", line 23, in main app.run(argv) File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\main\application.py", line 198, in run self._run(argv) File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\main\application.py", line 187, in _run self.run_checks() File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\main\application.py", line 103, in run_checks self.file_checker_manager.run() File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\checker.py", line 236, in run self.run_serial() File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\checker.py", line 219, in run_serial ).run_checks() ^^^^^^^^^^^^ File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8_noqa\noqa_filter.py", line 189, in run_checks result = super().run_checks(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\checker.py", line 524, in run_checks self.run_ast_checks() File "C:\Users\alexw\coding\slow-cpython-venv\Lib\site-packages\flake8\checker.py", line 426, in run_ast_checks for (line_number, offset, text, _) in runner: File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 70, in run visitor.visit(self.tree) File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 348, in visit super().visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 407, in visit return visitor(node) ^^^^^^^^^^^^^ File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 432, in visit_Module self.generic_visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 415, in generic_visit self.visit(item) File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 348, in visit super().visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 407, in visit return visitor(node) ^^^^^^^^^^^^^ File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 417, in generic_visit self.visit(value) File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 348, in visit super().visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 407, in visit return visitor(node) ^^^^^^^^^^^^^ File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 521, in visit_JoinedStr self.generic_visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 415, in generic_visit self.visit(item) File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 348, in visit super().visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 407, in visit return visitor(node) ^^^^^^^^^^^^^ File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 417, in generic_visit self.visit(value) File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 348, in visit super().visit(node) File "C:\Users\alexw\coding\cpython\Lib\ast.py", line 407, in visit return visitor(node) ^^^^^^^^^^^^^ File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 520, in visit_JoinedStr self.check_for_b907(node) File "C:\Users\alexw\coding\flake8-bugbear\bugbear.py", line 1273, in check_for_b907 and value.value[-1] in quote_marks ~~~~~~~~~~~^^^^ IndexError: string index out of range ```

This is because this snippet parses differently on Python 3.12 (presumably due to PEP 701).

On Python 3.11: ```pycon >>> import ast >>> print(ast.dump(ast.parse("""f'"{var:}"'"""), indent=2)) Module( body=[ Expr( value=JoinedStr( values=[ Constant(value='"'), FormattedValue( value=Name(id='var', ctx=Load()), conversion=-1, format_spec=JoinedStr(values=[])), Constant(value='"')]))], type_ignores=[]) ```
On Python 3.12: ```pycon >>> import ast >>> print(ast.dump(ast.parse("""f'"{var:}"'"""), indent=2)) Module( body=[ Expr( value=JoinedStr( values=[ Constant(value='"'), FormattedValue( value=Name(id='var', ctx=Load()), conversion=-1, format_spec=JoinedStr( values=[ Constant(value='')])), Constant(value='"')]))], type_ignores=[]) ```

As a result of this, BugbearTestCase.test_b907 and BugbearTestCase.test_b907_format_specifier_permutations both crash on Python 3.12.

(N.B. I had to comment out the test that uses hypothesmith (and the import of hypothesmith) to get the tests to run on Python 3.12 -- seems like hypothesmith can't be installed on Python 3.12 yet.)