mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00

## Summary This PR implements the rule B901, which is part of the opinionated rules of `flake8-bugbear`. This rule seems to be desired in `ruff` as per https://github.com/astral-sh/ruff/issues/3758 and https://github.com/astral-sh/ruff/issues/2954#issuecomment-1441162976. ## Test Plan As this PR was made closely following the [CONTRIBUTING.md](8a25531a71/CONTRIBUTING.md
), it tests using the snapshot approach, that is described there. ## Sources The implementation is inspired by [the original implementation in the `flake8-bugbear` repository](d1aec4cbef/bugbear.py (L1092)
). The error message and [test file](d1aec4cbef/tests/b901.py
) where also copied from there. The documentation I came up with on my own and needs improvement. Maybe the example given in https://github.com/astral-sh/ruff/issues/2954#issuecomment-1441162976 could be used, but maybe they are too complex, I'm not sure. ## Open Questions - [ ] Documentation. (See above.) - [x] Can I access the parent in a visitor? The [original implementation](d1aec4cbef/bugbear.py (L1100)
) references the `yield` statement's parent to check if it is an expression statement. I didn't find a way to do this in `ruff` and used the `is_expresssion_statement` field on the visitor instead. What are your thoughts on this? Is it possible and / or desired to access the parent node here? - [x] Is `Option::is_some(...)` -> `...unwrap()` the right thing to do? Referring to [this piece of code](9d5a280f71/crates/ruff_linter/src/rules/flake8_bugbear/rules/return_x_in_generator.rs (L91-L96)
). From my understanding, the `.unwrap()` is safe, because it is checked that `return_` is not `None`. However, I feel like I missed a more elegant solution that does both in one. ## Other I don't know a lot about this rule, I just implemented it because I found it in a https://github.com/astral-sh/ruff/labels/good%20first%20issue. I'm new to Rust, so any constructive critisism is appreciated. --------- Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
78 lines
887 B
Python
78 lines
887 B
Python
"""
|
|
Should emit:
|
|
B901 - on lines 9, 36
|
|
"""
|
|
|
|
|
|
def broken():
|
|
if True:
|
|
return [1, 2, 3]
|
|
|
|
yield 3
|
|
yield 2
|
|
yield 1
|
|
|
|
|
|
def not_broken():
|
|
if True:
|
|
return
|
|
|
|
yield 3
|
|
yield 2
|
|
yield 1
|
|
|
|
|
|
def not_broken2():
|
|
return not_broken()
|
|
|
|
|
|
def not_broken3():
|
|
return
|
|
|
|
yield from not_broken()
|
|
|
|
|
|
def broken2():
|
|
return [3, 2, 1]
|
|
|
|
yield from not_broken()
|
|
|
|
|
|
async def not_broken4():
|
|
import asyncio
|
|
|
|
await asyncio.sleep(1)
|
|
return 1
|
|
|
|
|
|
def not_broken5():
|
|
def inner():
|
|
return 2
|
|
|
|
yield inner()
|
|
|
|
|
|
def not_broken6():
|
|
return (yield from [])
|
|
|
|
|
|
def not_broken7():
|
|
x = yield from []
|
|
return x
|
|
|
|
|
|
def not_broken8():
|
|
x = None
|
|
|
|
def inner(ex):
|
|
nonlocal x
|
|
x = ex
|
|
|
|
inner((yield from []))
|
|
return x
|
|
|
|
|
|
class NotBroken9(object):
|
|
def __await__(self):
|
|
yield from function()
|
|
return 42
|