-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Summary
The fix for fast-api-unused-path-parameter (FAST003) can introduce a syntax error.
When the function’s first parameter uses *, FAST003 doesn’t add a comma before it. Example:
$ cat >fast003_1.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/things/{thing_id}")
async def read_thing(*query: str): ...
# EOF
$ ruff --isolated check fast003_1.py --select FAST003 --unsafe-fixes --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.Ditto for **. Example:
$ cat >fast003_2.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/things/{thing_id}")
async def read_thing(**query: str): ...
# EOF
$ ruff --isolated check fast003_2.py --select FAST003 --unsafe-fixes --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.When the parameter list ends with /, FAST003 puts the new parameter before it, introducing a syntax error. Example:
$ cat >fast003_3.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/queries/{thing_id}")
async def read_query(query: str, /): ...
# EOF
$ ruff --isolated check fast003_3.py --select FAST003 --unsafe-fixes --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.The fix introduces a syntax error when the path parameter name is __debug__. It detects the error but modifies the file anyway. The fix should be suppressed in this case, as it already is for path parameters that are Python keywords. Example:
$ cat >fast003_4.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/queries/{__debug__}")
async def read_query(query: str): ...
# EOF
$ ruff --isolated check fast003_4.py --select FAST003 --unsafe-fixes --fix --output-format concise -q
fast003_4.py:4:34: invalid-syntax: cannot assign to `__debug__`
$ cat fast003_4.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/queries/{__debug__}")
async def read_query(query: str, __debug__): ...
$ python fast003_4.py 2>&1 | tail -n 1
SyntaxError: cannot assign to __debug__The fix fails to converge when the path parameter is equivalent under NFKC to a function parameter but not equal to it. FastAPI only supports ASCII in path parameter names anyway, so the fix should ignore non-ASCII path parameters. Example:
$ cat >fast003_5.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/queries/{𝑞𝑢𝑒𝑟𝑦}")
async def read_query(query: str): ...
# EOF
$ ruff --isolated check fast003_5.py --select FAST003 --unsafe-fixes --diff
error: Failed to converge after 100 iterations.
This indicates a bug in Ruff. If you could open an issue at:
https://github.com/astral-sh/ruff/issues/new?title=%5BInfinite%20loop%5D
...quoting the contents of `fast003_5.py`, the rule codes FAST003, along with the `pyproject.toml` settings and executed command, we'd be very appreciative!
--- fast003_5.py
+++ fast003_5.py
@@ -1,4 +1,4 @@
from fastapi import FastAPI
app = FastAPI()
@app.get("/queries/{𝑞𝑢𝑒𝑟𝑦}")
-async def read_query(query: str): ...
+async def read_query(query: str, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦, 𝑞𝑢𝑒𝑟𝑦): ...
Would fix 100 errors.The fix can add a parameter without a default after a positional-only parameter with a default, which is a syntax error. Example:
$ cat >fast003_6.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/things/{thing_id}")
async def read_thing(query: str = "", /,): ...
# EOF
$ ruff --isolated check fast003_6.py --select FAST003 --unsafe-fixes --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.The fix can create a positional-only parameter. That isn’t a syntax error but it doesn’t fix the problem, so it is not a useful change. As the FAST003 documentation says, “If a path parameter is declared in the route path, but as a positional-only argument in the function signature, it will also not be accessible in the function body, as FastAPI will not inject the parameter.” Example:
$ cat >fast003_7.py <<'# EOF'
from fastapi import FastAPI
app = FastAPI()
@app.get("/things/{thing_id}")
async def read_thing(query: str = "", /, x=None): ...
# EOF
$ ruff --isolated check fast003_7.py --select FAST003 --unsafe-fixes --fix --output-format concise -q
fast003_7.py:3:19: FAST003 Parameter `thing_id` appears in route path, but only as a positional-only argument in `read_thing` signature
$ cat fast003_7.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/things/{thing_id}")
async def read_thing(thing_id, query: str = "", /, x=None): ...Version
ruff 0.12.8 (f51a228 2025-08-07)