Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
324455f580 | ||
|
|
da1c320bfa | ||
|
|
485d997d35 | ||
|
|
d7214e77e6 | ||
|
|
952c623102 | ||
|
|
0a26201643 | ||
|
|
0e67757edb | ||
|
|
c395e44bd7 | ||
|
|
75da72bd7f | ||
|
|
521e6de2c8 | ||
|
|
0b963ddcfa | ||
|
|
937de121f3 | ||
|
|
787e2fd49d | ||
|
|
6acc316d19 | ||
|
|
a647f31600 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -4,3 +4,4 @@ crates/ruff/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
|
||||
crates/ruff/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
|
||||
|
||||
ruff.schema.json linguist-generated=true text=auto eol=lf
|
||||
*.md.snap linguist-language=Markdown
|
||||
|
||||
16
.github/workflows/ci.yaml
vendored
16
.github/workflows/ci.yaml
vendored
@@ -31,17 +31,6 @@ jobs:
|
||||
cargo-clippy:
|
||||
name: "cargo clippy"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: |
|
||||
rustup component add clippy
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
|
||||
cargo-clippy-wasm:
|
||||
name: "cargo clippy (wasm)"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
@@ -49,7 +38,10 @@ jobs:
|
||||
rustup component add clippy
|
||||
rustup target add wasm32-unknown-unknown
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
- name: "Clippy"
|
||||
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
- name: "Clippy (wasm)"
|
||||
run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
|
||||
cargo-test:
|
||||
strategy:
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
# Breaking Changes
|
||||
|
||||
## 0.0.277
|
||||
|
||||
### `.ipynb_checkpoints`, `.pyenv`, `.pytest_cache`, and `.vscode` are now excluded by default ([#5513](https://github.com/astral-sh/ruff/pull/5513))
|
||||
|
||||
Ruff maintains a list of default exclusions, which now consists of the following patterns:
|
||||
|
||||
- `.bzr`
|
||||
- `.direnv`
|
||||
- `.eggs`
|
||||
- `.git`
|
||||
- `.git-rewrite`
|
||||
- `.hg`
|
||||
- `.ipynb_checkpoints`
|
||||
- `.mypy_cache`
|
||||
- `.nox`
|
||||
- `.pants.d`
|
||||
- `.pyenv`
|
||||
- `.pytest_cache`
|
||||
- `.pytype`
|
||||
- `.ruff_cache`
|
||||
- `.svn`
|
||||
- `.tox`
|
||||
- `.venv`
|
||||
- `.vscode`
|
||||
- `__pypackages__`
|
||||
- `_build`
|
||||
- `buck-out`
|
||||
- `build`
|
||||
- `dist`
|
||||
- `node_modules`
|
||||
- `venv`
|
||||
|
||||
Previously, the `.ipynb_checkpoints`, `.pyenv`, `.pytest_cache`, and `.vscode` directories were not
|
||||
excluded by default. This change brings Ruff's default exclusions in line with other tools like
|
||||
Black.
|
||||
|
||||
## 0.0.276
|
||||
|
||||
### The `keep-runtime-typing` setting has been reinstated ([#5470](https://github.com/astral-sh/ruff/pull/5470))
|
||||
|
||||
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -746,7 +746,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.276"
|
||||
version = "0.0.277"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1829,7 +1829,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.276"
|
||||
version = "0.0.277"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1865,6 +1865,7 @@ dependencies = [
|
||||
"result-like",
|
||||
"ruff_cache",
|
||||
"ruff_diagnostics",
|
||||
"ruff_index",
|
||||
"ruff_macros",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_semantic",
|
||||
@@ -1926,7 +1927,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cli"
|
||||
version = "0.0.276"
|
||||
version = "0.0.277"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
|
||||
@@ -139,7 +139,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.0.276
|
||||
rev: v0.0.277
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.276"
|
||||
version = "0.0.277"
|
||||
description = """
|
||||
Convert Flake8 configuration files to Ruff configuration files.
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.276"
|
||||
version = "0.0.277"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
@@ -17,6 +17,7 @@ name = "ruff"
|
||||
[dependencies]
|
||||
ruff_cache = { path = "../ruff_cache" }
|
||||
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
||||
ruff_index = { path = "../ruff_index" }
|
||||
ruff_macros = { path = "../ruff_macros" }
|
||||
ruff_python_whitespace = { path = "../ruff_python_whitespace" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast", features = ["serde"] }
|
||||
@@ -88,3 +89,5 @@ colored = { workspace = true, features = ["no-color"] }
|
||||
[features]
|
||||
default = []
|
||||
schemars = ["dep:schemars"]
|
||||
# Enables the UnreachableCode rule
|
||||
unreachable-code = []
|
||||
|
||||
11
crates/ruff/resources/test/fixtures/control-flow-graph/assert.py
vendored
Normal file
11
crates/ruff/resources/test/fixtures/control-flow-graph/assert.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
def func():
|
||||
assert True
|
||||
|
||||
def func():
|
||||
assert False
|
||||
|
||||
def func():
|
||||
assert True, "oops"
|
||||
|
||||
def func():
|
||||
assert False, "oops"
|
||||
41
crates/ruff/resources/test/fixtures/control-flow-graph/async-for.py
vendored
Normal file
41
crates/ruff/resources/test/fixtures/control-flow-graph/async-for.py
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
def func():
|
||||
async for i in range(5):
|
||||
print(i)
|
||||
|
||||
def func():
|
||||
async for i in range(20):
|
||||
print(i)
|
||||
else:
|
||||
return 0
|
||||
|
||||
def func():
|
||||
async for i in range(10):
|
||||
if i == 5:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def func():
|
||||
async for i in range(111):
|
||||
if i == 5:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 2
|
||||
|
||||
def func():
|
||||
async for i in range(12):
|
||||
continue
|
||||
|
||||
def func():
|
||||
async for i in range(1110):
|
||||
if True:
|
||||
continue
|
||||
|
||||
def func():
|
||||
async for i in range(13):
|
||||
break
|
||||
|
||||
def func():
|
||||
async for i in range(1110):
|
||||
if True:
|
||||
break
|
||||
41
crates/ruff/resources/test/fixtures/control-flow-graph/for.py
vendored
Normal file
41
crates/ruff/resources/test/fixtures/control-flow-graph/for.py
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
def func():
|
||||
for i in range(5):
|
||||
print(i)
|
||||
|
||||
def func():
|
||||
for i in range(20):
|
||||
print(i)
|
||||
else:
|
||||
return 0
|
||||
|
||||
def func():
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def func():
|
||||
for i in range(111):
|
||||
if i == 5:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 2
|
||||
|
||||
def func():
|
||||
for i in range(12):
|
||||
continue
|
||||
|
||||
def func():
|
||||
for i in range(1110):
|
||||
if True:
|
||||
continue
|
||||
|
||||
def func():
|
||||
for i in range(13):
|
||||
break
|
||||
|
||||
def func():
|
||||
for i in range(1110):
|
||||
if True:
|
||||
break
|
||||
108
crates/ruff/resources/test/fixtures/control-flow-graph/if.py
vendored
Normal file
108
crates/ruff/resources/test/fixtures/control-flow-graph/if.py
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
return "unreachable"
|
||||
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return "unreachable"
|
||||
|
||||
def func():
|
||||
if True:
|
||||
if True:
|
||||
return 1
|
||||
return 2
|
||||
else:
|
||||
return 3
|
||||
return "unreachable2"
|
||||
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
elif False:
|
||||
return 2
|
||||
else:
|
||||
return 0
|
||||
|
||||
def func():
|
||||
if False:
|
||||
return 1
|
||||
elif True:
|
||||
return 2
|
||||
else:
|
||||
return 0
|
||||
|
||||
def func():
|
||||
if True:
|
||||
if False:
|
||||
return 0
|
||||
elif True:
|
||||
return 1
|
||||
else:
|
||||
return 2
|
||||
return 3
|
||||
elif True:
|
||||
return 4
|
||||
else:
|
||||
return 5
|
||||
return 6
|
||||
|
||||
def func():
|
||||
if False:
|
||||
return "unreached"
|
||||
elif False:
|
||||
return "also unreached"
|
||||
return "reached"
|
||||
|
||||
# Test case found in the Bokeh repository that trigger a false positive.
|
||||
def func(self, obj: BytesRep) -> bytes:
|
||||
data = obj["data"]
|
||||
|
||||
if isinstance(data, str):
|
||||
return base64.b64decode(data)
|
||||
elif isinstance(data, Buffer):
|
||||
buffer = data
|
||||
else:
|
||||
id = data["id"]
|
||||
|
||||
if id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f"can't resolve buffer '{id}'")
|
||||
|
||||
return buffer.data
|
||||
131
crates/ruff/resources/test/fixtures/control-flow-graph/match.py
vendored
Normal file
131
crates/ruff/resources/test/fixtures/control-flow-graph/match.py
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
def func(status):
|
||||
match status:
|
||||
case _:
|
||||
return 0
|
||||
return "unreachable"
|
||||
|
||||
def func(status):
|
||||
match status:
|
||||
case 1:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def func(status):
|
||||
match status:
|
||||
case 1:
|
||||
return 1
|
||||
case _:
|
||||
return 0
|
||||
|
||||
def func(status):
|
||||
match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5
|
||||
return 6
|
||||
|
||||
def func(status):
|
||||
match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5
|
||||
case _:
|
||||
return 10
|
||||
return 0
|
||||
|
||||
def func(status):
|
||||
match status:
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
case 1:
|
||||
return "1 again"
|
||||
case _:
|
||||
return 3
|
||||
|
||||
def func(status):
|
||||
i = 0
|
||||
match status, i:
|
||||
case _, _:
|
||||
return 0
|
||||
|
||||
def func(status):
|
||||
i = 0
|
||||
match status, i:
|
||||
case _, 0:
|
||||
return 0
|
||||
case _, 2:
|
||||
return 0
|
||||
|
||||
def func(point):
|
||||
match point:
|
||||
case (0, 0):
|
||||
print("Origin")
|
||||
case _:
|
||||
raise ValueError("oops")
|
||||
|
||||
def func(point):
|
||||
match point:
|
||||
case (0, 0):
|
||||
print("Origin")
|
||||
case (0, y):
|
||||
print(f"Y={y}")
|
||||
case (x, 0):
|
||||
print(f"X={x}")
|
||||
case (x, y):
|
||||
print(f"X={x}, Y={y}")
|
||||
case _:
|
||||
raise ValueError("Not a point")
|
||||
|
||||
def where_is(point):
|
||||
class Point:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
match point:
|
||||
case Point(x=0, y=0):
|
||||
print("Origin")
|
||||
case Point(x=0, y=y):
|
||||
print(f"Y={y}")
|
||||
case Point(x=x, y=0):
|
||||
print(f"X={x}")
|
||||
case Point():
|
||||
print("Somewhere else")
|
||||
case _:
|
||||
print("Not a point")
|
||||
|
||||
def func(points):
|
||||
match points:
|
||||
case []:
|
||||
print("No points")
|
||||
case [Point(0, 0)]:
|
||||
print("The origin")
|
||||
case [Point(x, y)]:
|
||||
print(f"Single point {x}, {y}")
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f"Two on the Y axis at {y1}, {y2}")
|
||||
case _:
|
||||
print("Something else")
|
||||
|
||||
def func(point):
|
||||
match point:
|
||||
case Point(x, y) if x == y:
|
||||
print(f"Y=X at {x}")
|
||||
case Point(x, y):
|
||||
print(f"Not on the diagonal")
|
||||
|
||||
def func():
|
||||
from enum import Enum
|
||||
class Color(Enum):
|
||||
RED = 'red'
|
||||
GREEN = 'green'
|
||||
BLUE = 'blue'
|
||||
|
||||
color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))
|
||||
|
||||
match color:
|
||||
case Color.RED:
|
||||
print("I see red!")
|
||||
case Color.GREEN:
|
||||
print("Grass is green")
|
||||
case Color.BLUE:
|
||||
print("I'm feeling the blues :(")
|
||||
5
crates/ruff/resources/test/fixtures/control-flow-graph/raise.py
vendored
Normal file
5
crates/ruff/resources/test/fixtures/control-flow-graph/raise.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
def func():
|
||||
raise Exception
|
||||
|
||||
def func():
|
||||
raise "a glass!"
|
||||
23
crates/ruff/resources/test/fixtures/control-flow-graph/simple.py
vendored
Normal file
23
crates/ruff/resources/test/fixtures/control-flow-graph/simple.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
def func():
|
||||
pass
|
||||
|
||||
def func():
|
||||
pass
|
||||
|
||||
def func():
|
||||
return
|
||||
|
||||
def func():
|
||||
return 1
|
||||
|
||||
def func():
|
||||
return 1
|
||||
return "unreachable"
|
||||
|
||||
def func():
|
||||
i = 0
|
||||
|
||||
def func():
|
||||
i = 0
|
||||
i += 2
|
||||
return i
|
||||
41
crates/ruff/resources/test/fixtures/control-flow-graph/try.py
vendored
Normal file
41
crates/ruff/resources/test/fixtures/control-flow-graph/try.py
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
def func():
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
...
|
||||
except OtherException as e:
|
||||
...
|
||||
else:
|
||||
...
|
||||
finally:
|
||||
...
|
||||
|
||||
def func():
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
...
|
||||
|
||||
def func():
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
...
|
||||
except OtherException as e:
|
||||
...
|
||||
|
||||
def func():
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
...
|
||||
except OtherException as e:
|
||||
...
|
||||
else:
|
||||
...
|
||||
|
||||
def func():
|
||||
try:
|
||||
...
|
||||
finally:
|
||||
...
|
||||
121
crates/ruff/resources/test/fixtures/control-flow-graph/while.py
vendored
Normal file
121
crates/ruff/resources/test/fixtures/control-flow-graph/while.py
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
def func():
|
||||
while False:
|
||||
return "unreachable"
|
||||
return 1
|
||||
|
||||
def func():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return 1
|
||||
|
||||
def func():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return 1
|
||||
return "also unreachable"
|
||||
|
||||
def func():
|
||||
while True:
|
||||
return 1
|
||||
return "unreachable"
|
||||
|
||||
def func():
|
||||
while True:
|
||||
return 1
|
||||
else:
|
||||
return "unreachable"
|
||||
|
||||
def func():
|
||||
while True:
|
||||
return 1
|
||||
else:
|
||||
return "unreachable"
|
||||
return "also unreachable"
|
||||
|
||||
def func():
|
||||
i = 0
|
||||
while False:
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def func():
|
||||
i = 0
|
||||
while True:
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def func():
|
||||
while True:
|
||||
pass
|
||||
return 1
|
||||
|
||||
def func():
|
||||
i = 0
|
||||
while True:
|
||||
if True:
|
||||
print("ok")
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def func():
|
||||
i = 0
|
||||
while True:
|
||||
if False:
|
||||
print("ok")
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def func():
|
||||
while True:
|
||||
if True:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def func():
|
||||
while True:
|
||||
continue
|
||||
|
||||
def func():
|
||||
while False:
|
||||
continue
|
||||
|
||||
def func():
|
||||
while True:
|
||||
break
|
||||
|
||||
def func():
|
||||
while False:
|
||||
break
|
||||
|
||||
def func():
|
||||
while True:
|
||||
if True:
|
||||
continue
|
||||
|
||||
def func():
|
||||
while True:
|
||||
if True:
|
||||
break
|
||||
|
||||
'''
|
||||
TODO: because `try` statements aren't handled this triggers a false positive as
|
||||
the last statement is reached, but the rules thinks it isn't (it doesn't
|
||||
see/process the break statement).
|
||||
|
||||
# Test case found in the Bokeh repository that trigger a false positive.
|
||||
def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
|
||||
self.stop_serving = False
|
||||
while True:
|
||||
try:
|
||||
self.server = HTTPServer((host, port), HtmlOnlyHandler)
|
||||
self.host = host
|
||||
self.port = port
|
||||
break
|
||||
except OSError:
|
||||
log.debug(f"port {port} is in use, trying to next one")
|
||||
port += 1
|
||||
|
||||
self.thread = threading.Thread(target=self._run_web_server)
|
||||
'''
|
||||
12
crates/ruff/resources/test/fixtures/flake8_bandit/S307.py
vendored
Normal file
12
crates/ruff/resources/test/fixtures/flake8_bandit/S307.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import os
|
||||
|
||||
print(eval("1+1")) # S307
|
||||
print(eval("os.getcwd()")) # S307
|
||||
|
||||
|
||||
class Class(object):
|
||||
def eval(self):
|
||||
print("hi")
|
||||
|
||||
def foo(self):
|
||||
self.eval() # OK
|
||||
@@ -30,3 +30,10 @@ def f():
|
||||
result = []
|
||||
for i in items:
|
||||
result.append(i) # OK
|
||||
|
||||
|
||||
def f():
|
||||
items = [1, 2, 3, 4]
|
||||
result = {}
|
||||
for i in items:
|
||||
result[i].append(i) # OK
|
||||
|
||||
@@ -17,3 +17,10 @@ def f():
|
||||
result = []
|
||||
for i in items:
|
||||
result.append(i * i) # OK
|
||||
|
||||
|
||||
def f():
|
||||
items = [1, 2, 3, 4]
|
||||
result = {}
|
||||
for i in items:
|
||||
result[i].append(i * i) # OK
|
||||
|
||||
56
crates/ruff/resources/test/fixtures/pylint/type_param_name_mismatch.py
vendored
Normal file
56
crates/ruff/resources/test/fixtures/pylint/type_param_name_mismatch.py
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
from typing import TypeVar, ParamSpec, NewType, TypeVarTuple
|
||||
|
||||
# Errors.
|
||||
|
||||
X = TypeVar("T")
|
||||
X = TypeVar(name="T")
|
||||
|
||||
Y = ParamSpec("T")
|
||||
Y = ParamSpec(name="T")
|
||||
|
||||
Z = NewType("T", int)
|
||||
Z = NewType(name="T", tp=int)
|
||||
|
||||
Ws = TypeVarTuple("Ts")
|
||||
Ws = TypeVarTuple(name="Ts")
|
||||
|
||||
# Non-errors.
|
||||
|
||||
T = TypeVar("T")
|
||||
T = TypeVar(name="T")
|
||||
|
||||
T = ParamSpec("T")
|
||||
T = ParamSpec(name="T")
|
||||
|
||||
T = NewType("T", int)
|
||||
T = NewType(name="T", tp=int)
|
||||
|
||||
Ts = TypeVarTuple("Ts")
|
||||
Ts = TypeVarTuple(name="Ts")
|
||||
|
||||
# Errors, but not covered by this rule.
|
||||
|
||||
# Non-string literal name.
|
||||
T = TypeVar(some_str)
|
||||
T = TypeVar(name=some_str)
|
||||
T = TypeVar(1)
|
||||
T = TypeVar(name=1)
|
||||
T = ParamSpec(some_str)
|
||||
T = ParamSpec(name=some_str)
|
||||
T = ParamSpec(1)
|
||||
T = ParamSpec(name=1)
|
||||
T = NewType(some_str, int)
|
||||
T = NewType(name=some_str, tp=int)
|
||||
T = NewType(1, int)
|
||||
T = NewType(name=1, tp=int)
|
||||
Ts = TypeVarTuple(some_str)
|
||||
Ts = TypeVarTuple(name=some_str)
|
||||
Ts = TypeVarTuple(1)
|
||||
Ts = TypeVarTuple(name=1)
|
||||
|
||||
# No names provided.
|
||||
T = TypeVar()
|
||||
T = ParamSpec()
|
||||
T = NewType()
|
||||
T = NewType(tp=int)
|
||||
Ts = TypeVarTuple()
|
||||
185
crates/ruff/resources/test/fixtures/ruff/RUF014.py
vendored
Normal file
185
crates/ruff/resources/test/fixtures/ruff/RUF014.py
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
def after_return():
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
async def also_works_on_async_functions():
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def if_always_true():
|
||||
if True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def if_always_false():
|
||||
if False:
|
||||
return "unreachable"
|
||||
return "reachable"
|
||||
|
||||
def if_elif_always_false():
|
||||
if False:
|
||||
return "unreachable"
|
||||
elif False:
|
||||
return "also unreachable"
|
||||
return "reachable"
|
||||
|
||||
def if_elif_always_true():
|
||||
if False:
|
||||
return "unreachable"
|
||||
elif True:
|
||||
return "reachable"
|
||||
return "also unreachable"
|
||||
|
||||
def ends_with_if():
|
||||
if False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return "reachable"
|
||||
|
||||
def infinite_loop():
|
||||
while True:
|
||||
continue
|
||||
return "unreachable"
|
||||
|
||||
''' TODO: we could determine these, but we don't yet.
|
||||
def for_range_return():
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def for_range_else():
|
||||
for i in range(111):
|
||||
if i == 5:
|
||||
return "reachable"
|
||||
else:
|
||||
return "unreachable"
|
||||
return "also unreachable"
|
||||
|
||||
def for_range_break():
|
||||
for i in range(13):
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def for_range_if_break():
|
||||
for i in range(1110):
|
||||
if True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
'''
|
||||
|
||||
def match_wildcard(status):
|
||||
match status:
|
||||
case _:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def match_case_and_wildcard(status):
|
||||
match status:
|
||||
case 1:
|
||||
return "reachable"
|
||||
case _:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def raise_exception():
|
||||
raise Exception
|
||||
return "unreachable"
|
||||
|
||||
def while_false():
|
||||
while False:
|
||||
return "unreachable"
|
||||
return "reachable"
|
||||
|
||||
def while_false_else():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return "reachable"
|
||||
|
||||
def while_false_else_return():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return "reachable"
|
||||
return "also unreachable"
|
||||
|
||||
def while_true():
|
||||
while True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def while_true_else():
|
||||
while True:
|
||||
return "reachable"
|
||||
else:
|
||||
return "unreachable"
|
||||
|
||||
def while_true_else_return():
|
||||
while True:
|
||||
return "reachable"
|
||||
else:
|
||||
return "unreachable"
|
||||
return "also unreachable"
|
||||
|
||||
def while_false_var_i():
|
||||
i = 0
|
||||
while False:
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def while_true_var_i():
|
||||
i = 0
|
||||
while True:
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def while_infinite():
|
||||
while True:
|
||||
pass
|
||||
return "unreachable"
|
||||
|
||||
def while_if_true():
|
||||
while True:
|
||||
if True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
# Test case found in the Bokeh repository that trigger a false positive.
|
||||
def bokeh1(self, obj: BytesRep) -> bytes:
|
||||
data = obj["data"]
|
||||
|
||||
if isinstance(data, str):
|
||||
return base64.b64decode(data)
|
||||
elif isinstance(data, Buffer):
|
||||
buffer = data
|
||||
else:
|
||||
id = data["id"]
|
||||
|
||||
if id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f"can't resolve buffer '{id}'")
|
||||
|
||||
return buffer.data
|
||||
|
||||
'''
|
||||
TODO: because `try` statements aren't handled this triggers a false positive as
|
||||
the last statement is reached, but the rules thinks it isn't (it doesn't
|
||||
see/process the break statement).
|
||||
|
||||
# Test case found in the Bokeh repository that trigger a false positive.
|
||||
def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
|
||||
self.stop_serving = False
|
||||
while True:
|
||||
try:
|
||||
self.server = HTTPServer((host, port), HtmlOnlyHandler)
|
||||
self.host = host
|
||||
self.port = port
|
||||
break
|
||||
except OSError:
|
||||
log.debug(f"port {port} is in use, trying to next one")
|
||||
port += 1
|
||||
|
||||
self.thread = threading.Thread(target=self._run_web_server)
|
||||
'''
|
||||
@@ -619,6 +619,11 @@ where
|
||||
);
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "unreachable-code")]
|
||||
if self.enabled(Rule::UnreachableCode) {
|
||||
self.diagnostics
|
||||
.extend(ruff::rules::unreachable::in_function(name, body));
|
||||
}
|
||||
}
|
||||
Stmt::Return(_) => {
|
||||
if self.enabled(Rule::ReturnOutsideFunction) {
|
||||
@@ -1650,6 +1655,9 @@ where
|
||||
self.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
if self.settings.rules.enabled(Rule::TypeParamNameMismatch) {
|
||||
pylint::rules::type_param_name_mismatch(self, value, targets);
|
||||
}
|
||||
if self.is_stub {
|
||||
if self.any_enabled(&[
|
||||
Rule::UnprefixedTypeParam,
|
||||
@@ -2579,9 +2587,7 @@ where
|
||||
flake8_pie::rules::unnecessary_dict_kwargs(self, expr, keywords);
|
||||
}
|
||||
if self.enabled(Rule::ExecBuiltin) {
|
||||
if let Some(diagnostic) = flake8_bandit::rules::exec_used(expr, func) {
|
||||
self.diagnostics.push(diagnostic);
|
||||
}
|
||||
flake8_bandit::rules::exec_used(self, func);
|
||||
}
|
||||
if self.enabled(Rule::BadFilePermissions) {
|
||||
flake8_bandit::rules::bad_file_permissions(self, func, args, keywords);
|
||||
|
||||
@@ -14,6 +14,18 @@ use crate::rules;
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct NoqaCode(&'static str, &'static str);
|
||||
|
||||
impl NoqaCode {
|
||||
/// Return the prefix for the [`NoqaCode`], e.g., `SIM` for `SIM101`.
|
||||
pub fn prefix(&self) -> &str {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Return the suffix for the [`NoqaCode`], e.g., `101` for `SIM101`.
|
||||
pub fn suffix(&self) -> &str {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for NoqaCode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self, f)
|
||||
@@ -156,6 +168,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||
(Pyflakes, "901") => (RuleGroup::Unspecified, rules::pyflakes::rules::RaiseNotImplemented),
|
||||
|
||||
// pylint
|
||||
(Pylint, "C0132") => (RuleGroup::Unspecified, rules::pylint::rules::TypeParamNameMismatch),
|
||||
(Pylint, "C0205") => (RuleGroup::Unspecified, rules::pylint::rules::SingleStringSlots),
|
||||
(Pylint, "C0414") => (RuleGroup::Unspecified, rules::pylint::rules::UselessImportAlias),
|
||||
(Pylint, "C1901") => (RuleGroup::Nursery, rules::pylint::rules::CompareToEmptyString),
|
||||
@@ -761,6 +774,8 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||
(Ruff, "011") => (RuleGroup::Unspecified, rules::ruff::rules::StaticKeyDictComprehension),
|
||||
(Ruff, "012") => (RuleGroup::Unspecified, rules::ruff::rules::MutableClassDefault),
|
||||
(Ruff, "013") => (RuleGroup::Unspecified, rules::ruff::rules::ImplicitOptional),
|
||||
#[cfg(feature = "unreachable-code")]
|
||||
(Ruff, "014") => (RuleGroup::Nursery, rules::ruff::rules::UnreachableCode),
|
||||
(Ruff, "100") => (RuleGroup::Unspecified, rules::ruff::rules::UnusedNOQA),
|
||||
(Ruff, "200") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidPyprojectToml),
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ pub(crate) fn infer_plugins_from_codes(selectors: &HashSet<RuleSelector>) -> Vec
|
||||
for selector in selectors {
|
||||
if selector
|
||||
.into_iter()
|
||||
.any(|rule| Linter::from(plugin).into_iter().any(|r| r == rule))
|
||||
.any(|rule| Linter::from(plugin).rules().any(|r| r == rule))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ pub trait AsRule {
|
||||
impl Rule {
|
||||
pub fn from_code(code: &str) -> Result<Self, FromCodeError> {
|
||||
let (linter, code) = Linter::parse_code(code).ok_or(FromCodeError::Unknown)?;
|
||||
let prefix: RuleCodePrefix = RuleCodePrefix::parse(&linter, code)?;
|
||||
Ok(prefix.into_iter().next().unwrap())
|
||||
linter
|
||||
.all_rules()
|
||||
.find(|rule| rule.noqa_code().suffix() == code)
|
||||
.ok_or(FromCodeError::Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,16 +158,16 @@ impl IntoIterator for &RuleSelector {
|
||||
}
|
||||
RuleSelector::C => RuleSelectorIter::Chain(
|
||||
Linter::Flake8Comprehensions
|
||||
.into_iter()
|
||||
.chain(Linter::McCabe.into_iter()),
|
||||
.rules()
|
||||
.chain(Linter::McCabe.rules()),
|
||||
),
|
||||
RuleSelector::T => RuleSelectorIter::Chain(
|
||||
Linter::Flake8Debugger
|
||||
.into_iter()
|
||||
.chain(Linter::Flake8Print.into_iter()),
|
||||
.rules()
|
||||
.chain(Linter::Flake8Print.rules()),
|
||||
),
|
||||
RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.into_iter()),
|
||||
RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.into_iter()),
|
||||
RuleSelector::Linter(linter) => RuleSelectorIter::Vec(linter.rules()),
|
||||
RuleSelector::Prefix { prefix, .. } => RuleSelectorIter::Vec(prefix.clone().rules()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,7 +346,7 @@ mod clap_completion {
|
||||
let prefix = p.linter().common_prefix();
|
||||
let code = p.short_code();
|
||||
|
||||
let mut rules_iter = p.into_iter();
|
||||
let mut rules_iter = p.rules();
|
||||
let rule1 = rules_iter.next();
|
||||
let rule2 = rules_iter.next();
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ mod tests {
|
||||
#[test_case(Rule::SubprocessPopenWithShellEqualsTrue, Path::new("S602.py"))]
|
||||
#[test_case(Rule::SubprocessWithoutShellEqualsTrue, Path::new("S603.py"))]
|
||||
#[test_case(Rule::SuspiciousPickleUsage, Path::new("S301.py"))]
|
||||
#[test_case(Rule::SuspiciousEvalUsage, Path::new("S307.py"))]
|
||||
#[test_case(Rule::SuspiciousTelnetUsage, Path::new("S312.py"))]
|
||||
#[test_case(Rule::TryExceptContinue, Path::new("S112.py"))]
|
||||
#[test_case(Rule::TryExceptPass, Path::new("S110.py"))]
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use rustpython_parser::ast::{self, Expr, Ranged};
|
||||
use rustpython_parser::ast::{Expr, Ranged};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
#[violation]
|
||||
pub struct ExecBuiltin;
|
||||
|
||||
@@ -14,12 +16,16 @@ impl Violation for ExecBuiltin {
|
||||
}
|
||||
|
||||
/// S102
|
||||
pub(crate) fn exec_used(expr: &Expr, func: &Expr) -> Option<Diagnostic> {
|
||||
let Expr::Name(ast::ExprName { id, .. }) = func else {
|
||||
return None;
|
||||
};
|
||||
if id != "exec" {
|
||||
return None;
|
||||
pub(crate) fn exec_used(checker: &mut Checker, func: &Expr) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
matches!(call_path.as_slice(), ["" | "builtin", "exec"])
|
||||
})
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ExecBuiltin, func.range()));
|
||||
}
|
||||
Some(Diagnostic::new(ExecBuiltin, expr.range()))
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ impl Violation for SuspiciousFTPLibUsage {
|
||||
}
|
||||
}
|
||||
|
||||
/// S001
|
||||
/// S301, S302, S303, S304, S305, S306, S307, S308, S310, S311, S312, S313, S314, S315, S316, S317, S318, S319, S320, S321, S323
|
||||
pub(crate) fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
|
||||
return;
|
||||
@@ -246,7 +246,7 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
|
||||
// Mktemp
|
||||
["tempfile", "mktemp"] => Some(SuspiciousMktempUsage.into()),
|
||||
// Eval
|
||||
["eval"] => Some(SuspiciousEvalUsage.into()),
|
||||
["" | "builtins", "eval"] => Some(SuspiciousEvalUsage.into()),
|
||||
// MarkSafe
|
||||
["django", "utils", "safestring", "mark_safe"] => Some(SuspiciousMarkSafeUsage.into()),
|
||||
// URLOpen
|
||||
|
||||
@@ -6,7 +6,7 @@ S102.py:3:5: S102 Use of `exec` detected
|
||||
1 | def fn():
|
||||
2 | # Error
|
||||
3 | exec('x = 2')
|
||||
| ^^^^^^^^^^^^^ S102
|
||||
| ^^^^ S102
|
||||
4 |
|
||||
5 | exec('y = 3')
|
||||
|
|
||||
@@ -16,7 +16,7 @@ S102.py:5:1: S102 Use of `exec` detected
|
||||
3 | exec('x = 2')
|
||||
4 |
|
||||
5 | exec('y = 3')
|
||||
| ^^^^^^^^^^^^^ S102
|
||||
| ^^^^ S102
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_bandit/mod.rs
|
||||
---
|
||||
S307.py:3:7: S307 Use of possibly insecure function; consider using `ast.literal_eval`
|
||||
|
|
||||
1 | import os
|
||||
2 |
|
||||
3 | print(eval("1+1")) # S307
|
||||
| ^^^^^^^^^^^ S307
|
||||
4 | print(eval("os.getcwd()")) # S307
|
||||
|
|
||||
|
||||
S307.py:4:7: S307 Use of possibly insecure function; consider using `ast.literal_eval`
|
||||
|
|
||||
3 | print(eval("1+1")) # S307
|
||||
4 | print(eval("os.getcwd()")) # S307
|
||||
| ^^^^^^^^^^^^^^^^^^^ S307
|
||||
|
|
||||
|
||||
|
||||
@@ -42,16 +42,16 @@ impl AlwaysAutofixableViolation for BadQuotesInlineString {
|
||||
fn message(&self) -> String {
|
||||
let BadQuotesInlineString { quote } = self;
|
||||
match quote {
|
||||
Quote::Single => format!("Double quotes found but single quotes preferred"),
|
||||
Quote::Double => format!("Single quotes found but double quotes preferred"),
|
||||
Quote::Single => format!("Double quotes found but single quotes preferred"),
|
||||
}
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let BadQuotesInlineString { quote } = self;
|
||||
match quote {
|
||||
Quote::Single => "Replace double quotes with single quotes".to_string(),
|
||||
Quote::Double => "Replace single quotes with double quotes".to_string(),
|
||||
Quote::Single => "Replace double quotes with single quotes".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,16 +91,16 @@ impl AlwaysAutofixableViolation for BadQuotesMultilineString {
|
||||
fn message(&self) -> String {
|
||||
let BadQuotesMultilineString { quote } = self;
|
||||
match quote {
|
||||
Quote::Single => format!("Double quote multiline found but single quotes preferred"),
|
||||
Quote::Double => format!("Single quote multiline found but double quotes preferred"),
|
||||
Quote::Single => format!("Double quote multiline found but single quotes preferred"),
|
||||
}
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let BadQuotesMultilineString { quote } = self;
|
||||
match quote {
|
||||
Quote::Single => "Replace double multiline quotes with single quotes".to_string(),
|
||||
Quote::Double => "Replace single multiline quotes with double quotes".to_string(),
|
||||
Quote::Single => "Replace double multiline quotes with single quotes".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,16 +139,16 @@ impl AlwaysAutofixableViolation for BadQuotesDocstring {
|
||||
fn message(&self) -> String {
|
||||
let BadQuotesDocstring { quote } = self;
|
||||
match quote {
|
||||
Quote::Single => format!("Double quote docstring found but single quotes preferred"),
|
||||
Quote::Double => format!("Single quote docstring found but double quotes preferred"),
|
||||
Quote::Single => format!("Double quote docstring found but single quotes preferred"),
|
||||
}
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let BadQuotesDocstring { quote } = self;
|
||||
match quote {
|
||||
Quote::Single => "Replace double quotes docstring with single quotes".to_string(),
|
||||
Quote::Double => "Replace single quotes docstring with double quotes".to_string(),
|
||||
Quote::Single => "Replace double quotes docstring with single quotes".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,8 +186,8 @@ impl AlwaysAutofixableViolation for AvoidableEscapedQuote {
|
||||
|
||||
const fn good_single(quote: Quote) -> char {
|
||||
match quote {
|
||||
Quote::Single => '\'',
|
||||
Quote::Double => '"',
|
||||
Quote::Single => '\'',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,22 +200,22 @@ const fn bad_single(quote: Quote) -> char {
|
||||
|
||||
const fn good_multiline(quote: Quote) -> &'static str {
|
||||
match quote {
|
||||
Quote::Single => "'''",
|
||||
Quote::Double => "\"\"\"",
|
||||
Quote::Single => "'''",
|
||||
}
|
||||
}
|
||||
|
||||
const fn good_multiline_ending(quote: Quote) -> &'static str {
|
||||
match quote {
|
||||
Quote::Single => "'\"\"\"",
|
||||
Quote::Double => "\"'''",
|
||||
Quote::Single => "'\"\"\"",
|
||||
}
|
||||
}
|
||||
|
||||
const fn good_docstring(quote: Quote) -> &'static str {
|
||||
match quote {
|
||||
Quote::Single => "'",
|
||||
Quote::Double => "\"",
|
||||
Quote::Single => "'",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ use ruff_macros::{CacheKey, CombineOptions, ConfigurationOptions};
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum Quote {
|
||||
/// Use single quotes.
|
||||
Single,
|
||||
/// Use double quotes.
|
||||
Double,
|
||||
/// Use single quotes.
|
||||
Single,
|
||||
}
|
||||
|
||||
impl Default for Quote {
|
||||
|
||||
@@ -327,7 +327,7 @@ mod tests {
|
||||
fn contents(contents: &str, snapshot: &str) {
|
||||
let diagnostics = test_snippet(
|
||||
contents,
|
||||
&settings::Settings::for_rules(&Linter::Flake8TypeChecking),
|
||||
&settings::Settings::for_rules(Linter::Flake8TypeChecking.rules()),
|
||||
);
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
}
|
||||
|
||||
@@ -353,8 +353,10 @@ mod tests {
|
||||
"PD901_fail_df_var"
|
||||
)]
|
||||
fn contents(contents: &str, snapshot: &str) {
|
||||
let diagnostics =
|
||||
test_snippet(contents, &settings::Settings::for_rules(&Linter::PandasVet));
|
||||
let diagnostics = test_snippet(
|
||||
contents,
|
||||
&settings::Settings::for_rules(Linter::PandasVet.rules()),
|
||||
);
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ use rustpython_parser::ast::{self, Expr, Stmt};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::any_over_expr;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
@@ -52,6 +53,10 @@ impl Violation for ManualListComprehension {
|
||||
|
||||
/// PERF401
|
||||
pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, body: &[Stmt]) {
|
||||
let Expr::Name(ast::ExprName { id, .. }) = target else {
|
||||
return;
|
||||
};
|
||||
|
||||
let (stmt, conditional) = match body {
|
||||
// ```python
|
||||
// for x in y:
|
||||
@@ -99,22 +104,27 @@ pub(crate) fn manual_list_comprehension(checker: &mut Checker, target: &Expr, bo
|
||||
|
||||
// Ignore direct list copies (e.g., `for x in y: filtered.append(x)`).
|
||||
if !conditional {
|
||||
if arg.as_name_expr().map_or(false, |arg| {
|
||||
target
|
||||
.as_name_expr()
|
||||
.map_or(false, |target| arg.id == target.id)
|
||||
}) {
|
||||
if arg.as_name_expr().map_or(false, |arg| arg.id == *id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else {
|
||||
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if attr.as_str() == "append" {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ManualListComprehension, *range));
|
||||
if attr.as_str() != "append" {
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid, e.g., `for x in y: filtered[x].append(x * x)`.
|
||||
if any_over_expr(value, &|expr| {
|
||||
expr.as_name_expr().map_or(false, |expr| expr.id == *id)
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ManualListComprehension, *range));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use rustpython_parser::ast::{self, Expr, Stmt};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::any_over_expr;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
@@ -45,6 +46,10 @@ impl Violation for ManualListCopy {
|
||||
|
||||
/// PERF402
|
||||
pub(crate) fn manual_list_copy(checker: &mut Checker, target: &Expr, body: &[Stmt]) {
|
||||
let Expr::Name(ast::ExprName { id, .. }) = target else {
|
||||
return;
|
||||
};
|
||||
|
||||
let [stmt] = body else {
|
||||
return;
|
||||
};
|
||||
@@ -72,21 +77,26 @@ pub(crate) fn manual_list_copy(checker: &mut Checker, target: &Expr, body: &[Stm
|
||||
};
|
||||
|
||||
// Only flag direct list copies (e.g., `for x in y: filtered.append(x)`).
|
||||
if !arg.as_name_expr().map_or(false, |arg| {
|
||||
target
|
||||
.as_name_expr()
|
||||
.map_or(false, |target| arg.id == target.id)
|
||||
if !arg.as_name_expr().map_or(false, |arg| arg.id == *id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !matches!(attr.as_str(), "append" | "insert") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid, e.g., `for x in y: filtered[x].append(x * x)`.
|
||||
if any_over_expr(value, &|expr| {
|
||||
expr.as_name_expr().map_or(false, |expr| expr.id == *id)
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
|
||||
let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if matches!(attr.as_str(), "append" | "insert") {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ManualListCopy, *range));
|
||||
}
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ManualListCopy, *range));
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ mod tests {
|
||||
"load_after_unbind_from_class_scope"
|
||||
)]
|
||||
fn contents(contents: &str, snapshot: &str) {
|
||||
let diagnostics = test_snippet(contents, &Settings::for_rules(&Linter::Pyflakes));
|
||||
let diagnostics = test_snippet(contents, &Settings::for_rules(Linter::Pyflakes.rules()));
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
}
|
||||
|
||||
@@ -498,7 +498,7 @@ mod tests {
|
||||
/// Note that all tests marked with `#[ignore]` should be considered TODOs.
|
||||
fn flakes(contents: &str, expected: &[Rule]) {
|
||||
let contents = dedent(contents);
|
||||
let settings = Settings::for_rules(&Linter::Pyflakes);
|
||||
let settings = Settings::for_rules(Linter::Pyflakes.rules());
|
||||
let tokens: Vec<LexResult> = ruff_rustpython::tokenize(&contents);
|
||||
let locator = Locator::new(&contents);
|
||||
let stylist = Stylist::from_tokens(&tokens, &locator);
|
||||
|
||||
@@ -85,6 +85,7 @@ mod tests {
|
||||
Path::new("too_many_return_statements.py")
|
||||
)]
|
||||
#[test_case(Rule::TooManyStatements, Path::new("too_many_statements.py"))]
|
||||
#[test_case(Rule::TypeParamNameMismatch, Path::new("type_param_name_mismatch.py"))]
|
||||
#[test_case(
|
||||
Rule::UnexpectedSpecialMethodSignature,
|
||||
Path::new("unexpected_special_method_signature.py")
|
||||
|
||||
@@ -37,6 +37,7 @@ pub(crate) use too_many_arguments::*;
|
||||
pub(crate) use too_many_branches::*;
|
||||
pub(crate) use too_many_return_statements::*;
|
||||
pub(crate) use too_many_statements::*;
|
||||
pub(crate) use type_param_name_mismatch::*;
|
||||
pub(crate) use unexpected_special_method_signature::*;
|
||||
pub(crate) use unnecessary_direct_lambda_call::*;
|
||||
pub(crate) use useless_else_on_loop::*;
|
||||
@@ -84,6 +85,7 @@ mod too_many_arguments;
|
||||
mod too_many_branches;
|
||||
mod too_many_return_statements;
|
||||
mod too_many_statements;
|
||||
mod type_param_name_mismatch;
|
||||
mod unexpected_special_method_signature;
|
||||
mod unnecessary_direct_lambda_call;
|
||||
mod useless_else_on_loop;
|
||||
|
||||
166
crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs
Normal file
166
crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs
Normal file
@@ -0,0 +1,166 @@
|
||||
use std::fmt;
|
||||
|
||||
use rustpython_parser::ast::{self, Constant, Expr, Ranged};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `TypeVar`, `TypeVarTuple`, `ParamSpec`, and `NewType`
|
||||
/// definitions in which the name of the type parameter does not match the name
|
||||
/// of the variable to which it is assigned.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// When defining a `TypeVar` or a related type parameter, Python allows you to
|
||||
/// provide a name for the type parameter. According to [PEP 484], the name
|
||||
/// provided to the `TypeVar` constructor must be equal to the name of the
|
||||
/// variable to which it is assigned.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// from typing import TypeVar
|
||||
///
|
||||
/// T = TypeVar("U")
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from typing import TypeVar
|
||||
///
|
||||
/// T = TypeVar("T")
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `typing` — Support for type hints](https://docs.python.org/3/library/typing.html)
|
||||
/// - [PEP 484 – Type Hints: Generics](https://peps.python.org/pep-0484/#generics)
|
||||
///
|
||||
/// [PEP 484]:https://peps.python.org/pep-0484/#generics
|
||||
#[violation]
|
||||
pub struct TypeParamNameMismatch {
|
||||
kind: VarKind,
|
||||
var_name: String,
|
||||
param_name: String,
|
||||
}
|
||||
|
||||
impl Violation for TypeParamNameMismatch {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let TypeParamNameMismatch {
|
||||
kind,
|
||||
var_name,
|
||||
param_name,
|
||||
} = self;
|
||||
format!("`{kind}` name `{param_name}` does not match assigned variable name `{var_name}`")
|
||||
}
|
||||
}
|
||||
|
||||
/// PLC0132
|
||||
pub(crate) fn type_param_name_mismatch(checker: &mut Checker, value: &Expr, targets: &[Expr]) {
|
||||
let [target] = targets else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Expr::Name(ast::ExprName { id: var_name, .. }) = &target else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(param_name) = param_name(value) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if var_name == param_name {
|
||||
return;
|
||||
}
|
||||
|
||||
let Expr::Call(ast::ExprCall { func, .. }) = value else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(kind) = checker
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.and_then(|call_path| {
|
||||
if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "ParamSpec")
|
||||
{
|
||||
Some(VarKind::ParamSpec)
|
||||
} else if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "TypeVar")
|
||||
{
|
||||
Some(VarKind::TypeVar)
|
||||
} else if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "TypeVarTuple")
|
||||
{
|
||||
Some(VarKind::TypeVarTuple)
|
||||
} else if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "NewType")
|
||||
{
|
||||
Some(VarKind::NewType)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
TypeParamNameMismatch {
|
||||
kind,
|
||||
var_name: var_name.to_string(),
|
||||
param_name: param_name.to_string(),
|
||||
},
|
||||
value.range(),
|
||||
));
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
enum VarKind {
|
||||
TypeVar,
|
||||
ParamSpec,
|
||||
TypeVarTuple,
|
||||
NewType,
|
||||
}
|
||||
|
||||
impl fmt::Display for VarKind {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
VarKind::TypeVar => fmt.write_str("TypeVar"),
|
||||
VarKind::ParamSpec => fmt.write_str("ParamSpec"),
|
||||
VarKind::TypeVarTuple => fmt.write_str("TypeVarTuple"),
|
||||
VarKind::NewType => fmt.write_str("NewType"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of the `name` parameter to, e.g., a `TypeVar` constructor.
|
||||
fn param_name(value: &Expr) -> Option<&str> {
|
||||
// Handle both `TypeVar("T")` and `TypeVar(name="T")`.
|
||||
let call = value.as_call_expr()?;
|
||||
let name_param = call
|
||||
.keywords
|
||||
.iter()
|
||||
.find(|keyword| {
|
||||
keyword
|
||||
.arg
|
||||
.as_ref()
|
||||
.map_or(false, |keyword| keyword.as_str() == "name")
|
||||
})
|
||||
.map(|keyword| &keyword.value)
|
||||
.or_else(|| call.args.get(0))?;
|
||||
if let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(name),
|
||||
..
|
||||
}) = &name_param
|
||||
{
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/pylint/mod.rs
|
||||
---
|
||||
type_param_name_mismatch.py:5:5: PLC0132 `TypeVar` name `T` does not match assigned variable name `X`
|
||||
|
|
||||
3 | # Errors.
|
||||
4 |
|
||||
5 | X = TypeVar("T")
|
||||
| ^^^^^^^^^^^^ PLC0132
|
||||
6 | X = TypeVar(name="T")
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:6:5: PLC0132 `TypeVar` name `T` does not match assigned variable name `X`
|
||||
|
|
||||
5 | X = TypeVar("T")
|
||||
6 | X = TypeVar(name="T")
|
||||
| ^^^^^^^^^^^^^^^^^ PLC0132
|
||||
7 |
|
||||
8 | Y = ParamSpec("T")
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:8:5: PLC0132 `ParamSpec` name `T` does not match assigned variable name `Y`
|
||||
|
|
||||
6 | X = TypeVar(name="T")
|
||||
7 |
|
||||
8 | Y = ParamSpec("T")
|
||||
| ^^^^^^^^^^^^^^ PLC0132
|
||||
9 | Y = ParamSpec(name="T")
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:9:5: PLC0132 `ParamSpec` name `T` does not match assigned variable name `Y`
|
||||
|
|
||||
8 | Y = ParamSpec("T")
|
||||
9 | Y = ParamSpec(name="T")
|
||||
| ^^^^^^^^^^^^^^^^^^^ PLC0132
|
||||
10 |
|
||||
11 | Z = NewType("T", int)
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:11:5: PLC0132 `NewType` name `T` does not match assigned variable name `Z`
|
||||
|
|
||||
9 | Y = ParamSpec(name="T")
|
||||
10 |
|
||||
11 | Z = NewType("T", int)
|
||||
| ^^^^^^^^^^^^^^^^^ PLC0132
|
||||
12 | Z = NewType(name="T", tp=int)
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:12:5: PLC0132 `NewType` name `T` does not match assigned variable name `Z`
|
||||
|
|
||||
11 | Z = NewType("T", int)
|
||||
12 | Z = NewType(name="T", tp=int)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ PLC0132
|
||||
13 |
|
||||
14 | Ws = TypeVarTuple("Ts")
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:14:6: PLC0132 `TypeVarTuple` name `Ts` does not match assigned variable name `Ws`
|
||||
|
|
||||
12 | Z = NewType(name="T", tp=int)
|
||||
13 |
|
||||
14 | Ws = TypeVarTuple("Ts")
|
||||
| ^^^^^^^^^^^^^^^^^^ PLC0132
|
||||
15 | Ws = TypeVarTuple(name="Ts")
|
||||
|
|
||||
|
||||
type_param_name_mismatch.py:15:6: PLC0132 `TypeVarTuple` name `Ts` does not match assigned variable name `Ws`
|
||||
|
|
||||
14 | Ws = TypeVarTuple("Ts")
|
||||
15 | Ws = TypeVarTuple(name="Ts")
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PLC0132
|
||||
16 |
|
||||
17 | # Non-errors.
|
||||
|
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ mod tests {
|
||||
#[test_case(Rule::MutableDataclassDefault, Path::new("RUF008.py"))]
|
||||
#[test_case(Rule::PairwiseOverZipped, Path::new("RUF007.py"))]
|
||||
#[test_case(Rule::StaticKeyDictComprehension, Path::new("RUF011.py"))]
|
||||
#[cfg_attr(
|
||||
feature = "unreachable-code",
|
||||
test_case(Rule::UnreachableCode, Path::new("RUF014.py"))
|
||||
)]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
|
||||
@@ -9,6 +9,8 @@ pub(crate) use mutable_class_default::*;
|
||||
pub(crate) use mutable_dataclass_default::*;
|
||||
pub(crate) use pairwise_over_zipped::*;
|
||||
pub(crate) use static_key_dict_comprehension::*;
|
||||
#[cfg(feature = "unreachable-code")]
|
||||
pub(crate) use unreachable::*;
|
||||
pub(crate) use unused_noqa::*;
|
||||
|
||||
mod ambiguous_unicode_character;
|
||||
@@ -24,6 +26,8 @@ mod mutable_class_default;
|
||||
mod mutable_dataclass_default;
|
||||
mod pairwise_over_zipped;
|
||||
mod static_key_dict_comprehension;
|
||||
#[cfg(feature = "unreachable-code")]
|
||||
pub(crate) mod unreachable;
|
||||
mod unused_noqa;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
assert True
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1[["Exception raised"]]
|
||||
block2["assert True\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
assert False
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1[["Exception raised"]]
|
||||
block2["assert False\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
assert True, "oops"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1[["Exception raised"]]
|
||||
block2["assert True, #quot;oops#quot;\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
assert False, "oops"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1[["Exception raised"]]
|
||||
block2["assert False, #quot;oops#quot;\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(5):
|
||||
print(i)
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["print(i)\n"]
|
||||
block2["async for i in range(5):
|
||||
print(i)\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(5)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(20):
|
||||
print(i)
|
||||
else:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["print(i)\n"]
|
||||
block1["return 0\n"]
|
||||
block2["async for i in range(20):
|
||||
print(i)
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(20)" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(10):
|
||||
if i == 5:
|
||||
return 1
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if i == 5:
|
||||
return 1\n"]
|
||||
block3["async for i in range(10):
|
||||
if i == 5:
|
||||
return 1\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "range(10)" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "i == 5" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(111):
|
||||
if i == 5:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 2
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 2\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if i == 5:
|
||||
return 1\n"]
|
||||
block3["return 0\n"]
|
||||
block4["async for i in range(111):
|
||||
if i == 5:
|
||||
return 1
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "range(111)" --> block2
|
||||
block4 -- "else" --> block3
|
||||
block3 --> return
|
||||
block2 -- "i == 5" --> block1
|
||||
block2 -- "else" --> block4
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 4
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(12):
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["async for i in range(12):
|
||||
continue\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(12)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 5
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(1110):
|
||||
if True:
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["if True:
|
||||
continue\n"]
|
||||
block3["async for i in range(1110):
|
||||
if True:
|
||||
continue\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "range(1110)" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> block3
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 6
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(13):
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["async for i in range(13):
|
||||
break\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(13)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 7
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
async for i in range(1110):
|
||||
if True:
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["if True:
|
||||
break\n"]
|
||||
block3["async for i in range(1110):
|
||||
if True:
|
||||
break\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "range(1110)" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(5):
|
||||
print(i)
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["print(i)\n"]
|
||||
block2["for i in range(5):
|
||||
print(i)\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(5)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(20):
|
||||
print(i)
|
||||
else:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["print(i)\n"]
|
||||
block1["return 0\n"]
|
||||
block2["for i in range(20):
|
||||
print(i)
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(20)" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
return 1
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if i == 5:
|
||||
return 1\n"]
|
||||
block3["for i in range(10):
|
||||
if i == 5:
|
||||
return 1\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "range(10)" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "i == 5" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(111):
|
||||
if i == 5:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 2
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 2\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if i == 5:
|
||||
return 1\n"]
|
||||
block3["return 0\n"]
|
||||
block4["for i in range(111):
|
||||
if i == 5:
|
||||
return 1
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "range(111)" --> block2
|
||||
block4 -- "else" --> block3
|
||||
block3 --> return
|
||||
block2 -- "i == 5" --> block1
|
||||
block2 -- "else" --> block4
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 4
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(12):
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["for i in range(12):
|
||||
continue\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(12)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 5
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(1110):
|
||||
if True:
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["if True:
|
||||
continue\n"]
|
||||
block3["for i in range(1110):
|
||||
if True:
|
||||
continue\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "range(1110)" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> block3
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 6
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(13):
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["for i in range(13):
|
||||
break\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "range(13)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 7
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
for i in range(1110):
|
||||
if True:
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["if True:
|
||||
break\n"]
|
||||
block3["for i in range(1110):
|
||||
if True:
|
||||
break\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "range(1110)" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,535 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["return 0\n"]
|
||||
block2["if False:
|
||||
return 0\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if True:
|
||||
return 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if False:
|
||||
return 0
|
||||
else:
|
||||
return 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["return 0\n"]
|
||||
block2["if True:
|
||||
return 1
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 4
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
return "unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable#quot;\n"]
|
||||
block1["return 0\n"]
|
||||
block2["return 1\n"]
|
||||
block3["if False:
|
||||
return 0
|
||||
else:
|
||||
return 1\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "False" --> block1
|
||||
block3 -- "else" --> block2
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 5
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return "unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable#quot;\n"]
|
||||
block1["return 1\n"]
|
||||
block2["return 0\n"]
|
||||
block3["if True:
|
||||
return 1
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "True" --> block1
|
||||
block3 -- "else" --> block2
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 6
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
if True:
|
||||
return 1
|
||||
return 2
|
||||
else:
|
||||
return 3
|
||||
return "unreachable2"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable2#quot;\n"]
|
||||
block1["return 2\n"]
|
||||
block2["return 1\n"]
|
||||
block3["if True:
|
||||
return 1\n"]
|
||||
block4["return 3\n"]
|
||||
block5["if True:
|
||||
if True:
|
||||
return 1
|
||||
return 2
|
||||
else:
|
||||
return 3\n"]
|
||||
|
||||
start --> block5
|
||||
block5 -- "True" --> block3
|
||||
block5 -- "else" --> block4
|
||||
block4 --> return
|
||||
block3 -- "True" --> block2
|
||||
block3 -- "else" --> block1
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 7
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if False:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["return 0\n"]
|
||||
block2["if False:
|
||||
return 0\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 8
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["return 1\n"]
|
||||
block2["if True:
|
||||
return 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 9
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
return 1
|
||||
elif False:
|
||||
return 2
|
||||
else:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["return 2\n"]
|
||||
block2["return 0\n"]
|
||||
block3["elif False:
|
||||
return 2
|
||||
else:
|
||||
return 0\n"]
|
||||
block4["if True:
|
||||
return 1
|
||||
elif False:
|
||||
return 2
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "True" --> block0
|
||||
block4 -- "else" --> block3
|
||||
block3 -- "False" --> block1
|
||||
block3 -- "else" --> block2
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 10
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if False:
|
||||
return 1
|
||||
elif True:
|
||||
return 2
|
||||
else:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["return 2\n"]
|
||||
block2["return 0\n"]
|
||||
block3["elif True:
|
||||
return 2
|
||||
else:
|
||||
return 0\n"]
|
||||
block4["if False:
|
||||
return 1
|
||||
elif True:
|
||||
return 2
|
||||
else:
|
||||
return 0\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "False" --> block0
|
||||
block4 -- "else" --> block3
|
||||
block3 -- "True" --> block1
|
||||
block3 -- "else" --> block2
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 11
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if True:
|
||||
if False:
|
||||
return 0
|
||||
elif True:
|
||||
return 1
|
||||
else:
|
||||
return 2
|
||||
return 3
|
||||
elif True:
|
||||
return 4
|
||||
else:
|
||||
return 5
|
||||
return 6
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 6\n"]
|
||||
block1["return 3\n"]
|
||||
block2["return 0\n"]
|
||||
block3["return 1\n"]
|
||||
block4["return 2\n"]
|
||||
block5["elif True:
|
||||
return 1
|
||||
else:
|
||||
return 2\n"]
|
||||
block6["if False:
|
||||
return 0
|
||||
elif True:
|
||||
return 1
|
||||
else:
|
||||
return 2\n"]
|
||||
block7["return 4\n"]
|
||||
block8["return 5\n"]
|
||||
block9["elif True:
|
||||
return 4
|
||||
else:
|
||||
return 5\n"]
|
||||
block10["if True:
|
||||
if False:
|
||||
return 0
|
||||
elif True:
|
||||
return 1
|
||||
else:
|
||||
return 2
|
||||
return 3
|
||||
elif True:
|
||||
return 4
|
||||
else:
|
||||
return 5\n"]
|
||||
|
||||
start --> block10
|
||||
block10 -- "True" --> block6
|
||||
block10 -- "else" --> block9
|
||||
block9 -- "True" --> block7
|
||||
block9 -- "else" --> block8
|
||||
block8 --> return
|
||||
block7 --> return
|
||||
block6 -- "False" --> block2
|
||||
block6 -- "else" --> block5
|
||||
block5 -- "True" --> block3
|
||||
block5 -- "else" --> block4
|
||||
block4 --> return
|
||||
block3 --> return
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 12
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
if False:
|
||||
return "unreached"
|
||||
elif False:
|
||||
return "also unreached"
|
||||
return "reached"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;reached#quot;\n"]
|
||||
block1["return #quot;unreached#quot;\n"]
|
||||
block2["return #quot;also unreached#quot;\n"]
|
||||
block3["elif False:
|
||||
return #quot;also unreached#quot;\n"]
|
||||
block4["if False:
|
||||
return #quot;unreached#quot;
|
||||
elif False:
|
||||
return #quot;also unreached#quot;\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "False" --> block1
|
||||
block4 -- "else" --> block3
|
||||
block3 -- "False" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 13
|
||||
### Source
|
||||
```python
|
||||
def func(self, obj: BytesRep) -> bytes:
|
||||
data = obj["data"]
|
||||
|
||||
if isinstance(data, str):
|
||||
return base64.b64decode(data)
|
||||
elif isinstance(data, Buffer):
|
||||
buffer = data
|
||||
else:
|
||||
id = data["id"]
|
||||
|
||||
if id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f"can't resolve buffer '{id}'")
|
||||
|
||||
return buffer.data
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return buffer.data\n"]
|
||||
block1["return base64.b64decode(data)\n"]
|
||||
block2["buffer = data\n"]
|
||||
block3["buffer = self._buffers[id]\n"]
|
||||
block4["self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
|
||||
block5["id = data[#quot;id#quot;]\nif id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
|
||||
block6["elif isinstance(data, Buffer):
|
||||
buffer = data
|
||||
else:
|
||||
id = data[#quot;id#quot;]
|
||||
|
||||
if id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
|
||||
block7["data = obj[#quot;data#quot;]\nif isinstance(data, str):
|
||||
return base64.b64decode(data)
|
||||
elif isinstance(data, Buffer):
|
||||
buffer = data
|
||||
else:
|
||||
id = data[#quot;id#quot;]
|
||||
|
||||
if id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f#quot;can't resolve buffer '{id}'#quot;)\n"]
|
||||
|
||||
start --> block7
|
||||
block7 -- "isinstance(data, str)" --> block1
|
||||
block7 -- "else" --> block6
|
||||
block6 -- "isinstance(data, Buffer)" --> block2
|
||||
block6 -- "else" --> block5
|
||||
block5 -- "id in self._buffers" --> block3
|
||||
block5 -- "else" --> block4
|
||||
block4 --> block0
|
||||
block3 --> block0
|
||||
block2 --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,776 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
match status:
|
||||
case _:
|
||||
return 0
|
||||
return "unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable#quot;\n"]
|
||||
block1["return 0\n"]
|
||||
block2["match status:
|
||||
case _:
|
||||
return 0\n"]
|
||||
|
||||
start --> block2
|
||||
block2 --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
match status:
|
||||
case 1:
|
||||
return 1
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 1\n"]
|
||||
block2["match status:
|
||||
case 1:
|
||||
return 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "case 1" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
match status:
|
||||
case 1:
|
||||
return 1
|
||||
case _:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["match status:
|
||||
case 1:
|
||||
return 1
|
||||
case _:
|
||||
return 0\n"]
|
||||
block2["return 1\n"]
|
||||
block3["match status:
|
||||
case 1:
|
||||
return 1
|
||||
case _:
|
||||
return 0\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "case 1" --> block2
|
||||
block3 -- "else" --> block1
|
||||
block2 --> return
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5
|
||||
return 6
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 6\n"]
|
||||
block1["return 5\n"]
|
||||
block2["match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "case 1 | 2 | 3" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 4
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5
|
||||
case _:
|
||||
return 10
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 10\n"]
|
||||
block2["match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5
|
||||
case _:
|
||||
return 10\n"]
|
||||
block3["return 5\n"]
|
||||
block4["match status:
|
||||
case 1 | 2 | 3:
|
||||
return 5
|
||||
case _:
|
||||
return 10\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "case 1 | 2 | 3" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> return
|
||||
block2 --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 5
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
match status:
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
case 1:
|
||||
return "1 again"
|
||||
case _:
|
||||
return 3
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 3\n"]
|
||||
block1["match status:
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
case 1:
|
||||
return #quot;1 again#quot;
|
||||
case _:
|
||||
return 3\n"]
|
||||
block2["return #quot;1 again#quot;\n"]
|
||||
block3["match status:
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
case 1:
|
||||
return #quot;1 again#quot;
|
||||
case _:
|
||||
return 3\n"]
|
||||
block4["return 1\n"]
|
||||
block5["match status:
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
case 1:
|
||||
return #quot;1 again#quot;
|
||||
case _:
|
||||
return 3\n"]
|
||||
block6["return 0\n"]
|
||||
block7["match status:
|
||||
case 0:
|
||||
return 0
|
||||
case 1:
|
||||
return 1
|
||||
case 1:
|
||||
return #quot;1 again#quot;
|
||||
case _:
|
||||
return 3\n"]
|
||||
|
||||
start --> block7
|
||||
block7 -- "case 0" --> block6
|
||||
block7 -- "else" --> block5
|
||||
block6 --> return
|
||||
block5 -- "case 1" --> block4
|
||||
block5 -- "else" --> block3
|
||||
block4 --> return
|
||||
block3 -- "case 1" --> block2
|
||||
block3 -- "else" --> block1
|
||||
block2 --> return
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 6
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
i = 0
|
||||
match status, i:
|
||||
case _, _:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["return 0\n"]
|
||||
block2["match status, i:
|
||||
case _, _:
|
||||
return 0\n"]
|
||||
block3["i = 0\n"]
|
||||
|
||||
start --> block3
|
||||
block3 --> block2
|
||||
block2 -- "case _, _" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 7
|
||||
### Source
|
||||
```python
|
||||
def func(status):
|
||||
i = 0
|
||||
match status, i:
|
||||
case _, 0:
|
||||
return 0
|
||||
case _, 2:
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["return 0\n"]
|
||||
block2["match status, i:
|
||||
case _, 0:
|
||||
return 0
|
||||
case _, 2:
|
||||
return 0\n"]
|
||||
block3["return 0\n"]
|
||||
block4["match status, i:
|
||||
case _, 0:
|
||||
return 0
|
||||
case _, 2:
|
||||
return 0\n"]
|
||||
block5["i = 0\n"]
|
||||
|
||||
start --> block5
|
||||
block5 --> block4
|
||||
block4 -- "case _, 0" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> return
|
||||
block2 -- "case _, 2" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 8
|
||||
### Source
|
||||
```python
|
||||
def func(point):
|
||||
match point:
|
||||
case (0, 0):
|
||||
print("Origin")
|
||||
case _:
|
||||
raise ValueError("oops")
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["raise ValueError(#quot;oops#quot;)\n"]
|
||||
block2["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;oops#quot;)\n"]
|
||||
block3["print(#quot;Origin#quot;)\n"]
|
||||
block4["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;oops#quot;)\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "case (0, 0)" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> block0
|
||||
block2 --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 9
|
||||
### Source
|
||||
```python
|
||||
def func(point):
|
||||
match point:
|
||||
case (0, 0):
|
||||
print("Origin")
|
||||
case (0, y):
|
||||
print(f"Y={y}")
|
||||
case (x, 0):
|
||||
print(f"X={x}")
|
||||
case (x, y):
|
||||
print(f"X={x}, Y={y}")
|
||||
case _:
|
||||
raise ValueError("Not a point")
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["raise ValueError(#quot;Not a point#quot;)\n"]
|
||||
block2["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case (0, y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case (x, 0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case (x, y):
|
||||
print(f#quot;X={x}, Y={y}#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;Not a point#quot;)\n"]
|
||||
block3["print(f#quot;X={x}, Y={y}#quot;)\n"]
|
||||
block4["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case (0, y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case (x, 0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case (x, y):
|
||||
print(f#quot;X={x}, Y={y}#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;Not a point#quot;)\n"]
|
||||
block5["print(f#quot;X={x}#quot;)\n"]
|
||||
block6["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case (0, y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case (x, 0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case (x, y):
|
||||
print(f#quot;X={x}, Y={y}#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;Not a point#quot;)\n"]
|
||||
block7["print(f#quot;Y={y}#quot;)\n"]
|
||||
block8["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case (0, y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case (x, 0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case (x, y):
|
||||
print(f#quot;X={x}, Y={y}#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;Not a point#quot;)\n"]
|
||||
block9["print(#quot;Origin#quot;)\n"]
|
||||
block10["match point:
|
||||
case (0, 0):
|
||||
print(#quot;Origin#quot;)
|
||||
case (0, y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case (x, 0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case (x, y):
|
||||
print(f#quot;X={x}, Y={y}#quot;)
|
||||
case _:
|
||||
raise ValueError(#quot;Not a point#quot;)\n"]
|
||||
|
||||
start --> block10
|
||||
block10 -- "case (0, 0)" --> block9
|
||||
block10 -- "else" --> block8
|
||||
block9 --> block0
|
||||
block8 -- "case (0, y)" --> block7
|
||||
block8 -- "else" --> block6
|
||||
block7 --> block0
|
||||
block6 -- "case (x, 0)" --> block5
|
||||
block6 -- "else" --> block4
|
||||
block5 --> block0
|
||||
block4 -- "case (x, y)" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> block0
|
||||
block2 --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 10
|
||||
### Source
|
||||
```python
|
||||
def where_is(point):
|
||||
class Point:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
match point:
|
||||
case Point(x=0, y=0):
|
||||
print("Origin")
|
||||
case Point(x=0, y=y):
|
||||
print(f"Y={y}")
|
||||
case Point(x=x, y=0):
|
||||
print(f"X={x}")
|
||||
case Point():
|
||||
print("Somewhere else")
|
||||
case _:
|
||||
print("Not a point")
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["print(#quot;Not a point#quot;)\n"]
|
||||
block2["match point:
|
||||
case Point(x=0, y=0):
|
||||
print(#quot;Origin#quot;)
|
||||
case Point(x=0, y=y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case Point(x=x, y=0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case Point():
|
||||
print(#quot;Somewhere else#quot;)
|
||||
case _:
|
||||
print(#quot;Not a point#quot;)\n"]
|
||||
block3["print(#quot;Somewhere else#quot;)\n"]
|
||||
block4["match point:
|
||||
case Point(x=0, y=0):
|
||||
print(#quot;Origin#quot;)
|
||||
case Point(x=0, y=y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case Point(x=x, y=0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case Point():
|
||||
print(#quot;Somewhere else#quot;)
|
||||
case _:
|
||||
print(#quot;Not a point#quot;)\n"]
|
||||
block5["print(f#quot;X={x}#quot;)\n"]
|
||||
block6["match point:
|
||||
case Point(x=0, y=0):
|
||||
print(#quot;Origin#quot;)
|
||||
case Point(x=0, y=y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case Point(x=x, y=0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case Point():
|
||||
print(#quot;Somewhere else#quot;)
|
||||
case _:
|
||||
print(#quot;Not a point#quot;)\n"]
|
||||
block7["print(f#quot;Y={y}#quot;)\n"]
|
||||
block8["match point:
|
||||
case Point(x=0, y=0):
|
||||
print(#quot;Origin#quot;)
|
||||
case Point(x=0, y=y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case Point(x=x, y=0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case Point():
|
||||
print(#quot;Somewhere else#quot;)
|
||||
case _:
|
||||
print(#quot;Not a point#quot;)\n"]
|
||||
block9["print(#quot;Origin#quot;)\n"]
|
||||
block10["match point:
|
||||
case Point(x=0, y=0):
|
||||
print(#quot;Origin#quot;)
|
||||
case Point(x=0, y=y):
|
||||
print(f#quot;Y={y}#quot;)
|
||||
case Point(x=x, y=0):
|
||||
print(f#quot;X={x}#quot;)
|
||||
case Point():
|
||||
print(#quot;Somewhere else#quot;)
|
||||
case _:
|
||||
print(#quot;Not a point#quot;)\n"]
|
||||
block11["class Point:
|
||||
x: int
|
||||
y: int\n"]
|
||||
|
||||
start --> block11
|
||||
block11 --> block10
|
||||
block10 -- "case Point(x=0, y=0)" --> block9
|
||||
block10 -- "else" --> block8
|
||||
block9 --> block0
|
||||
block8 -- "case Point(x=0, y=y)" --> block7
|
||||
block8 -- "else" --> block6
|
||||
block7 --> block0
|
||||
block6 -- "case Point(x=x, y=0)" --> block5
|
||||
block6 -- "else" --> block4
|
||||
block5 --> block0
|
||||
block4 -- "case Point()" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> block0
|
||||
block2 --> block1
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 11
|
||||
### Source
|
||||
```python
|
||||
def func(points):
|
||||
match points:
|
||||
case []:
|
||||
print("No points")
|
||||
case [Point(0, 0)]:
|
||||
print("The origin")
|
||||
case [Point(x, y)]:
|
||||
print(f"Single point {x}, {y}")
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f"Two on the Y axis at {y1}, {y2}")
|
||||
case _:
|
||||
print("Something else")
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["print(#quot;Something else#quot;)\n"]
|
||||
block2["match points:
|
||||
case []:
|
||||
print(#quot;No points#quot;)
|
||||
case [Point(0, 0)]:
|
||||
print(#quot;The origin#quot;)
|
||||
case [Point(x, y)]:
|
||||
print(f#quot;Single point {x}, {y}#quot;)
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
|
||||
case _:
|
||||
print(#quot;Something else#quot;)\n"]
|
||||
block3["print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)\n"]
|
||||
block4["match points:
|
||||
case []:
|
||||
print(#quot;No points#quot;)
|
||||
case [Point(0, 0)]:
|
||||
print(#quot;The origin#quot;)
|
||||
case [Point(x, y)]:
|
||||
print(f#quot;Single point {x}, {y}#quot;)
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
|
||||
case _:
|
||||
print(#quot;Something else#quot;)\n"]
|
||||
block5["print(f#quot;Single point {x}, {y}#quot;)\n"]
|
||||
block6["match points:
|
||||
case []:
|
||||
print(#quot;No points#quot;)
|
||||
case [Point(0, 0)]:
|
||||
print(#quot;The origin#quot;)
|
||||
case [Point(x, y)]:
|
||||
print(f#quot;Single point {x}, {y}#quot;)
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
|
||||
case _:
|
||||
print(#quot;Something else#quot;)\n"]
|
||||
block7["print(#quot;The origin#quot;)\n"]
|
||||
block8["match points:
|
||||
case []:
|
||||
print(#quot;No points#quot;)
|
||||
case [Point(0, 0)]:
|
||||
print(#quot;The origin#quot;)
|
||||
case [Point(x, y)]:
|
||||
print(f#quot;Single point {x}, {y}#quot;)
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
|
||||
case _:
|
||||
print(#quot;Something else#quot;)\n"]
|
||||
block9["print(#quot;No points#quot;)\n"]
|
||||
block10["match points:
|
||||
case []:
|
||||
print(#quot;No points#quot;)
|
||||
case [Point(0, 0)]:
|
||||
print(#quot;The origin#quot;)
|
||||
case [Point(x, y)]:
|
||||
print(f#quot;Single point {x}, {y}#quot;)
|
||||
case [Point(0, y1), Point(0, y2)]:
|
||||
print(f#quot;Two on the Y axis at {y1}, {y2}#quot;)
|
||||
case _:
|
||||
print(#quot;Something else#quot;)\n"]
|
||||
|
||||
start --> block10
|
||||
block10 -- "case []" --> block9
|
||||
block10 -- "else" --> block8
|
||||
block9 --> block0
|
||||
block8 -- "case [Point(0, 0)]" --> block7
|
||||
block8 -- "else" --> block6
|
||||
block7 --> block0
|
||||
block6 -- "case [Point(x, y)]" --> block5
|
||||
block6 -- "else" --> block4
|
||||
block5 --> block0
|
||||
block4 -- "case [Point(0, y1), Point(0, y2)]" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> block0
|
||||
block2 --> block1
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 12
|
||||
### Source
|
||||
```python
|
||||
def func(point):
|
||||
match point:
|
||||
case Point(x, y) if x == y:
|
||||
print(f"Y=X at {x}")
|
||||
case Point(x, y):
|
||||
print(f"Not on the diagonal")
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["print(f#quot;Not on the diagonal#quot;)\n"]
|
||||
block2["match point:
|
||||
case Point(x, y) if x == y:
|
||||
print(f#quot;Y=X at {x}#quot;)
|
||||
case Point(x, y):
|
||||
print(f#quot;Not on the diagonal#quot;)\n"]
|
||||
block3["print(f#quot;Y=X at {x}#quot;)\n"]
|
||||
block4["match point:
|
||||
case Point(x, y) if x == y:
|
||||
print(f#quot;Y=X at {x}#quot;)
|
||||
case Point(x, y):
|
||||
print(f#quot;Not on the diagonal#quot;)\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "case Point(x, y) if x == y" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> block0
|
||||
block2 -- "case Point(x, y)" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 13
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
from enum import Enum
|
||||
class Color(Enum):
|
||||
RED = 'red'
|
||||
GREEN = 'green'
|
||||
BLUE = 'blue'
|
||||
|
||||
color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))
|
||||
|
||||
match color:
|
||||
case Color.RED:
|
||||
print("I see red!")
|
||||
case Color.GREEN:
|
||||
print("Grass is green")
|
||||
case Color.BLUE:
|
||||
print("I'm feeling the blues :(")
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["print(#quot;I'm feeling the blues :(#quot;)\n"]
|
||||
block2["match color:
|
||||
case Color.RED:
|
||||
print(#quot;I see red!#quot;)
|
||||
case Color.GREEN:
|
||||
print(#quot;Grass is green#quot;)
|
||||
case Color.BLUE:
|
||||
print(#quot;I'm feeling the blues :(#quot;)\n"]
|
||||
block3["print(#quot;Grass is green#quot;)\n"]
|
||||
block4["match color:
|
||||
case Color.RED:
|
||||
print(#quot;I see red!#quot;)
|
||||
case Color.GREEN:
|
||||
print(#quot;Grass is green#quot;)
|
||||
case Color.BLUE:
|
||||
print(#quot;I'm feeling the blues :(#quot;)\n"]
|
||||
block5["print(#quot;I see red!#quot;)\n"]
|
||||
block6["match color:
|
||||
case Color.RED:
|
||||
print(#quot;I see red!#quot;)
|
||||
case Color.GREEN:
|
||||
print(#quot;Grass is green#quot;)
|
||||
case Color.BLUE:
|
||||
print(#quot;I'm feeling the blues :(#quot;)\n"]
|
||||
block7["from enum import Enum\nclass Color(Enum):
|
||||
RED = 'red'
|
||||
GREEN = 'green'
|
||||
BLUE = 'blue'\ncolor = Color(input(#quot;Enter your choice of 'red', 'blue' or 'green': #quot;))\n"]
|
||||
|
||||
start --> block7
|
||||
block7 --> block6
|
||||
block6 -- "case Color.RED" --> block5
|
||||
block6 -- "else" --> block4
|
||||
block5 --> block0
|
||||
block4 -- "case Color.GREEN" --> block3
|
||||
block4 -- "else" --> block2
|
||||
block3 --> block0
|
||||
block2 -- "case Color.BLUE" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
raise Exception
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["raise Exception\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
raise "a glass!"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["raise #quot;a glass!#quot;\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
pass
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["pass\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
pass
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["pass\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
return
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 4
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
return 1
|
||||
return "unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable#quot;\n"]
|
||||
block1["return 1\n"]
|
||||
|
||||
start --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 5
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
i = 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["i = 0\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 6
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
i = 0
|
||||
i += 2
|
||||
return i
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["i = 0\ni += 2\nreturn i\n"]
|
||||
|
||||
start --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,527 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/rules/unreachable.rs
|
||||
description: "This is a Mermaid graph. You can use https://mermaid.live to visualize it as a diagram."
|
||||
---
|
||||
## Function 0
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while False:
|
||||
return "unreachable"
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["return #quot;unreachable#quot;\n"]
|
||||
block2["while False:
|
||||
return #quot;unreachable#quot;\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 1
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable#quot;\n"]
|
||||
block1["return 1\n"]
|
||||
block2["while False:
|
||||
return #quot;unreachable#quot;
|
||||
else:
|
||||
return 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 2
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return 1
|
||||
return "also unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;also unreachable#quot;\n"]
|
||||
block1["return #quot;unreachable#quot;\n"]
|
||||
block2["return 1\n"]
|
||||
block3["while False:
|
||||
return #quot;unreachable#quot;
|
||||
else:
|
||||
return 1\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "False" --> block1
|
||||
block3 -- "else" --> block2
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 3
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
return 1
|
||||
return "unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;unreachable#quot;\n"]
|
||||
block1["return 1\n"]
|
||||
block2["while True:
|
||||
return 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 4
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
return 1
|
||||
else:
|
||||
return "unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["return #quot;unreachable#quot;\n"]
|
||||
block2["while True:
|
||||
return 1
|
||||
else:
|
||||
return #quot;unreachable#quot;\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block0
|
||||
block2 -- "else" --> block1
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 5
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
return 1
|
||||
else:
|
||||
return "unreachable"
|
||||
return "also unreachable"
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return #quot;also unreachable#quot;\n"]
|
||||
block1["return 1\n"]
|
||||
block2["return #quot;unreachable#quot;\n"]
|
||||
block3["while True:
|
||||
return 1
|
||||
else:
|
||||
return #quot;unreachable#quot;\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "True" --> block1
|
||||
block3 -- "else" --> block2
|
||||
block2 --> return
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 6
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
i = 0
|
||||
while False:
|
||||
i += 1
|
||||
return i
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return i\n"]
|
||||
block1["i += 1\n"]
|
||||
block2["i = 0\nwhile False:
|
||||
i += 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 7
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
i = 0
|
||||
while True:
|
||||
i += 1
|
||||
return i
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return i\n"]
|
||||
block1["i += 1\n"]
|
||||
block2["i = 0\nwhile True:
|
||||
i += 1\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 8
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
pass
|
||||
return 1
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 1\n"]
|
||||
block1["pass\n"]
|
||||
block2["while True:
|
||||
pass\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 9
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
i = 0
|
||||
while True:
|
||||
if True:
|
||||
print("ok")
|
||||
i += 1
|
||||
return i
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return i\n"]
|
||||
block1["i += 1\n"]
|
||||
block2["print(#quot;ok#quot;)\n"]
|
||||
block3["if True:
|
||||
print(#quot;ok#quot;)\n"]
|
||||
block4["i = 0\nwhile True:
|
||||
if True:
|
||||
print(#quot;ok#quot;)
|
||||
i += 1\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "True" --> block3
|
||||
block4 -- "else" --> block0
|
||||
block3 -- "True" --> block2
|
||||
block3 -- "else" --> block1
|
||||
block2 --> block1
|
||||
block1 --> block4
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 10
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
i = 0
|
||||
while True:
|
||||
if False:
|
||||
print("ok")
|
||||
i += 1
|
||||
return i
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return i\n"]
|
||||
block1["i += 1\n"]
|
||||
block2["print(#quot;ok#quot;)\n"]
|
||||
block3["if False:
|
||||
print(#quot;ok#quot;)\n"]
|
||||
block4["i = 0\nwhile True:
|
||||
if False:
|
||||
print(#quot;ok#quot;)
|
||||
i += 1\n"]
|
||||
|
||||
start --> block4
|
||||
block4 -- "True" --> block3
|
||||
block4 -- "else" --> block0
|
||||
block3 -- "False" --> block2
|
||||
block3 -- "else" --> block1
|
||||
block2 --> block1
|
||||
block1 --> block4
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 11
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
if True:
|
||||
return 1
|
||||
return 0
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0["return 0\n"]
|
||||
block1["return 1\n"]
|
||||
block2["if True:
|
||||
return 1\n"]
|
||||
block3["while True:
|
||||
if True:
|
||||
return 1\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "True" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> return
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 12
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["while True:
|
||||
continue\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 13
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while False:
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["while False:
|
||||
continue\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block2
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 14
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["while True:
|
||||
break\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 15
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while False:
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["while False:
|
||||
break\n"]
|
||||
|
||||
start --> block2
|
||||
block2 -- "False" --> block1
|
||||
block2 -- "else" --> block0
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 16
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
if True:
|
||||
continue
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["continue\n"]
|
||||
block2["if True:
|
||||
continue\n"]
|
||||
block3["while True:
|
||||
if True:
|
||||
continue\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "True" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> block3
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
## Function 17
|
||||
### Source
|
||||
```python
|
||||
def func():
|
||||
while True:
|
||||
if True:
|
||||
break
|
||||
```
|
||||
|
||||
### Control Flow Graph
|
||||
```mermaid
|
||||
flowchart TD
|
||||
start(("Start"))
|
||||
return(("End"))
|
||||
block0[["`*(empty)*`"]]
|
||||
block1["break\n"]
|
||||
block2["if True:
|
||||
break\n"]
|
||||
block3["while True:
|
||||
if True:
|
||||
break\n"]
|
||||
|
||||
start --> block3
|
||||
block3 -- "True" --> block2
|
||||
block3 -- "else" --> block0
|
||||
block2 -- "True" --> block1
|
||||
block2 -- "else" --> block3
|
||||
block1 --> block0
|
||||
block0 --> return
|
||||
```
|
||||
|
||||
|
||||
1101
crates/ruff/src/rules/ruff/rules/unreachable.rs
Normal file
1101
crates/ruff/src/rules/ruff/rules/unreachable.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,249 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF014.py:3:5: RUF014 Unreachable code in after_return
|
||||
|
|
||||
1 | def after_return():
|
||||
2 | return "reachable"
|
||||
3 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
4 |
|
||||
5 | async def also_works_on_async_functions():
|
||||
|
|
||||
|
||||
RUF014.py:7:5: RUF014 Unreachable code in also_works_on_async_functions
|
||||
|
|
||||
5 | async def also_works_on_async_functions():
|
||||
6 | return "reachable"
|
||||
7 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
8 |
|
||||
9 | def if_always_true():
|
||||
|
|
||||
|
||||
RUF014.py:12:5: RUF014 Unreachable code in if_always_true
|
||||
|
|
||||
10 | if True:
|
||||
11 | return "reachable"
|
||||
12 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
13 |
|
||||
14 | def if_always_false():
|
||||
|
|
||||
|
||||
RUF014.py:16:9: RUF014 Unreachable code in if_always_false
|
||||
|
|
||||
14 | def if_always_false():
|
||||
15 | if False:
|
||||
16 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
17 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:21:9: RUF014 Unreachable code in if_elif_always_false
|
||||
|
|
||||
19 | def if_elif_always_false():
|
||||
20 | if False:
|
||||
21 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
22 | elif False:
|
||||
23 | return "also unreachable"
|
||||
|
|
||||
|
||||
RUF014.py:23:9: RUF014 Unreachable code in if_elif_always_false
|
||||
|
|
||||
21 | return "unreachable"
|
||||
22 | elif False:
|
||||
23 | return "also unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
24 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:28:9: RUF014 Unreachable code in if_elif_always_true
|
||||
|
|
||||
26 | def if_elif_always_true():
|
||||
27 | if False:
|
||||
28 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
29 | elif True:
|
||||
30 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:31:5: RUF014 Unreachable code in if_elif_always_true
|
||||
|
|
||||
29 | elif True:
|
||||
30 | return "reachable"
|
||||
31 | return "also unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
32 |
|
||||
33 | def ends_with_if():
|
||||
|
|
||||
|
||||
RUF014.py:35:9: RUF014 Unreachable code in ends_with_if
|
||||
|
|
||||
33 | def ends_with_if():
|
||||
34 | if False:
|
||||
35 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
36 | else:
|
||||
37 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:42:5: RUF014 Unreachable code in infinite_loop
|
||||
|
|
||||
40 | while True:
|
||||
41 | continue
|
||||
42 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
43 |
|
||||
44 | ''' TODO: we could determine these, but we don't yet.
|
||||
|
|
||||
|
||||
RUF014.py:75:5: RUF014 Unreachable code in match_wildcard
|
||||
|
|
||||
73 | case _:
|
||||
74 | return "reachable"
|
||||
75 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
76 |
|
||||
77 | def match_case_and_wildcard(status):
|
||||
|
|
||||
|
||||
RUF014.py:83:5: RUF014 Unreachable code in match_case_and_wildcard
|
||||
|
|
||||
81 | case _:
|
||||
82 | return "reachable"
|
||||
83 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
84 |
|
||||
85 | def raise_exception():
|
||||
|
|
||||
|
||||
RUF014.py:87:5: RUF014 Unreachable code in raise_exception
|
||||
|
|
||||
85 | def raise_exception():
|
||||
86 | raise Exception
|
||||
87 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
88 |
|
||||
89 | def while_false():
|
||||
|
|
||||
|
||||
RUF014.py:91:9: RUF014 Unreachable code in while_false
|
||||
|
|
||||
89 | def while_false():
|
||||
90 | while False:
|
||||
91 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
92 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:96:9: RUF014 Unreachable code in while_false_else
|
||||
|
|
||||
94 | def while_false_else():
|
||||
95 | while False:
|
||||
96 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
97 | else:
|
||||
98 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:102:9: RUF014 Unreachable code in while_false_else_return
|
||||
|
|
||||
100 | def while_false_else_return():
|
||||
101 | while False:
|
||||
102 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
103 | else:
|
||||
104 | return "reachable"
|
||||
|
|
||||
|
||||
RUF014.py:105:5: RUF014 Unreachable code in while_false_else_return
|
||||
|
|
||||
103 | else:
|
||||
104 | return "reachable"
|
||||
105 | return "also unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
106 |
|
||||
107 | def while_true():
|
||||
|
|
||||
|
||||
RUF014.py:110:5: RUF014 Unreachable code in while_true
|
||||
|
|
||||
108 | while True:
|
||||
109 | return "reachable"
|
||||
110 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
111 |
|
||||
112 | def while_true_else():
|
||||
|
|
||||
|
||||
RUF014.py:116:9: RUF014 Unreachable code in while_true_else
|
||||
|
|
||||
114 | return "reachable"
|
||||
115 | else:
|
||||
116 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
117 |
|
||||
118 | def while_true_else_return():
|
||||
|
|
||||
|
||||
RUF014.py:122:9: RUF014 Unreachable code in while_true_else_return
|
||||
|
|
||||
120 | return "reachable"
|
||||
121 | else:
|
||||
122 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
123 | return "also unreachable"
|
||||
|
|
||||
|
||||
RUF014.py:123:5: RUF014 Unreachable code in while_true_else_return
|
||||
|
|
||||
121 | else:
|
||||
122 | return "unreachable"
|
||||
123 | return "also unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
124 |
|
||||
125 | def while_false_var_i():
|
||||
|
|
||||
|
||||
RUF014.py:128:9: RUF014 Unreachable code in while_false_var_i
|
||||
|
|
||||
126 | i = 0
|
||||
127 | while False:
|
||||
128 | i += 1
|
||||
| ^^^^^^ RUF014
|
||||
129 | return i
|
||||
|
|
||||
|
||||
RUF014.py:135:5: RUF014 Unreachable code in while_true_var_i
|
||||
|
|
||||
133 | while True:
|
||||
134 | i += 1
|
||||
135 | return i
|
||||
| ^^^^^^^^ RUF014
|
||||
136 |
|
||||
137 | def while_infinite():
|
||||
|
|
||||
|
||||
RUF014.py:140:5: RUF014 Unreachable code in while_infinite
|
||||
|
|
||||
138 | while True:
|
||||
139 | pass
|
||||
140 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
141 |
|
||||
142 | def while_if_true():
|
||||
|
|
||||
|
||||
RUF014.py:146:5: RUF014 Unreachable code in while_if_true
|
||||
|
|
||||
144 | if True:
|
||||
145 | return "reachable"
|
||||
146 | return "unreachable"
|
||||
| ^^^^^^^^^^^^^^^^^^^^ RUF014
|
||||
147 |
|
||||
148 | # Test case found in the Bokeh repository that trigger a false positive.
|
||||
|
|
||||
|
||||
|
||||
@@ -39,14 +39,18 @@ pub static EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
|
||||
FilePattern::Builtin(".git"),
|
||||
FilePattern::Builtin(".git-rewrite"),
|
||||
FilePattern::Builtin(".hg"),
|
||||
FilePattern::Builtin(".ipynb_checkpoints"),
|
||||
FilePattern::Builtin(".mypy_cache"),
|
||||
FilePattern::Builtin(".nox"),
|
||||
FilePattern::Builtin(".pants.d"),
|
||||
FilePattern::Builtin(".pyenv"),
|
||||
FilePattern::Builtin(".pytest_cache"),
|
||||
FilePattern::Builtin(".pytype"),
|
||||
FilePattern::Builtin(".ruff_cache"),
|
||||
FilePattern::Builtin(".svn"),
|
||||
FilePattern::Builtin(".tox"),
|
||||
FilePattern::Builtin(".venv"),
|
||||
FilePattern::Builtin(".vscode"),
|
||||
FilePattern::Builtin("__pypackages__"),
|
||||
FilePattern::Builtin("_build"),
|
||||
FilePattern::Builtin("buck-out"),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_cli"
|
||||
version = "0.0.276"
|
||||
version = "0.0.277"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -35,11 +35,17 @@ pub struct Args {
|
||||
pub enum Command {
|
||||
/// Run Ruff on the given files or directories (default).
|
||||
Check(CheckArgs),
|
||||
/// Explain a rule.
|
||||
/// Explain a rule (or all rules).
|
||||
#[clap(alias = "--explain")]
|
||||
#[command(group = clap::ArgGroup::new("selector").multiple(false).required(true))]
|
||||
Rule {
|
||||
#[arg(value_parser=Rule::from_code)]
|
||||
rule: Rule,
|
||||
/// Rule to explain
|
||||
#[arg(value_parser=Rule::from_code, group = "selector")]
|
||||
rule: Option<Rule>,
|
||||
|
||||
/// Explain all rules
|
||||
#[arg(long, conflicts_with = "rule", group = "selector")]
|
||||
all: bool,
|
||||
|
||||
/// Output format
|
||||
#[arg(long, value_enum, default_value = "text")]
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use std::io::{self, BufWriter, Write};
|
||||
|
||||
use anyhow::Result;
|
||||
use serde::Serialize;
|
||||
use serde::ser::SerializeSeq;
|
||||
use serde::{Serialize, Serializer};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use ruff::registry::{Linter, Rule, RuleNamespace};
|
||||
use ruff_diagnostics::AutofixKind;
|
||||
@@ -11,73 +13,106 @@ use crate::args::HelpFormat;
|
||||
#[derive(Serialize)]
|
||||
struct Explanation<'a> {
|
||||
name: &'a str,
|
||||
code: &'a str,
|
||||
code: String,
|
||||
linter: &'a str,
|
||||
summary: &'a str,
|
||||
message_formats: &'a [&'a str],
|
||||
autofix: &'a str,
|
||||
autofix: String,
|
||||
explanation: Option<&'a str>,
|
||||
nursery: bool,
|
||||
}
|
||||
|
||||
impl<'a> Explanation<'a> {
|
||||
fn from_rule(rule: &'a Rule) -> Self {
|
||||
let code = rule.noqa_code().to_string();
|
||||
let (linter, _) = Linter::parse_code(&code).unwrap();
|
||||
let autofix = rule.autofixable().to_string();
|
||||
Self {
|
||||
name: rule.as_ref(),
|
||||
code,
|
||||
linter: linter.name(),
|
||||
summary: rule.message_formats()[0],
|
||||
message_formats: rule.message_formats(),
|
||||
autofix,
|
||||
explanation: rule.explanation(),
|
||||
nursery: rule.is_nursery(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn format_rule_text(rule: Rule) -> String {
|
||||
let mut output = String::new();
|
||||
output.push_str(&format!("# {} ({})", rule.as_ref(), rule.noqa_code()));
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
|
||||
let (linter, _) = Linter::parse_code(&rule.noqa_code().to_string()).unwrap();
|
||||
output.push_str(&format!("Derived from the **{}** linter.", linter.name()));
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
|
||||
let autofix = rule.autofixable();
|
||||
if matches!(autofix, AutofixKind::Always | AutofixKind::Sometimes) {
|
||||
output.push_str(&autofix.to_string());
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
if rule.is_nursery() {
|
||||
output.push_str(&format!(
|
||||
r#"This rule is part of the **nursery**, a collection of newer lints that are
|
||||
still under development. As such, it must be enabled by explicitly selecting
|
||||
{}."#,
|
||||
rule.noqa_code()
|
||||
));
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
if let Some(explanation) = rule.explanation() {
|
||||
output.push_str(explanation.trim());
|
||||
} else {
|
||||
output.push_str("Message formats:");
|
||||
for format in rule.message_formats() {
|
||||
output.push('\n');
|
||||
output.push_str(&format!("* {format}"));
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
/// Explain a `Rule` to the user.
|
||||
pub(crate) fn rule(rule: Rule, format: HelpFormat) -> Result<()> {
|
||||
let (linter, _) = Linter::parse_code(&rule.noqa_code().to_string()).unwrap();
|
||||
let mut stdout = BufWriter::new(io::stdout().lock());
|
||||
let mut output = String::new();
|
||||
|
||||
match format {
|
||||
HelpFormat::Text => {
|
||||
output.push_str(&format!("# {} ({})", rule.as_ref(), rule.noqa_code()));
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
writeln!(stdout, "{}", format_rule_text(rule))?;
|
||||
}
|
||||
HelpFormat::Json => {
|
||||
serde_json::to_writer_pretty(stdout, &Explanation::from_rule(&rule))?;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let (linter, _) = Linter::parse_code(&rule.noqa_code().to_string()).unwrap();
|
||||
output.push_str(&format!("Derived from the **{}** linter.", linter.name()));
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
|
||||
let autofix = rule.autofixable();
|
||||
if matches!(autofix, AutofixKind::Always | AutofixKind::Sometimes) {
|
||||
output.push_str(&autofix.to_string());
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
if rule.is_nursery() {
|
||||
output.push_str(&format!(
|
||||
r#"This rule is part of the **nursery**, a collection of newer lints that are
|
||||
still under development. As such, it must be enabled by explicitly selecting
|
||||
{}."#,
|
||||
rule.noqa_code()
|
||||
));
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
}
|
||||
|
||||
if let Some(explanation) = rule.explanation() {
|
||||
output.push_str(explanation.trim());
|
||||
} else {
|
||||
output.push_str("Message formats:");
|
||||
for format in rule.message_formats() {
|
||||
output.push('\n');
|
||||
output.push_str(&format!("* {format}"));
|
||||
}
|
||||
/// Explain all rules to the user.
|
||||
pub(crate) fn rules(format: HelpFormat) -> Result<()> {
|
||||
let mut stdout = BufWriter::new(io::stdout().lock());
|
||||
match format {
|
||||
HelpFormat::Text => {
|
||||
for rule in Rule::iter() {
|
||||
writeln!(stdout, "{}", format_rule_text(rule))?;
|
||||
writeln!(stdout)?;
|
||||
}
|
||||
}
|
||||
HelpFormat::Json => {
|
||||
output.push_str(&serde_json::to_string_pretty(&Explanation {
|
||||
name: rule.as_ref(),
|
||||
code: &rule.noqa_code().to_string(),
|
||||
linter: linter.name(),
|
||||
summary: rule.message_formats()[0],
|
||||
message_formats: rule.message_formats(),
|
||||
autofix: &rule.autofixable().to_string(),
|
||||
explanation: rule.explanation(),
|
||||
})?);
|
||||
let mut serializer = serde_json::Serializer::pretty(stdout);
|
||||
let mut seq = serializer.serialize_seq(None)?;
|
||||
for rule in Rule::iter() {
|
||||
seq.serialize_element(&Explanation::from_rule(&rule))?;
|
||||
}
|
||||
seq.end()?;
|
||||
}
|
||||
};
|
||||
|
||||
writeln!(stdout, "{output}")?;
|
||||
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -134,7 +134,14 @@ quoting the executed command, along with the relevant file contents and `pyproje
|
||||
set_up_logging(&log_level)?;
|
||||
|
||||
match command {
|
||||
Command::Rule { rule, format } => commands::rule::rule(rule, format)?,
|
||||
Command::Rule { rule, all, format } => {
|
||||
if all {
|
||||
commands::rule::rules(format)?;
|
||||
}
|
||||
if let Some(rule) = rule {
|
||||
commands::rule::rule(rule, format)?;
|
||||
}
|
||||
}
|
||||
Command::Config { option } => return Ok(commands::config::config(option.as_deref())),
|
||||
Command::Linter { format } => commands::linter::linter(format)?,
|
||||
Command::Clean => commands::clean::clean(log_level)?,
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
//! checking entire repositories.
|
||||
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io::stdout;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::io::{stdout, BufWriter};
|
||||
use std::panic::catch_unwind;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::ExitCode;
|
||||
@@ -49,6 +50,9 @@ pub(crate) struct Args {
|
||||
/// Checks each project inside a directory
|
||||
#[arg(long)]
|
||||
pub(crate) multi_project: bool,
|
||||
/// Write all errors to this file in addition to stdout
|
||||
#[arg(long)]
|
||||
pub(crate) error_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Generate ourself a `try_parse_from` impl for `CheckArgs`. This is a strange way to use clap but
|
||||
@@ -69,6 +73,12 @@ pub(crate) fn main(args: &Args) -> anyhow::Result<ExitCode> {
|
||||
#[allow(clippy::print_stdout)]
|
||||
{
|
||||
print!("{}", result.display(args.format));
|
||||
println!(
|
||||
"Found {} stability errors in {} files in {:.2}s",
|
||||
result.diagnostics.len(),
|
||||
result.file_count,
|
||||
result.duration.as_secs_f32(),
|
||||
);
|
||||
}
|
||||
|
||||
result.is_success()
|
||||
@@ -114,6 +124,7 @@ fn check_multi_project(args: &Args) -> bool {
|
||||
|
||||
match check_repo(&Args {
|
||||
files: vec![path.clone()],
|
||||
error_file: args.error_file.clone(),
|
||||
..*args
|
||||
}) {
|
||||
Ok(result) => sender.send(Message::Finished { result, path }),
|
||||
@@ -126,6 +137,9 @@ fn check_multi_project(args: &Args) -> bool {
|
||||
|
||||
scope.spawn(|_| {
|
||||
let mut stdout = stdout().lock();
|
||||
let mut error_file = args.error_file.as_ref().map(|error_file| {
|
||||
BufWriter::new(File::create(error_file).expect("Couldn't open error file"))
|
||||
});
|
||||
|
||||
for message in receiver {
|
||||
match message {
|
||||
@@ -135,13 +149,19 @@ fn check_multi_project(args: &Args) -> bool {
|
||||
Message::Finished { path, result } => {
|
||||
total_errors += result.diagnostics.len();
|
||||
total_files += result.file_count;
|
||||
|
||||
writeln!(
|
||||
stdout,
|
||||
"Finished {}\n{}\n",
|
||||
"Finished {} with {} files in {:.2}s",
|
||||
path.display(),
|
||||
result.display(args.format)
|
||||
result.file_count,
|
||||
result.duration.as_secs_f32(),
|
||||
)
|
||||
.unwrap();
|
||||
write!(stdout, "{}", result.display(args.format)).unwrap();
|
||||
if let Some(error_file) = &mut error_file {
|
||||
write!(error_file, "{}", result.display(args.format)).unwrap();
|
||||
}
|
||||
all_success = all_success && result.is_success();
|
||||
}
|
||||
Message::Failed { path, error } => {
|
||||
@@ -157,8 +177,10 @@ fn check_multi_project(args: &Args) -> bool {
|
||||
|
||||
#[allow(clippy::print_stdout)]
|
||||
{
|
||||
println!("{total_errors} stability errors in {total_files} files");
|
||||
println!("Finished in {}s", duration.as_secs_f32());
|
||||
println!(
|
||||
"{total_errors} stability errors in {total_files} files in {}s",
|
||||
duration.as_secs_f32()
|
||||
);
|
||||
}
|
||||
|
||||
all_success
|
||||
@@ -295,23 +317,11 @@ struct DisplayCheckRepoResult<'a> {
|
||||
}
|
||||
|
||||
impl Display for DisplayCheckRepoResult<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let CheckRepoResult {
|
||||
duration,
|
||||
file_count,
|
||||
diagnostics,
|
||||
} = self.result;
|
||||
|
||||
for diagnostic in diagnostics {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
for diagnostic in &self.result.diagnostics {
|
||||
write!(f, "{}", diagnostic.display(self.format))?;
|
||||
}
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
"Formatting {} files twice took {:.2}s",
|
||||
file_count,
|
||||
duration.as_secs_f32()
|
||||
)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ mod tests {
|
||||
|
||||
use super::{main, Args};
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(not(feature = "unreachable-code"), test)]
|
||||
fn test_generate_json_schema() -> Result<()> {
|
||||
let mode = if env::var("RUFF_UPDATE_SCHEMA").as_deref() == Ok("1") {
|
||||
Mode::Write
|
||||
|
||||
@@ -102,10 +102,10 @@ pub(crate) fn generate() -> String {
|
||||
));
|
||||
table_out.push('\n');
|
||||
table_out.push('\n');
|
||||
generate_table(&mut table_out, prefix, &linter);
|
||||
generate_table(&mut table_out, prefix.clone().rules(), &linter);
|
||||
}
|
||||
} else {
|
||||
generate_table(&mut table_out, &linter, &linter);
|
||||
generate_table(&mut table_out, linter.rules(), &linter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,11 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn first(&self) -> Option<&T> {
|
||||
self.raw.first()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn len(&self) -> usize {
|
||||
self.raw.len()
|
||||
@@ -63,6 +68,13 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
||||
(0..self.len()).map(|n| I::new(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_enumerated(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator + '_ {
|
||||
self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
|
||||
self.raw.iter_mut()
|
||||
|
||||
@@ -155,30 +155,13 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result<TokenStream> {
|
||||
}
|
||||
|
||||
output.extend(quote! {
|
||||
impl IntoIterator for &#linter {
|
||||
type Item = Rule;
|
||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
impl #linter {
|
||||
pub fn rules(self) -> ::std::vec::IntoIter<Rule> {
|
||||
match self { #prefix_into_iter_match_arms }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
output.extend(quote! {
|
||||
impl IntoIterator for &RuleCodePrefix {
|
||||
type Item = Rule;
|
||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
#(RuleCodePrefix::#linter_idents(prefix) => prefix.into_iter(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
output.extend(quote! {
|
||||
impl RuleCodePrefix {
|
||||
pub fn parse(linter: &Linter, code: &str) -> Result<Self, crate::registry::FromCodeError> {
|
||||
@@ -188,6 +171,12 @@ pub(crate) fn map_codes(func: &ItemFn) -> syn::Result<TokenStream> {
|
||||
#(Linter::#linter_idents => RuleCodePrefix::#linter_idents(#linter_idents::from_str(code).map_err(|_| crate::registry::FromCodeError::Unknown)?),)*
|
||||
})
|
||||
}
|
||||
|
||||
pub fn rules(self) -> ::std::vec::IntoIter<Rule> {
|
||||
match self {
|
||||
#(RuleCodePrefix::#linter_idents(prefix) => prefix.clone().rules(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -344,32 +333,39 @@ fn generate_iter_impl(
|
||||
linter_to_rules: &BTreeMap<Ident, BTreeMap<String, Rule>>,
|
||||
linter_idents: &[&Ident],
|
||||
) -> TokenStream {
|
||||
let mut linter_into_iter_match_arms = quote!();
|
||||
let mut linter_rules_match_arms = quote!();
|
||||
let mut linter_all_rules_match_arms = quote!();
|
||||
for (linter, map) in linter_to_rules {
|
||||
let rule_paths = map
|
||||
.values()
|
||||
.filter(|rule| {
|
||||
// Nursery rules have to be explicitly selected, so we ignore them when looking at
|
||||
// linter-level selectors (e.g., `--select SIM`).
|
||||
!is_nursery(&rule.group)
|
||||
})
|
||||
.map(|Rule { attrs, path, .. }| {
|
||||
let rule_paths = map.values().filter(|rule| !is_nursery(&rule.group)).map(
|
||||
|Rule { attrs, path, .. }| {
|
||||
let rule_name = path.segments.last().unwrap();
|
||||
quote!(#(#attrs)* Rule::#rule_name)
|
||||
});
|
||||
linter_into_iter_match_arms.extend(quote! {
|
||||
},
|
||||
);
|
||||
linter_rules_match_arms.extend(quote! {
|
||||
Linter::#linter => vec![#(#rule_paths,)*].into_iter(),
|
||||
});
|
||||
let rule_paths = map.values().map(|Rule { attrs, path, .. }| {
|
||||
let rule_name = path.segments.last().unwrap();
|
||||
quote!(#(#attrs)* Rule::#rule_name)
|
||||
});
|
||||
linter_all_rules_match_arms.extend(quote! {
|
||||
Linter::#linter => vec![#(#rule_paths,)*].into_iter(),
|
||||
});
|
||||
}
|
||||
|
||||
quote! {
|
||||
impl IntoIterator for &Linter {
|
||||
type Item = Rule;
|
||||
type IntoIter = ::std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
impl Linter {
|
||||
/// Rules not in the nursery.
|
||||
pub fn rules(self: &Linter) -> ::std::vec::IntoIter<Rule> {
|
||||
match self {
|
||||
#linter_into_iter_match_arms
|
||||
#linter_rules_match_arms
|
||||
}
|
||||
}
|
||||
/// All rules, including those in the nursery.
|
||||
pub fn all_rules(self: &Linter) -> ::std::vec::IntoIter<Rule> {
|
||||
match self {
|
||||
#linter_all_rules_match_arms
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,11 @@ pub(super) fn generate_newtype_index(item: ItemStruct) -> syn::Result<proc_macro
|
||||
#vis #struct_token #ident(std::num::NonZeroU32)#semi_token
|
||||
|
||||
impl #ident {
|
||||
const MAX: u32 = u32::MAX - 1;
|
||||
const MAX_VALUE: u32 = u32::MAX - 1;
|
||||
const MAX: Self = Self::from_u32(Self::MAX_VALUE);
|
||||
|
||||
#vis const fn from_usize(value: usize) -> Self {
|
||||
assert!(value <= Self::MAX as usize);
|
||||
assert!(value <= Self::MAX_VALUE as usize);
|
||||
|
||||
// SAFETY:
|
||||
// * The `value < u32::MAX` guarantees that the add doesn't overflow.
|
||||
@@ -49,7 +50,7 @@ pub(super) fn generate_newtype_index(item: ItemStruct) -> syn::Result<proc_macro
|
||||
}
|
||||
|
||||
#vis const fn from_u32(value: u32) -> Self {
|
||||
assert!(value <= Self::MAX);
|
||||
assert!(value <= Self::MAX_VALUE);
|
||||
|
||||
// SAFETY:
|
||||
// * The `value < u32::MAX` guarantees that the add doesn't overflow.
|
||||
|
||||
@@ -81,3 +81,8 @@ f(
|
||||
dict()
|
||||
)
|
||||
|
||||
# Don't add a magic trailing comma when there is only one entry
|
||||
# Minimized from https://github.com/django/django/blob/7eeadc82c2f7d7a778e3bb43c34d642e6275dacf/django/contrib/admin/checks.py#L674-L681
|
||||
f(
|
||||
a.very_long_function_function_that_is_so_long_that_it_expands_the_parent_but_its_only_a_single_argument()
|
||||
)
|
||||
@@ -8,3 +8,16 @@ a2 = [ # a
|
||||
a3 = [
|
||||
# b
|
||||
]
|
||||
|
||||
# Add magic trailing comma only if there is more than one entry, but respect it if it's
|
||||
# already there
|
||||
b1 = [
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa
|
||||
]
|
||||
b2 = [
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa,
|
||||
]
|
||||
b3 = [
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa,
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa
|
||||
]
|
||||
|
||||
3
crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py
vendored
Normal file
3
crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa
|
||||
from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa
|
||||
from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd
|
||||
16
crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py
vendored
Normal file
16
crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
from a import aksjdhflsakhdflkjsadlfajkslhf
|
||||
from a import (
|
||||
aksjdhflsakhdflkjsadlfajkslhf,
|
||||
)
|
||||
from a import (
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa,
|
||||
)
|
||||
from a import (
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa,
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa,
|
||||
)
|
||||
from a import (
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd,
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd,
|
||||
)
|
||||
from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import *
|
||||
@@ -182,7 +182,10 @@ impl<'fmt, 'ast, 'buf> JoinNodesBuilder<'fmt, 'ast, 'buf> {
|
||||
pub(crate) struct JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||
result: FormatResult<()>,
|
||||
fmt: &'fmt mut PyFormatter<'ast, 'buf>,
|
||||
last_end: Option<TextSize>,
|
||||
end_of_last_entry: Option<TextSize>,
|
||||
/// We need to track whether we have more than one entry since a sole entry doesn't get a
|
||||
/// magic trailing comma even when expanded
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||
@@ -190,7 +193,8 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||
Self {
|
||||
fmt: f,
|
||||
result: Ok(()),
|
||||
last_end: None,
|
||||
end_of_last_entry: None,
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,11 +207,12 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||
T: Ranged,
|
||||
{
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.last_end.is_some() {
|
||||
if self.end_of_last_entry.is_some() {
|
||||
write!(self.fmt, [text(","), soft_line_break_or_space()])?;
|
||||
}
|
||||
|
||||
self.last_end = Some(node.end());
|
||||
self.end_of_last_entry = Some(node.end());
|
||||
self.len += 1;
|
||||
|
||||
content.fmt(self.fmt)
|
||||
});
|
||||
@@ -243,18 +248,23 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||
|
||||
pub(crate) fn finish(&mut self) -> FormatResult<()> {
|
||||
self.result.and_then(|_| {
|
||||
if let Some(last_end) = self.last_end.take() {
|
||||
if_group_breaks(&text(",")).fmt(self.fmt)?;
|
||||
|
||||
if self.fmt.options().magic_trailing_comma().is_respect()
|
||||
if let Some(last_end) = self.end_of_last_entry.take() {
|
||||
let magic_trailing_comma = self.fmt.options().magic_trailing_comma().is_respect()
|
||||
&& matches!(
|
||||
first_non_trivia_token(last_end, self.fmt.context().contents()),
|
||||
Some(Token {
|
||||
kind: TokenKind::Comma,
|
||||
..
|
||||
})
|
||||
)
|
||||
{
|
||||
);
|
||||
|
||||
// If there is a single entry, only keep the magic trailing comma, don't add it if
|
||||
// it wasn't there. If there is more than one entry, always add it.
|
||||
if magic_trailing_comma || self.len > 1 {
|
||||
if_group_breaks(&text(",")).fmt(self.fmt)?;
|
||||
}
|
||||
|
||||
if magic_trailing_comma {
|
||||
expand_parent().fmt(self.fmt)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::{write, Buffer, FormatResult};
|
||||
use crate::{AsFormat, FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::prelude::{space, text};
|
||||
use ruff_formatter::{write, Buffer, Format, FormatResult};
|
||||
use rustpython_parser::ast::Alias;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -7,6 +8,15 @@ pub struct FormatAlias;
|
||||
|
||||
impl FormatNodeRule<Alias> for FormatAlias {
|
||||
fn fmt_fields(&self, item: &Alias, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
write!(f, [not_yet_implemented(item)])
|
||||
let Alias {
|
||||
range: _,
|
||||
name,
|
||||
asname,
|
||||
} = item;
|
||||
name.format().fmt(f)?;
|
||||
if let Some(asname) = asname {
|
||||
write!(f, [space(), text("as"), space(), asname.format()])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
|
||||
use crate::{FormatNodeRule, FormattedIterExt, PyFormatter};
|
||||
use ruff_formatter::prelude::{format_args, format_with, space, text};
|
||||
use ruff_formatter::{write, Buffer, FormatResult};
|
||||
use rustpython_parser::ast::StmtImport;
|
||||
|
||||
@@ -7,6 +8,12 @@ pub struct FormatStmtImport;
|
||||
|
||||
impl FormatNodeRule<StmtImport> for FormatStmtImport {
|
||||
fn fmt_fields(&self, item: &StmtImport, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
write!(f, [not_yet_implemented(item)])
|
||||
let StmtImport { names, range: _ } = item;
|
||||
let names = format_with(|f| {
|
||||
f.join_with(&format_args![text(","), space()])
|
||||
.entries(names.iter().formatted())
|
||||
.finish()
|
||||
});
|
||||
write!(f, [text("import"), space(), names])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::{write, Buffer, FormatResult};
|
||||
use crate::builders::{optional_parentheses, PyFormatterExtensions};
|
||||
use crate::{AsFormat, FormatNodeRule, PyFormatter};
|
||||
use ruff_formatter::prelude::{dynamic_text, format_with, space, text};
|
||||
use ruff_formatter::{write, Buffer, Format, FormatResult};
|
||||
use rustpython_parser::ast::StmtImportFrom;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -7,6 +9,40 @@ pub struct FormatStmtImportFrom;
|
||||
|
||||
impl FormatNodeRule<StmtImportFrom> for FormatStmtImportFrom {
|
||||
fn fmt_fields(&self, item: &StmtImportFrom, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
write!(f, [not_yet_implemented(item)])
|
||||
let StmtImportFrom {
|
||||
module,
|
||||
names,
|
||||
range: _,
|
||||
level,
|
||||
} = item;
|
||||
|
||||
let level_str = level
|
||||
.map(|level| ".".repeat(level.to_usize()))
|
||||
.unwrap_or(String::default());
|
||||
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
text("from"),
|
||||
space(),
|
||||
dynamic_text(&level_str, None),
|
||||
module.as_ref().map(AsFormat::format),
|
||||
space(),
|
||||
text("import"),
|
||||
space(),
|
||||
]
|
||||
)?;
|
||||
if let [name] = names.as_slice() {
|
||||
// star can't be surrounded by parentheses
|
||||
if name.name.as_str() == "*" {
|
||||
return text("*").fmt(f);
|
||||
}
|
||||
}
|
||||
let names = format_with(|f| {
|
||||
f.join_comma_separated()
|
||||
.entries(names.iter().map(|name| (name, name.format())))
|
||||
.finish()
|
||||
});
|
||||
optional_parentheses(&names).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,21 +43,20 @@ def eggs() -> Union[str, int]: ...
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,32 +1,58 @@
|
||||
-from typing import Union
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+
|
||||
from typing import Union
|
||||
|
||||
+
|
||||
@bird
|
||||
-def zoo(): ...
|
||||
+def zoo():
|
||||
+ ...
|
||||
+
|
||||
+
|
||||
+class A:
|
||||
+ ...
|
||||
|
||||
-class A: ...
|
||||
|
||||
+class A:
|
||||
+ ...
|
||||
+
|
||||
+
|
||||
@bar
|
||||
class B:
|
||||
- def BMethod(self) -> None: ...
|
||||
@@ -94,14 +93,14 @@ def eggs() -> Union[str, int]: ...
|
||||
+
|
||||
+class F(A, C):
|
||||
+ ...
|
||||
+
|
||||
+
|
||||
+def spam() -> None:
|
||||
+ ...
|
||||
|
||||
-class F(A, C): ...
|
||||
|
||||
-def spam() -> None: ...
|
||||
+def spam() -> None:
|
||||
+ ...
|
||||
+
|
||||
+
|
||||
@overload
|
||||
-def spam(arg: str) -> str: ...
|
||||
+def spam(arg: str) -> str:
|
||||
@@ -120,7 +119,7 @@ def eggs() -> Union[str, int]: ...
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from typing import Union
|
||||
|
||||
|
||||
@bird
|
||||
|
||||
@@ -312,15 +312,6 @@ long_unmergable_string_with_pragma = (
|
||||
|
||||
y = "Short string"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
)
|
||||
|
||||
print(
|
||||
- "This is a really long string inside of a print statement with no extra arguments attached at the end of it."
|
||||
+ "This is a really long string inside of a print statement with no extra arguments attached at the end of it.",
|
||||
)
|
||||
|
||||
D1 = {
|
||||
@@ -70,8 +70,8 @@
|
||||
bad_split3 = (
|
||||
"What if we have inline comments on " # First Comment
|
||||
@@ -367,7 +358,7 @@ long_unmergable_string_with_pragma = (
|
||||
|
||||
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
|
||||
|
||||
@@ -165,30 +163,18 @@
|
||||
@@ -165,25 +163,13 @@
|
||||
|
||||
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
||||
|
||||
@@ -397,12 +388,6 @@ long_unmergable_string_with_pragma = (
|
||||
|
||||
some_function_call(
|
||||
"With a reallly generic name and with a really really long string that is, at some point down the line, "
|
||||
+ added
|
||||
- + " to a variable and then added to another string."
|
||||
+ + " to a variable and then added to another string.",
|
||||
)
|
||||
|
||||
some_function_call(
|
||||
@@ -212,29 +198,25 @@
|
||||
)
|
||||
|
||||
@@ -412,7 +397,7 @@ long_unmergable_string_with_pragma = (
|
||||
- " which should NOT be there."
|
||||
- ),
|
||||
+ "This is a really long string argument to a function that has a trailing comma"
|
||||
+ " which should NOT be there.",
|
||||
+ " which should NOT be there."
|
||||
)
|
||||
|
||||
func_with_bad_comma(
|
||||
@@ -421,7 +406,7 @@ long_unmergable_string_with_pragma = (
|
||||
- " which should NOT be there."
|
||||
- ), # comment after comma
|
||||
+ "This is a really long string argument to a function that has a trailing comma"
|
||||
+ " which should NOT be there.", # comment after comma
|
||||
+ " which should NOT be there." # comment after comma
|
||||
)
|
||||
|
||||
func_with_bad_parens_that_wont_fit_in_one_line(
|
||||
@@ -498,7 +483,7 @@ print(
|
||||
)
|
||||
|
||||
print(
|
||||
"This is a really long string inside of a print statement with no extra arguments attached at the end of it.",
|
||||
"This is a really long string inside of a print statement with no extra arguments attached at the end of it."
|
||||
)
|
||||
|
||||
D1 = {
|
||||
@@ -660,7 +645,7 @@ NOT_YET_IMPLEMENTED_StmtAssert
|
||||
some_function_call(
|
||||
"With a reallly generic name and with a really really long string that is, at some point down the line, "
|
||||
+ added
|
||||
+ " to a variable and then added to another string.",
|
||||
+ " to a variable and then added to another string."
|
||||
)
|
||||
|
||||
some_function_call(
|
||||
@@ -685,12 +670,12 @@ func_with_bad_comma(
|
||||
|
||||
func_with_bad_comma(
|
||||
"This is a really long string argument to a function that has a trailing comma"
|
||||
" which should NOT be there.",
|
||||
" which should NOT be there."
|
||||
)
|
||||
|
||||
func_with_bad_comma(
|
||||
"This is a really long string argument to a function that has a trailing comma"
|
||||
" which should NOT be there.", # comment after comma
|
||||
" which should NOT be there." # comment after comma
|
||||
)
|
||||
|
||||
func_with_bad_parens_that_wont_fit_in_one_line(
|
||||
|
||||
@@ -132,8 +132,7 @@ match bar1:
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,119 +1,43 @@
|
||||
-import match
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
import match
|
||||
|
||||
-match something:
|
||||
- case [a as b]:
|
||||
@@ -208,10 +207,11 @@ match bar1:
|
||||
- ),
|
||||
- ):
|
||||
- pass
|
||||
-
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
- case [a as match]:
|
||||
- pass
|
||||
-
|
||||
|
||||
- case case:
|
||||
- pass
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
@@ -220,8 +220,9 @@ match bar1:
|
||||
-match match:
|
||||
- case case:
|
||||
- pass
|
||||
-
|
||||
-
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
|
||||
-match a, *b(), c:
|
||||
- case d, *f, g:
|
||||
- pass
|
||||
@@ -236,30 +237,28 @@ match bar1:
|
||||
- pass
|
||||
- case {"maybe": something(complicated as this) as that}:
|
||||
- pass
|
||||
-
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
|
||||
-match something:
|
||||
- case 1 as a:
|
||||
- pass
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
- case 2 as b, 3 as c:
|
||||
- pass
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
- case 4 as d, (5 as e), (6 | 7 as g), *h:
|
||||
- pass
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
|
||||
-
|
||||
-match bar1:
|
||||
- case Foo(aa=Callable() as aa, bb=int()):
|
||||
- print(bar1.aa, bar1.bb)
|
||||
- case _:
|
||||
- print("no match", "\n")
|
||||
+NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
|
||||
-
|
||||
-
|
||||
-match bar1:
|
||||
- case Foo(
|
||||
- normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
|
||||
@@ -271,7 +270,7 @@ match bar1:
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import match
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ match match(
|
||||
|
||||
-match(arg) # comment
|
||||
+match(
|
||||
+ arg, # comment
|
||||
+ arg # comment
|
||||
+)
|
||||
|
||||
match()
|
||||
@@ -93,7 +93,7 @@ match match(
|
||||
|
||||
-case(arg) # comment
|
||||
+case(
|
||||
+ arg, # comment
|
||||
+ arg # comment
|
||||
+)
|
||||
|
||||
case()
|
||||
@@ -103,7 +103,7 @@ match match(
|
||||
|
||||
-re.match(something) # fast
|
||||
+re.match(
|
||||
+ something, # fast
|
||||
+ something # fast
|
||||
+)
|
||||
re.match()
|
||||
-match match():
|
||||
@@ -120,7 +120,7 @@ match match(
|
||||
NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
match(
|
||||
arg, # comment
|
||||
arg # comment
|
||||
)
|
||||
|
||||
match()
|
||||
@@ -128,7 +128,7 @@ match()
|
||||
match()
|
||||
|
||||
case(
|
||||
arg, # comment
|
||||
arg # comment
|
||||
)
|
||||
|
||||
case()
|
||||
@@ -137,7 +137,7 @@ case()
|
||||
|
||||
|
||||
re.match(
|
||||
something, # fast
|
||||
something # fast
|
||||
)
|
||||
re.match()
|
||||
NOT_YET_IMPLEMENTED_StmtMatch
|
||||
|
||||
@@ -83,31 +83,9 @@ if True:
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,40 +1,22 @@
|
||||
-import core, time, a
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
-from . import A, B, C
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
# keeps existing trailing comma
|
||||
-from foo import (
|
||||
- bar,
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
# also keeps existing structure
|
||||
-from foo import (
|
||||
- baz,
|
||||
- qux,
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
# `as` works as well
|
||||
-from foo import (
|
||||
- xyzzy as magic,
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
@@ -18,23 +18,12 @@
|
||||
xyzzy as magic,
|
||||
)
|
||||
|
||||
-a = {
|
||||
- 1,
|
||||
@@ -132,7 +110,7 @@ if True:
|
||||
nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)}
|
||||
nested_long_lines = [
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
@@ -52,10 +34,7 @@
|
||||
@@ -52,10 +41,7 @@
|
||||
y = {
|
||||
"oneple": (1,),
|
||||
}
|
||||
@@ -149,18 +127,25 @@ if True:
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import core, time, a
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from . import A, B, C
|
||||
|
||||
# keeps existing trailing comma
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from foo import (
|
||||
bar,
|
||||
)
|
||||
|
||||
# also keeps existing structure
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from foo import (
|
||||
baz,
|
||||
qux,
|
||||
)
|
||||
|
||||
# `as` works as well
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from foo import (
|
||||
xyzzy as magic,
|
||||
)
|
||||
|
||||
a = {1, 2, 3}
|
||||
b = {1, 2, 3}
|
||||
|
||||
@@ -1,347 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```py
|
||||
#!/usr/bin/env python3
|
||||
# fmt: on
|
||||
# Some license here.
|
||||
#
|
||||
# Has many lines. Many, many lines.
|
||||
# Many, many, many lines.
|
||||
"""Module docstring.
|
||||
|
||||
Possibly also many, many lines.
|
||||
"""
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
import a
|
||||
from b.c import X # some noqa comment
|
||||
|
||||
try:
|
||||
import fast
|
||||
except ImportError:
|
||||
import slow as fast
|
||||
|
||||
|
||||
# Some comment before a function.
|
||||
y = 1
|
||||
(
|
||||
# some strings
|
||||
y # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def function(default=None):
|
||||
"""Docstring comes first.
|
||||
|
||||
Possibly many lines.
|
||||
"""
|
||||
# FIXME: Some comment about why this function is crap but still in production.
|
||||
import inner_imports
|
||||
|
||||
if inner_imports.are_evil():
|
||||
# Explains why we have this if.
|
||||
# In great detail indeed.
|
||||
x = X()
|
||||
return x.method1() # type: ignore
|
||||
|
||||
# This return is also commented for some reason.
|
||||
return default
|
||||
|
||||
|
||||
# Explains why we use global state.
|
||||
GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)}
|
||||
|
||||
|
||||
# Another comment!
|
||||
# This time two lines.
|
||||
|
||||
|
||||
class Foo:
|
||||
"""Docstring for class Foo. Example from Sphinx docs."""
|
||||
|
||||
#: Doc comment for class attribute Foo.bar.
|
||||
#: It can have multiple lines.
|
||||
bar = 1
|
||||
|
||||
flox = 1.5 #: Doc comment for Foo.flox. One line only.
|
||||
|
||||
baz = 2
|
||||
"""Docstring for class attribute Foo.baz."""
|
||||
|
||||
def __init__(self):
|
||||
#: Doc comment for instance attribute qux.
|
||||
self.qux = 3
|
||||
|
||||
self.spam = 4
|
||||
"""Docstring for instance attribute spam."""
|
||||
|
||||
|
||||
#' <h1>This is pweave!</h1>
|
||||
|
||||
|
||||
@fast(really=True)
|
||||
async def wat():
|
||||
# This comment, for some reason \
|
||||
# contains a trailing backslash.
|
||||
async with X.open_async() as x: # Some more comments
|
||||
result = await x.method1()
|
||||
# Comment after ending a block.
|
||||
if result:
|
||||
print("A OK", file=sys.stdout)
|
||||
# Comment between things.
|
||||
print()
|
||||
|
||||
|
||||
# Some closing comments.
|
||||
# Maybe Vim or Emacs directives for formatting.
|
||||
# Who knows.
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -9,16 +9,16 @@
|
||||
Possibly also many, many lines.
|
||||
"""
|
||||
|
||||
-import os.path
|
||||
-import sys
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
-import a
|
||||
-from b.c import X # some noqa comment
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment
|
||||
|
||||
try:
|
||||
- import fast
|
||||
+ NOT_YET_IMPLEMENTED_StmtImport
|
||||
except ImportError:
|
||||
- import slow as fast
|
||||
+ NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
|
||||
# Some comment before a function.
|
||||
@@ -35,7 +35,7 @@
|
||||
Possibly many lines.
|
||||
"""
|
||||
# FIXME: Some comment about why this function is crap but still in production.
|
||||
- import inner_imports
|
||||
+ NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
if inner_imports.are_evil():
|
||||
# Explains why we have this if.
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
#!/usr/bin/env python3
|
||||
# fmt: on
|
||||
# Some license here.
|
||||
#
|
||||
# Has many lines. Many, many lines.
|
||||
# Many, many, many lines.
|
||||
"""Module docstring.
|
||||
|
||||
Possibly also many, many lines.
|
||||
"""
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment
|
||||
|
||||
try:
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
except ImportError:
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
|
||||
# Some comment before a function.
|
||||
y = 1
|
||||
(
|
||||
# some strings
|
||||
y # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def function(default=None):
|
||||
"""Docstring comes first.
|
||||
|
||||
Possibly many lines.
|
||||
"""
|
||||
# FIXME: Some comment about why this function is crap but still in production.
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
if inner_imports.are_evil():
|
||||
# Explains why we have this if.
|
||||
# In great detail indeed.
|
||||
x = X()
|
||||
return x.method1() # type: ignore
|
||||
|
||||
# This return is also commented for some reason.
|
||||
return default
|
||||
|
||||
|
||||
# Explains why we use global state.
|
||||
GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)}
|
||||
|
||||
|
||||
# Another comment!
|
||||
# This time two lines.
|
||||
|
||||
|
||||
class Foo:
|
||||
"""Docstring for class Foo. Example from Sphinx docs."""
|
||||
|
||||
#: Doc comment for class attribute Foo.bar.
|
||||
#: It can have multiple lines.
|
||||
bar = 1
|
||||
|
||||
flox = 1.5 #: Doc comment for Foo.flox. One line only.
|
||||
|
||||
baz = 2
|
||||
"""Docstring for class attribute Foo.baz."""
|
||||
|
||||
def __init__(self):
|
||||
#: Doc comment for instance attribute qux.
|
||||
self.qux = 3
|
||||
|
||||
self.spam = 4
|
||||
"""Docstring for instance attribute spam."""
|
||||
|
||||
|
||||
#' <h1>This is pweave!</h1>
|
||||
|
||||
|
||||
@fast(really=True)
|
||||
async def wat():
|
||||
# This comment, for some reason \
|
||||
# contains a trailing backslash.
|
||||
async with X.open_async() as x: # Some more comments
|
||||
result = await x.method1()
|
||||
# Comment after ending a block.
|
||||
if result:
|
||||
print("A OK", file=sys.stdout)
|
||||
# Comment between things.
|
||||
print()
|
||||
|
||||
|
||||
# Some closing comments.
|
||||
# Maybe Vim or Emacs directives for formatting.
|
||||
# Who knows.
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```py
|
||||
#!/usr/bin/env python3
|
||||
# fmt: on
|
||||
# Some license here.
|
||||
#
|
||||
# Has many lines. Many, many lines.
|
||||
# Many, many, many lines.
|
||||
"""Module docstring.
|
||||
|
||||
Possibly also many, many lines.
|
||||
"""
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
import a
|
||||
from b.c import X # some noqa comment
|
||||
|
||||
try:
|
||||
import fast
|
||||
except ImportError:
|
||||
import slow as fast
|
||||
|
||||
|
||||
# Some comment before a function.
|
||||
y = 1
|
||||
(
|
||||
# some strings
|
||||
y # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def function(default=None):
|
||||
"""Docstring comes first.
|
||||
|
||||
Possibly many lines.
|
||||
"""
|
||||
# FIXME: Some comment about why this function is crap but still in production.
|
||||
import inner_imports
|
||||
|
||||
if inner_imports.are_evil():
|
||||
# Explains why we have this if.
|
||||
# In great detail indeed.
|
||||
x = X()
|
||||
return x.method1() # type: ignore
|
||||
|
||||
# This return is also commented for some reason.
|
||||
return default
|
||||
|
||||
|
||||
# Explains why we use global state.
|
||||
GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)}
|
||||
|
||||
|
||||
# Another comment!
|
||||
# This time two lines.
|
||||
|
||||
|
||||
class Foo:
|
||||
"""Docstring for class Foo. Example from Sphinx docs."""
|
||||
|
||||
#: Doc comment for class attribute Foo.bar.
|
||||
#: It can have multiple lines.
|
||||
bar = 1
|
||||
|
||||
flox = 1.5 #: Doc comment for Foo.flox. One line only.
|
||||
|
||||
baz = 2
|
||||
"""Docstring for class attribute Foo.baz."""
|
||||
|
||||
def __init__(self):
|
||||
#: Doc comment for instance attribute qux.
|
||||
self.qux = 3
|
||||
|
||||
self.spam = 4
|
||||
"""Docstring for instance attribute spam."""
|
||||
|
||||
|
||||
#' <h1>This is pweave!</h1>
|
||||
|
||||
|
||||
@fast(really=True)
|
||||
async def wat():
|
||||
# This comment, for some reason \
|
||||
# contains a trailing backslash.
|
||||
async with X.open_async() as x: # Some more comments
|
||||
result = await x.method1()
|
||||
# Comment after ending a block.
|
||||
if result:
|
||||
print("A OK", file=sys.stdout)
|
||||
# Comment between things.
|
||||
print()
|
||||
|
||||
|
||||
# Some closing comments.
|
||||
# Maybe Vim or Emacs directives for formatting.
|
||||
# Who knows.
|
||||
```
|
||||
|
||||
|
||||
@@ -177,19 +177,18 @@ instruction()#comment with bad spacing
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,9 +1,5 @@
|
||||
-from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
@@ -1,8 +1,8 @@
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
- MyLovelyCompanyTeamProjectComponent, # NOT DRY
|
||||
-)
|
||||
-from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
+ MyLovelyCompanyTeamProjectComponent # NOT DRY
|
||||
)
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
- MyLovelyCompanyTeamProjectComponent as component, # DRY
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+ MyLovelyCompanyTeamProjectComponent as component # DRY
|
||||
)
|
||||
|
||||
# Please keep __all__ alphabetized within each category.
|
||||
|
||||
@@ -45,7 +41,7 @@
|
||||
@@ -45,7 +45,7 @@
|
||||
# user-defined types and objects
|
||||
Cheese,
|
||||
Cheese("Wensleydale"),
|
||||
@@ -198,7 +197,7 @@ instruction()#comment with bad spacing
|
||||
]
|
||||
|
||||
if "PYTHON" in os.environ:
|
||||
@@ -60,8 +56,12 @@
|
||||
@@ -60,8 +60,12 @@
|
||||
# Comment before function.
|
||||
def inline_comments_in_brackets_ruin_everything():
|
||||
if typedargslist:
|
||||
@@ -212,7 +211,7 @@ instruction()#comment with bad spacing
|
||||
children[0],
|
||||
body,
|
||||
children[-1], # type: ignore
|
||||
@@ -72,7 +72,11 @@
|
||||
@@ -72,7 +76,11 @@
|
||||
body,
|
||||
parameters.children[-1], # )2
|
||||
]
|
||||
@@ -225,7 +224,7 @@ instruction()#comment with bad spacing
|
||||
if (
|
||||
self._proc is not None
|
||||
# has the child process finished?
|
||||
@@ -114,25 +118,9 @@
|
||||
@@ -114,25 +122,9 @@
|
||||
# yup
|
||||
arg3=True,
|
||||
)
|
||||
@@ -254,7 +253,7 @@ instruction()#comment with bad spacing
|
||||
while True:
|
||||
if False:
|
||||
continue
|
||||
@@ -143,7 +131,10 @@
|
||||
@@ -143,7 +135,10 @@
|
||||
# let's return
|
||||
return Node(
|
||||
syms.simple_stmt,
|
||||
@@ -266,7 +265,7 @@ instruction()#comment with bad spacing
|
||||
)
|
||||
|
||||
|
||||
@@ -158,7 +149,11 @@
|
||||
@@ -158,7 +153,11 @@
|
||||
|
||||
class Test:
|
||||
def _init_host(self, parsed) -> None:
|
||||
@@ -284,8 +283,12 @@ instruction()#comment with bad spacing
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent # NOT DRY
|
||||
)
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent as component # DRY
|
||||
)
|
||||
|
||||
# Please keep __all__ alphabetized within each category.
|
||||
|
||||
|
||||
@@ -76,15 +76,6 @@ def func():
|
||||
# Capture each of the exceptions in the MultiError along with each of their causes and contexts
|
||||
if isinstance(exc_value, MultiError):
|
||||
embedded = []
|
||||
@@ -29,7 +22,7 @@
|
||||
# copy the set of _seen exceptions so that duplicates
|
||||
# shared between sub-exceptions are not omitted
|
||||
_seen=set(_seen),
|
||||
- )
|
||||
+ ),
|
||||
# This should be left alone (after)
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
@@ -114,7 +105,7 @@ def func():
|
||||
# copy the set of _seen exceptions so that duplicates
|
||||
# shared between sub-exceptions are not omitted
|
||||
_seen=set(_seen),
|
||||
),
|
||||
)
|
||||
# This should be left alone (after)
|
||||
)
|
||||
|
||||
|
||||
@@ -106,19 +106,7 @@ def foo3(list_a, list_b):
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,9 +1,5 @@
|
||||
-from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
- MyLovelyCompanyTeamProjectComponent, # NOT DRY
|
||||
-)
|
||||
-from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
- MyLovelyCompanyTeamProjectComponent as component, # DRY
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
|
||||
class C:
|
||||
@@ -58,37 +54,28 @@
|
||||
@@ -58,37 +58,28 @@
|
||||
|
||||
def foo(list_a, list_b):
|
||||
results = (
|
||||
@@ -172,8 +160,12 @@ def foo3(list_a, list_b):
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent, # NOT DRY
|
||||
)
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent as component, # DRY
|
||||
)
|
||||
|
||||
|
||||
class C:
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments5.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```py
|
||||
while True:
|
||||
if something.changed:
|
||||
do.stuff() # trailing comment
|
||||
# Comment belongs to the `if` block.
|
||||
# This one belongs to the `while` block.
|
||||
|
||||
# Should this one, too? I guess so.
|
||||
|
||||
# This one is properly standalone now.
|
||||
|
||||
for i in range(100):
|
||||
# first we do this
|
||||
if i % 33 == 0:
|
||||
break
|
||||
|
||||
# then we do this
|
||||
print(i)
|
||||
# and finally we loop around
|
||||
|
||||
with open(some_temp_file) as f:
|
||||
data = f.read()
|
||||
|
||||
try:
|
||||
with open(some_other_file) as w:
|
||||
w.write(data)
|
||||
|
||||
except OSError:
|
||||
print("problems")
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
# leading function comment
|
||||
def wat():
|
||||
...
|
||||
# trailing function comment
|
||||
|
||||
|
||||
# SECTION COMMENT
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading 3
|
||||
@deco3
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading function comment
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# Note: this is fixed in
|
||||
# Preview.empty_lines_before_class_or_def_with_leading_comments.
|
||||
# In the current style, the user will have to split those lines by hand.
|
||||
some_instruction
|
||||
|
||||
|
||||
# This comment should be split from `some_instruction` by two lines but isn't.
|
||||
def g():
|
||||
...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -27,7 +27,7 @@
|
||||
except OSError:
|
||||
print("problems")
|
||||
|
||||
-import sys
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
|
||||
# leading function comment
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
while True:
|
||||
if something.changed:
|
||||
do.stuff() # trailing comment
|
||||
# Comment belongs to the `if` block.
|
||||
# This one belongs to the `while` block.
|
||||
|
||||
# Should this one, too? I guess so.
|
||||
|
||||
# This one is properly standalone now.
|
||||
|
||||
for i in range(100):
|
||||
# first we do this
|
||||
if i % 33 == 0:
|
||||
break
|
||||
|
||||
# then we do this
|
||||
print(i)
|
||||
# and finally we loop around
|
||||
|
||||
with open(some_temp_file) as f:
|
||||
data = f.read()
|
||||
|
||||
try:
|
||||
with open(some_other_file) as w:
|
||||
w.write(data)
|
||||
|
||||
except OSError:
|
||||
print("problems")
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
|
||||
# leading function comment
|
||||
def wat():
|
||||
...
|
||||
# trailing function comment
|
||||
|
||||
|
||||
# SECTION COMMENT
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading 3
|
||||
@deco3
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading function comment
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# Note: this is fixed in
|
||||
# Preview.empty_lines_before_class_or_def_with_leading_comments.
|
||||
# In the current style, the user will have to split those lines by hand.
|
||||
some_instruction
|
||||
|
||||
|
||||
# This comment should be split from `some_instruction` by two lines but isn't.
|
||||
def g():
|
||||
...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```py
|
||||
while True:
|
||||
if something.changed:
|
||||
do.stuff() # trailing comment
|
||||
# Comment belongs to the `if` block.
|
||||
# This one belongs to the `while` block.
|
||||
|
||||
# Should this one, too? I guess so.
|
||||
|
||||
# This one is properly standalone now.
|
||||
|
||||
for i in range(100):
|
||||
# first we do this
|
||||
if i % 33 == 0:
|
||||
break
|
||||
|
||||
# then we do this
|
||||
print(i)
|
||||
# and finally we loop around
|
||||
|
||||
with open(some_temp_file) as f:
|
||||
data = f.read()
|
||||
|
||||
try:
|
||||
with open(some_other_file) as w:
|
||||
w.write(data)
|
||||
|
||||
except OSError:
|
||||
print("problems")
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
# leading function comment
|
||||
def wat():
|
||||
...
|
||||
# trailing function comment
|
||||
|
||||
|
||||
# SECTION COMMENT
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading 3
|
||||
@deco3
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading function comment
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# Note: this is fixed in
|
||||
# Preview.empty_lines_before_class_or_def_with_leading_comments.
|
||||
# In the current style, the user will have to split those lines by hand.
|
||||
some_instruction
|
||||
|
||||
|
||||
# This comment should be split from `some_instruction` by two lines but isn't.
|
||||
def g():
|
||||
...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
|
||||
@@ -130,12 +130,6 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,4 +1,4 @@
|
||||
-from typing import Any, Tuple
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
|
||||
def f(
|
||||
@@ -49,9 +49,7 @@
|
||||
element = 0 # type: int
|
||||
another_element = 1 # type: float
|
||||
@@ -192,7 +186,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from typing import Any, Tuple
|
||||
|
||||
|
||||
def f(
|
||||
|
||||
@@ -31,18 +31,7 @@ def function(a:int=42):
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,9 +1,4 @@
|
||||
-from .config import (
|
||||
- ConfigTypeAttributes,
|
||||
- Int,
|
||||
- Path, # String,
|
||||
- # DEFAULT_TYPE_ATTRIBUTES,
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
result = 1 # A simple comment
|
||||
result = (1,) # Another one
|
||||
@@ -14,9 +9,9 @@
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
|
||||
def function(a: int = 42):
|
||||
@@ -60,7 +49,12 @@ def function(a:int=42):
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from .config import (
|
||||
ConfigTypeAttributes,
|
||||
Int,
|
||||
Path, # String,
|
||||
# DEFAULT_TYPE_ATTRIBUTES,
|
||||
)
|
||||
|
||||
result = 1 # A simple comment
|
||||
result = (1,) # Another one
|
||||
|
||||
@@ -203,15 +203,6 @@ class C:
|
||||
print(i)
|
||||
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
||||
push_manager=context.request.resource_manager,
|
||||
@@ -37,7 +37,7 @@
|
||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||
).push(
|
||||
# Only send the first n items.
|
||||
- items=items[:num_items]
|
||||
+ items=items[:num_items],
|
||||
)
|
||||
return (
|
||||
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||
@@ -47,113 +47,46 @@
|
||||
def omitting_trailers(self) -> None:
|
||||
get_collection(
|
||||
@@ -418,7 +409,7 @@ class C:
|
||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||
).push(
|
||||
# Only send the first n items.
|
||||
items=items[:num_items],
|
||||
items=items[:num_items]
|
||||
)
|
||||
return (
|
||||
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||
|
||||
@@ -203,15 +203,6 @@ class C:
|
||||
print(i)
|
||||
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
||||
push_manager=context.request.resource_manager,
|
||||
@@ -37,7 +37,7 @@
|
||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||
).push(
|
||||
# Only send the first n items.
|
||||
- items=items[:num_items]
|
||||
+ items=items[:num_items],
|
||||
)
|
||||
return (
|
||||
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||
@@ -47,113 +47,46 @@
|
||||
def omitting_trailers(self) -> None:
|
||||
get_collection(
|
||||
@@ -418,7 +409,7 @@ class C:
|
||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||
).push(
|
||||
# Only send the first n items.
|
||||
items=items[:num_items],
|
||||
items=items[:num_items]
|
||||
)
|
||||
return (
|
||||
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||
|
||||
@@ -198,22 +198,13 @@ d={'a':1,
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,15 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
-import asyncio
|
||||
-import sys
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
@@ -6,10 +6,9 @@
|
||||
|
||||
-from third_party import X, Y, Z
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
-from library import some_connection, some_decorator
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from library import some_connection, some_decorator
|
||||
# fmt: off
|
||||
-from third_party import (X,
|
||||
- Y, Z)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+from third_party import X, Y, Z
|
||||
# fmt: on
|
||||
-f"trigger 3.6 mode"
|
||||
+NOT_YET_IMPLEMENTED_ExprJoinedStr
|
||||
@@ -336,7 +327,7 @@ d={'a':1,
|
||||
# fmt: off
|
||||
- from hello import a, b
|
||||
- 'unformatted'
|
||||
+ NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+ from hello import a, b
|
||||
+ "unformatted"
|
||||
# fmt: on
|
||||
|
||||
@@ -395,12 +386,8 @@ d={'a':1,
|
||||
# fmt: on
|
||||
# fmt: off
|
||||
# ...but comments still get reformatted even though they should not be
|
||||
@@ -150,12 +172,10 @@
|
||||
ast_args.kw_defaults,
|
||||
parameters,
|
||||
implicit_default=True,
|
||||
- )
|
||||
+ ),
|
||||
@@ -153,9 +175,7 @@
|
||||
)
|
||||
)
|
||||
# fmt: off
|
||||
- a = (
|
||||
@@ -437,14 +424,14 @@ d={'a':1,
|
||||
|
||||
```py
|
||||
#!/usr/bin/env python3
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from third_party import X, Y, Z
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from library import some_connection, some_decorator
|
||||
# fmt: off
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from third_party import X, Y, Z
|
||||
# fmt: on
|
||||
NOT_YET_IMPLEMENTED_ExprJoinedStr
|
||||
# Comment 1
|
||||
@@ -543,7 +530,7 @@ def subscriptlist():
|
||||
|
||||
def import_as_names():
|
||||
# fmt: off
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from hello import a, b
|
||||
"unformatted"
|
||||
# fmt: on
|
||||
|
||||
@@ -610,7 +597,7 @@ def long_lines():
|
||||
ast_args.kw_defaults,
|
||||
parameters,
|
||||
implicit_default=True,
|
||||
),
|
||||
)
|
||||
)
|
||||
# fmt: off
|
||||
a = unnecessary_bracket()
|
||||
|
||||
@@ -52,12 +52,7 @@ def test_calculate_fades():
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,40 +1,44 @@
|
||||
-import pytest
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
TmSt = 1
|
||||
TmEx = 2
|
||||
@@ -5,36 +5,40 @@
|
||||
|
||||
# fmt: off
|
||||
|
||||
@@ -113,7 +108,7 @@ def test_calculate_fades():
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import pytest
|
||||
|
||||
TmSt = 1
|
||||
TmEx = 2
|
||||
|
||||
@@ -37,20 +37,11 @@ def f(): pass
|
||||
+ 2,
|
||||
+ 3,
|
||||
+ 4,
|
||||
+ ],
|
||||
+ ]
|
||||
+)
|
||||
# fmt: on
|
||||
def f():
|
||||
pass
|
||||
@@ -14,7 +18,7 @@
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
- ]
|
||||
+ ],
|
||||
)
|
||||
def f():
|
||||
pass
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
@@ -63,7 +54,7 @@ def f(): pass
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
],
|
||||
]
|
||||
)
|
||||
# fmt: on
|
||||
def f():
|
||||
@@ -76,7 +67,7 @@ def f():
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
],
|
||||
]
|
||||
)
|
||||
def f():
|
||||
pass
|
||||
|
||||
@@ -103,7 +103,7 @@ elif unformatted:
|
||||
- # fmt: on
|
||||
- ] # Includes an formatted indentation.
|
||||
+ # fmt: on
|
||||
+ ], # Includes an formatted indentation.
|
||||
+ ] # Includes an formatted indentation.
|
||||
},
|
||||
)
|
||||
|
||||
@@ -186,7 +186,7 @@ setup(
|
||||
"foo-bar"
|
||||
"=foo.bar.:main",
|
||||
# fmt: on
|
||||
], # Includes an formatted indentation.
|
||||
] # Includes an formatted indentation.
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtpass_imports.py
|
||||
---
|
||||
## Input
|
||||
|
||||
```py
|
||||
# Regression test for https://github.com/psf/black/issues/3438
|
||||
|
||||
import ast
|
||||
import collections # fmt: skip
|
||||
import dataclasses
|
||||
# fmt: off
|
||||
import os
|
||||
# fmt: on
|
||||
import pathlib
|
||||
|
||||
import re # fmt: skip
|
||||
import secrets
|
||||
|
||||
# fmt: off
|
||||
import sys
|
||||
# fmt: on
|
||||
|
||||
import tempfile
|
||||
import zoneinfo
|
||||
```
|
||||
|
||||
## Black Differences
|
||||
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,19 +1,19 @@
|
||||
# Regression test for https://github.com/psf/black/issues/3438
|
||||
|
||||
-import ast
|
||||
-import collections # fmt: skip
|
||||
-import dataclasses
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
+NOT_YET_IMPLEMENTED_StmtImport # fmt: skip
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
# fmt: off
|
||||
-import os
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
# fmt: on
|
||||
-import pathlib
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
-import re # fmt: skip
|
||||
-import secrets
|
||||
+NOT_YET_IMPLEMENTED_StmtImport # fmt: skip
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
# fmt: off
|
||||
-import sys
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
# fmt: on
|
||||
|
||||
-import tempfile
|
||||
-import zoneinfo
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
# Regression test for https://github.com/psf/black/issues/3438
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
NOT_YET_IMPLEMENTED_StmtImport # fmt: skip
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
# fmt: off
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
# fmt: on
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImport # fmt: skip
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
# fmt: off
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
# fmt: on
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
```
|
||||
|
||||
## Black Output
|
||||
|
||||
```py
|
||||
# Regression test for https://github.com/psf/black/issues/3438
|
||||
|
||||
import ast
|
||||
import collections # fmt: skip
|
||||
import dataclasses
|
||||
# fmt: off
|
||||
import os
|
||||
# fmt: on
|
||||
import pathlib
|
||||
|
||||
import re # fmt: skip
|
||||
import secrets
|
||||
|
||||
# fmt: off
|
||||
import sys
|
||||
# fmt: on
|
||||
|
||||
import tempfile
|
||||
import zoneinfo
|
||||
```
|
||||
|
||||
|
||||
@@ -107,20 +107,12 @@ def __await__(): return (yield)
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,12 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
-import asyncio
|
||||
-import sys
|
||||
@@ -5,8 +5,7 @@
|
||||
from third_party import X, Y, Z
|
||||
|
||||
from library import some_connection, some_decorator
|
||||
-
|
||||
-from third_party import X, Y, Z
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
-from library import some_connection, some_decorator
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
-f"trigger 3.6 mode"
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_ExprJoinedStr
|
||||
|
||||
|
||||
@@ -198,24 +190,6 @@ def __await__(): return (yield)
|
||||
|
||||
|
||||
def long_lines():
|
||||
@@ -87,7 +94,7 @@
|
||||
ast_args.kw_defaults,
|
||||
parameters,
|
||||
implicit_default=True,
|
||||
- )
|
||||
+ ),
|
||||
)
|
||||
typedargslist.extend(
|
||||
gen_annotated_params(
|
||||
@@ -96,7 +103,7 @@
|
||||
parameters,
|
||||
implicit_default=True,
|
||||
# trailing standalone comment
|
||||
- )
|
||||
+ ),
|
||||
)
|
||||
_type_comment_re = re.compile(
|
||||
r"""
|
||||
@@ -135,14 +142,8 @@
|
||||
a,
|
||||
**kwargs,
|
||||
@@ -239,12 +213,12 @@ def __await__(): return (yield)
|
||||
|
||||
```py
|
||||
#!/usr/bin/env python3
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from third_party import X, Y, Z
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from library import some_connection, some_decorator
|
||||
NOT_YET_IMPLEMENTED_ExprJoinedStr
|
||||
|
||||
|
||||
@@ -334,7 +308,7 @@ def long_lines():
|
||||
ast_args.kw_defaults,
|
||||
parameters,
|
||||
implicit_default=True,
|
||||
),
|
||||
)
|
||||
)
|
||||
typedargslist.extend(
|
||||
gen_annotated_params(
|
||||
@@ -343,7 +317,7 @@ def long_lines():
|
||||
parameters,
|
||||
implicit_default=True,
|
||||
# trailing standalone comment
|
||||
),
|
||||
)
|
||||
)
|
||||
_type_comment_re = re.compile(
|
||||
r"""
|
||||
|
||||
@@ -65,22 +65,15 @@ with hmm_but_this_should_get_two_preceding_newlines():
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -32,34 +32,28 @@
|
||||
|
||||
|
||||
if os.name == "posix":
|
||||
- import termios
|
||||
+ NOT_YET_IMPLEMENTED_StmtImport
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
pass
|
||||
-
|
||||
elif os.name == "nt":
|
||||
try:
|
||||
- import msvcrt
|
||||
+ NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
import msvcrt
|
||||
@@ -45,21 +44,16 @@
|
||||
pass
|
||||
|
||||
except ImportError:
|
||||
@@ -141,13 +134,13 @@ def h():
|
||||
|
||||
|
||||
if os.name == "posix":
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import termios
|
||||
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
pass
|
||||
elif os.name == "nt":
|
||||
try:
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import msvcrt
|
||||
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
pass
|
||||
|
||||
@@ -73,15 +73,6 @@ some_module.some_function(
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -27,7 +27,7 @@
|
||||
call(
|
||||
arg={
|
||||
"explode": "this",
|
||||
- }
|
||||
+ },
|
||||
)
|
||||
call2(
|
||||
arg=[1, 2, 3],
|
||||
@@ -35,7 +35,9 @@
|
||||
x = {
|
||||
"a": 1,
|
||||
@@ -93,7 +84,7 @@ some_module.some_function(
|
||||
if (
|
||||
a
|
||||
== {
|
||||
@@ -47,22 +49,24 @@
|
||||
@@ -47,14 +49,16 @@
|
||||
"f": 6,
|
||||
"g": 7,
|
||||
"h": 8,
|
||||
@@ -114,17 +105,6 @@ some_module.some_function(
|
||||
json = {
|
||||
"k": {
|
||||
"k2": {
|
||||
"k3": [
|
||||
1,
|
||||
- ]
|
||||
- }
|
||||
- }
|
||||
+ ],
|
||||
+ },
|
||||
+ },
|
||||
}
|
||||
|
||||
|
||||
@@ -80,18 +84,14 @@
|
||||
pass
|
||||
|
||||
@@ -182,7 +162,7 @@ def f(
|
||||
call(
|
||||
arg={
|
||||
"explode": "this",
|
||||
},
|
||||
}
|
||||
)
|
||||
call2(
|
||||
arg=[1, 2, 3],
|
||||
@@ -219,9 +199,9 @@ def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||
"k2": {
|
||||
"k3": [
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,79 +61,15 @@ __all__ = (
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -2,53 +2,31 @@
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
-from logging import WARNING
|
||||
-from logging import (
|
||||
- ERROR,
|
||||
-)
|
||||
-import sys
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
# This relies on each of the submodules having an __all__ variable.
|
||||
-from .base_events import *
|
||||
-from .coroutines import *
|
||||
-from .events import * # comment here
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom # comment here
|
||||
|
||||
-from .futures import *
|
||||
-from .locks import * # comment here
|
||||
-from .protocols import *
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom # comment here
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
-from ..runners import * # comment here
|
||||
-from ..queues import *
|
||||
-from ..streams import *
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom # comment here
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
-from some_library import (
|
||||
- Just,
|
||||
- Enough,
|
||||
- Libraries,
|
||||
- To,
|
||||
- Fit,
|
||||
- In,
|
||||
- This,
|
||||
- Nice,
|
||||
- Split,
|
||||
- Which,
|
||||
- We,
|
||||
- No,
|
||||
- Longer,
|
||||
- Use,
|
||||
-)
|
||||
-from name_of_a_company.extremely_long_project_name.component.ttypes import (
|
||||
@@ -38,7 +38,7 @@
|
||||
Use,
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.component.ttypes import (
|
||||
- CuteLittleServiceHandlerFactoryyy,
|
||||
-)
|
||||
-from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+ CuteLittleServiceHandlerFactoryyy
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
|
||||
|
||||
-from .a.b.c.subprocess import *
|
||||
-from . import tasks
|
||||
-from . import A, B, C
|
||||
-from . import (
|
||||
- SomeVeryLongNameAndAllOfItsAdditionalLetters1,
|
||||
- SomeVeryLongNameAndAllOfItsAdditionalLetters2,
|
||||
-)
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
+NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
|
||||
__all__ = (
|
||||
base_events.__all__
|
||||
```
|
||||
|
||||
## Ruff Output
|
||||
@@ -143,31 +79,53 @@ __all__ = (
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
from logging import WARNING
|
||||
from logging import (
|
||||
ERROR,
|
||||
)
|
||||
import sys
|
||||
|
||||
# This relies on each of the submodules having an __all__ variable.
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom # comment here
|
||||
from .base_events import *
|
||||
from .coroutines import *
|
||||
from .events import * # comment here
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom # comment here
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from .futures import *
|
||||
from .locks import * # comment here
|
||||
from .protocols import *
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom # comment here
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from ..runners import * # comment here
|
||||
from ..queues import *
|
||||
from ..streams import *
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from some_library import (
|
||||
Just,
|
||||
Enough,
|
||||
Libraries,
|
||||
To,
|
||||
Fit,
|
||||
In,
|
||||
This,
|
||||
Nice,
|
||||
Split,
|
||||
Which,
|
||||
We,
|
||||
No,
|
||||
Longer,
|
||||
Use,
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.component.ttypes import (
|
||||
CuteLittleServiceHandlerFactoryyy
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
|
||||
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from .a.b.c.subprocess import *
|
||||
from . import tasks
|
||||
from . import A, B, C
|
||||
from . import (
|
||||
SomeVeryLongNameAndAllOfItsAdditionalLetters1,
|
||||
SomeVeryLongNameAndAllOfItsAdditionalLetters2,
|
||||
)
|
||||
|
||||
__all__ = (
|
||||
base_events.__all__
|
||||
|
||||
@@ -93,12 +93,6 @@ async def main():
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,4 +1,4 @@
|
||||
-import asyncio
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
|
||||
# Control example
|
||||
@@ -8,59 +8,70 @@
|
||||
|
||||
# Remove brackets for short coroutine/task
|
||||
@@ -219,7 +213,7 @@ async def main():
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import asyncio
|
||||
|
||||
|
||||
# Control example
|
||||
|
||||
@@ -120,12 +120,6 @@ with open("/path/to/file.txt", mode="r") as read_file:
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -1,4 +1,4 @@
|
||||
-import random
|
||||
+NOT_YET_IMPLEMENTED_StmtImport
|
||||
|
||||
|
||||
def foo1():
|
||||
@@ -27,16 +27,16 @@
|
||||
|
||||
|
||||
@@ -151,7 +145,7 @@ with open("/path/to/file.txt", mode="r") as read_file:
|
||||
## Ruff Output
|
||||
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImport
|
||||
import random
|
||||
|
||||
|
||||
def foo1():
|
||||
|
||||
@@ -111,7 +111,7 @@ x53 = (
|
||||
|
||||
## Output
|
||||
```py
|
||||
NOT_YET_IMPLEMENTED_StmtImportFrom
|
||||
from argparse import Namespace
|
||||
|
||||
a = Namespace()
|
||||
|
||||
|
||||
@@ -299,9 +299,9 @@ not (aaaaaaaaaaaaaa + {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_se
|
||||
[
|
||||
a
|
||||
+ [
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
]
|
||||
in c,
|
||||
in c
|
||||
]
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user