Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pylint] Re-implement unreachable (PLW0101) #10891

Merged
merged 50 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
0a20ab6
Revert "Remove `unreachable-code` feature (#9463)"
augustelalande Apr 11, 2024
4a716d6
remove feature gate
augustelalande Apr 11, 2024
b615c91
fix up
augustelalande Apr 11, 2024
a8023c5
mark preview
augustelalande Apr 11, 2024
ddaaee4
Implement post_processing to handle `break` and `continue` in loops w…
augustelalande Apr 13, 2024
b8ca509
Always get an after_block to avoid having to get one for each branch …
augustelalande Apr 14, 2024
64dbcc3
Fix #8958
augustelalande Apr 15, 2024
97aa6f0
fix infinite recursion
augustelalande Apr 15, 2024
ef0a913
Always close the loop
augustelalande Apr 15, 2024
cc3b083
fix handling of asserts in postprocessing
augustelalande Apr 16, 2024
0afcafa
initial implementation of try statement handling
augustelalande Apr 17, 2024
cc56b59
clean up docs
augustelalande Apr 20, 2024
ede5312
always process finally
augustelalande Apr 21, 2024
439bf09
these were fixed
augustelalande Apr 21, 2024
c293600
add cfg tests for try
augustelalande Apr 21, 2024
0b9512a
clippy
augustelalande Apr 21, 2024
91be932
execute blank `except` unconditionally
augustelalande Apr 21, 2024
a1e1fbf
process with statements
augustelalande Apr 21, 2024
1d97810
this was fixed
augustelalande Apr 21, 2024
91da715
maybe fall through with statement on error
augustelalande Apr 21, 2024
4978d06
remove `force_next_block` which would change the flow incorrectly
augustelalande Apr 21, 2024
619d710
improve processing of finallys
augustelalande Apr 22, 2024
97d560e
Fix clippy warnings
MichaReiser Aug 5, 2024
e8c7ebb
update message
augustelalande Aug 26, 2024
6c450c2
remove bitmap, use a flag on the blocks themselves
augustelalande Aug 26, 2024
f7e1e21
clippy
augustelalande Aug 26, 2024
acb07bb
add nested for loop tests with break and continue
augustelalande Aug 26, 2024
6536e43
add comments for post_processing
augustelalande Aug 26, 2024
d3807aa
highlight all statements in block
augustelalande Aug 26, 2024
2d76c51
fix overflow error, although this exposes another issue; will fix later
augustelalande Aug 27, 2024
64c9233
use BasicBlockKind
augustelalande Sep 5, 2024
e212ee3
do not re-use exception blocks for proper handling of finally
augustelalande Sep 5, 2024
b066bec
add another test case
augustelalande Sep 5, 2024
c96743e
clippy
augustelalande Sep 5, 2024
3f58cac
simplify handling of match statements
augustelalande Sep 5, 2024
902c123
rename conditions
augustelalande Sep 5, 2024
153c3b0
improve documentation
augustelalande Sep 5, 2024
be78736
don't assume loop body has any statements
augustelalande Sep 5, 2024
90d0551
format
augustelalande Sep 5, 2024
63efc1c
documentation
augustelalande Sep 5, 2024
fa84ffa
clippy
augustelalande Sep 5, 2024
1417363
merge blocks
augustelalande Aug 26, 2024
6a2be73
combine nearby violations into one
augustelalande Sep 5, 2024
70c414c
clippy
augustelalande Sep 5, 2024
c207f4c
sort by range start
augustelalande Sep 5, 2024
700b732
clippy
augustelalande Sep 5, 2024
902d641
use ViolationMetadata derive macro
dylwil3 Jan 2, 2025
5901292
clippy
dylwil3 Jan 2, 2025
9d47451
more aggressive clippy
dylwil3 Jan 2, 2025
d13ff6a
move rule to pylint
dylwil3 Jan 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/ruff_linter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ license = { workspace = true }
[dependencies]
ruff_cache = { workspace = true }
ruff_diagnostics = { workspace = true, features = ["serde"] }
ruff_index = { workspace = true }
ruff_notebook = { workspace = true }
ruff_macros = { workspace = true }
ruff_python_ast = { workspace = true, features = ["serde", "cache"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,29 @@ def func():

def func():
assert False, "oops"

def func():
y = 2
assert y == 2
assert y > 1
assert y < 3

def func():
for i in range(3):
assert i < x

def func():
for j in range(3):
x = 2
else:
assert False
return 1

def func():
for j in range(3):
if j == 2:
print('yay')
break
else:
assert False
return 1
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ def func():
if True:
break

# TODO(charlie): The `pass` here does not get properly redirected to the top of the
# loop, unlike below.
def func():
for i in range(5):
pass
Expand All @@ -54,3 +52,59 @@ def func():
else:
return 1
x = 1

def func():
for i in range(5):
pass
else:
pass

def func():
for i in range(3):
if i == 2:
assert i is not None
break
else:
raise Exception()
x = 0

def func():
for i in range(13):
for i in range(12):
x = 2
if True:
break

x = 3
if True:
break

print('hello')


def func():
for i in range(13):
for i in range(12):
x = 2
if True:
continue

x = 3
if True:
break

print('hello')


def func():
for i in range(13):
for i in range(12):
x = 2
if True:
break

x = 3
if True:
continue

print('hello')
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,25 @@ def func(self, obj: BytesRep) -> bytes:
self.error(f"can't resolve buffer '{id}'")

return buffer.data

def func(x):
if x == 1:
return 1
elif False:
return 2
elif x == 3:
return 3
elif True:
return 4
elif x == 5:
return 5
elif x == 6:
return 6

def func():
if x:
return
else:
assert x

print('pop')
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,14 @@ def func():
i = 0
i += 2
return i

def func():
with x:
i = 0
i = 1

def func():
with x:
i = 0
return 1
i = 1
111 changes: 94 additions & 17 deletions crates/ruff_linter/resources/test/fixtures/control-flow-graph/try.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,118 @@
def func():
try:
...
print("try")
except Exception:
...
print("Exception")
except OtherException as e:
...
print("OtherException")
else:
...
print("else")
finally:
...
print("finally")

def func():
try:
...
except Exception:
...
print("try")
except:
print("Exception")

def func():
try:
print("try")
except:
print("Exception")
except OtherException as e:
print("OtherException")

def func():
try:
...
print("try")
except Exception:
...
print("Exception")
except OtherException as e:
...
print("OtherException")

def func():
try:
...
print("try")
except Exception:
...
print("Exception")
except OtherException as e:
...
print("OtherException")
else:
...
print("else")

def func():
try:
print("try")
finally:
print("finally")

def func():
try:
...
return 0
except:
return 1
finally:
return 2

def func():
try:
raise Exception()
except:
print("reached")

def func():
try:
assert False
print("unreachable")
except:
print("reached")

def func():
try:
raise Exception()
finally:
print('reached')
return 2

def func():
try:
assert False
print("unreachable")
finally:
print("reached")

# Test case from ibis caused overflow
def func():
try:
if catalog is not None:
try:
x = 0
except PySparkParseException:
x = 1
try:
x = 2
except PySparkParseException:
x = 3
x = 8
finally:
if catalog is not None:
try:
x = 4
except PySparkParseException:
x = 5
try:
x = 6
except PySparkParseException:
x = 7


def func():
try:
assert False
except ex:
raise ex

finally:
...
raise Exception("other")
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,39 @@ def func():
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).
def func():
while True:
x = 0
x = 1
break
x = 2
x = 3

def func():
while True:
x = 0
x = 1
continue
x = 2
x = 3

def func():
while True:
x = 0
x = 1
return
x = 2
x = 3

def func():
while True:
x = 0
x = 1
raise Exception
x = 2
x = 3

# Test case found in the Bokeh repository that trigger a false positive.
# Test case found in the Bokeh repository that triggered a false positive.
def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
self.stop_serving = False
while True:
Expand All @@ -118,4 +145,3 @@ def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
port += 1

self.thread = threading.Thread(target=self._run_web_server)
'''
Loading
Loading