ruff icon indicating copy to clipboard operation
ruff copied to clipboard

Add convert exit() to sys.exit() rule

Open JonathanPlasse opened this issue 2 years ago • 3 comments

  • [ ] Fix
    • [x] It fixes when
      • [x] import sys
      • [x] import sys as sys2
      • [x] ~import sys.exit~ does not work
      • [x] from sys import exit as exit2
    • [ ] It does not fix when not it has to import sys. Is there an example of how to add an import while keeping it sorted if I is selected?
  • [ ] exit() is not detected inside functions. What did I do wrong? Is it current_scope() that is not enough? Do I need to iterate over every scope?

JonathanPlasse avatar Nov 19 '22 09:11 JonathanPlasse

It does not fix when not it has to import sys.

Hmm, no, we don't do that anywhere yet. Let's try for that later, as it would require fixes with multiple edits that change multiple parts of the tree.

exit() is not detected inside functions. What did I do wrong? Is it current_scope() that is not enough? Do I need to iterate over every scope?

Yeah, yeah you have to iterate over every scope in reverse, like:

for scope_index in self.scope_stack.iter().rev() {
    let scope = &mut self.scopes[*scope_index];
    ...
}

We might want to add a .current_scope()-like method to Checker to expose that iterate to plugins.

charliermarsh avatar Nov 19 '22 14:11 charliermarsh

@charliermarsh,

It does not fix when not it has to import sys.

Hmm, no, we don't do that anywhere yet. Let's try for that later, as it would require fixes with multiple edits that change multiple parts of the tree.

Let's open an issue once this PR is merged.

exit() is not detected inside functions. What did I do wrong? Is it current_scope() that is not enough? Do I need to iterate over every scope?

Yeah, yeah you have to iterate over every scope in reverse, like:

for scope_index in self.scope_stack.iter().rev() {
    let scope = &mut self.scopes[*scope_index];
    ...
}

We might want to add a .current_scope()-like method to Checker to expose that iterate to plugins.

I added Checker.current_scopes(). But, even if I iterate over every scope, it still does not work. Or maybe I made an error.

JonathanPlasse avatar Nov 19 '22 21:11 JonathanPlasse

@JonathanPlasse - I think your code is actually right! But the test case is a bit off. Right now, you have this:

...

def main():
    exit(6)  # Is not detected

...

def exit(e):
    print(e)

...

So, you're re-defining exit at the bottom, and when the main() with exit(6) is evaluated, exit is no longer the built-in. If you remove the def exit, the error is picked up -- which matches Python's semantics.

I think you'll need to split into a few different test files to evaluate all of those cases.

charliermarsh avatar Nov 20 '22 15:11 charliermarsh

@JonathanPlasse - Feel free to mark as "ready for review" when you're happy with this!

charliermarsh avatar Nov 20 '22 18:11 charliermarsh

I am ready for review :)

JonathanPlasse avatar Nov 20 '22 19:11 JonathanPlasse

Is it possible to make a pre-commit release?

JonathanPlasse avatar Nov 20 '22 19:11 JonathanPlasse

Is it normal that I have to specify --fixable in ruff --fix --fixable RUF --select RUFF file.py for the fix to work?

JonathanPlasse avatar Nov 20 '22 20:11 JonathanPlasse

Great! Will review tonight!

@JonathanPlasse - No, --fixable shouldn't be necessary. That's a bug, will PR, one sec...

charliermarsh avatar Nov 20 '22 20:11 charliermarsh

(Fixed in https://github.com/charliermarsh/ruff/pull/838.)

charliermarsh avatar Nov 20 '22 20:11 charliermarsh