flake8-sql icon indicating copy to clipboard operation
flake8-sql copied to clipboard

Support f-strings

Open KyleKing opened this issue 4 years ago • 3 comments

It looks like flake8-sql fails to parse queries built with f-strings (the same string with .format() works)

Below is a compact example tested with: python -m flake8 flake8_sql_check.py

columns = 'col1,col2'
view = 'View1'

# Works, catches Q440
query = 'select {columns} From [{view}]'.format(columns=columns, view=view)

# Throws "TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'"
# query = f'select {columns} From [{view}]'

Full traceback:

C:\Users\king.kyle\Developer\project>poetry run python -m flake8 flake8_sql_check.py
Traceback (most recent call last):
  File "c:\users\king.kyle\miniconda3\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\king.kyle\miniconda3\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\__main__.py", line 4, in <module>
    cli.main()
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\main\cli.py", line 22, in main 
    app.run(argv)
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\main\application.py", line 363, in run
    self._run(argv)
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\main\application.py", line 351, in _run
    self.run_checks()
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\main\application.py", line 264, in run_checks
    self.file_checker_manager.run()
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\checker.py", line 323, in run  
    self.run_serial()
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\checker.py", line 307, in run_serial
    checker.run_checks()
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\checker.py", line 589, in run_checks
    self.run_ast_checks()
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8\checker.py", line 494, in run_ast_checks
    for (line_number, offset, text, _) in runner:
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8_sql\linter.py", line 49, in run    initial_offset = _get_initial_offset(node, self.lines)
  File "C:\Users\king.kyle\Developer\project\.venv\lib\site-packages\flake8_sql\linter.py", line 178, in _get_initial_offset
    first_physical_line = physical_lines[query_end_lineno - len(logical_lines)]
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

I can possibly look into a PR later, but wanted to report the error since I've run into it a few times.

I just want to live dangerously:

Good old Bobby Tables

KyleKing avatar Apr 23 '21 15:04 KyleKing

Hahaha, I just went down a massive rabbit hole trying to figure this out, only to come out on the other side and realise there already was an issue on it :)

thomasaarholt avatar Aug 26 '21 10:08 thomasaarholt

I went back to revisit this issue, but I oddly can no longer replicate it 🤔

@thomasaarholt, can you share a snippet that fails for you? What Python version were you using?

KyleKing avatar Sep 04 '21 13:09 KyleKing

@KyleKing I am able to reproduce this error using Python 3.9.9, flake8 4.0.1 and flake8-sql 0.4.1 when running python -m flake8 flake8_sql_format_check.py on this file:

table_name = "mytable"
sql = f"SELECT id FROM {table_name} WHERE foo = 'bar'"

This gives the following traceback:

Traceback (most recent call last):
  File "/Users/brox/.pyenv/versions/3.9.9/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Users/brox/.pyenv/versions/3.9.9/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/__main__.py", line 4, in <module>
    cli.main()
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/main/cli.py", line 22, in main
    app.run(argv)
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/main/application.py", line 375, in run
    self._run(argv)
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/main/application.py", line 364, in _run
    self.run_checks()
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/main/application.py", line 271, in run_checks
    self.file_checker_manager.run()
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/checker.py", line 311, in run
    self.run_serial()
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/checker.py", line 295, in run_serial
    checker.run_checks()
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/checker.py", line 597, in run_checks
    self.run_ast_checks()
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8/checker.py", line 500, in run_ast_checks
    for (line_number, offset, text, _) in runner:
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8_sql/linter.py", line 49, in run
    initial_offset = _get_initial_offset(node, self.lines)
  File "/Users/brox/.pyenv/versions/sandbox/lib/python3.9/site-packages/flake8_sql/linter.py", line 178, in _get_initial_offset
    first_physical_line = physical_lines[query_end_lineno - len(logical_lines)]
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

brox avatar Jan 23 '22 13:01 brox