Skip to content

Conversation

VascoSch92
Copy link
Contributor

The PR addresses issue #18209.

Copy link
Contributor

github-actions bot commented May 20, 2025

ruff-ecosystem results

Linter (stable)

ℹ️ ecosystem check detected linter changes. (+6 -6 violations, +0 -0 fixes in 2 projects; 53 projects unchanged)

apache/superset (+1 -1 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --no-preview --select ALL

+ superset/migrations/versions/2015-12-04_09-42_1a48a5411020_adding_slug_to_dash.py:35:5: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- superset/migrations/versions/2015-12-04_09-42_1a48a5411020_adding_slug_to_dash.py:35:5: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`

binary-husky/gpt_academic (+5 -5 violations, +0 -0 fixes)

+ crazy_functions/Latex_Function.py:76:5: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- crazy_functions/Latex_Function.py:76:5: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ multi_language.py:363:9: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- multi_language.py:363:9: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ request_llms/com_qwenapi.py:57:21: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- request_llms/com_qwenapi.py:57:21: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ request_llms/oai_std_model_template.py:72:5: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- request_llms/oai_std_model_template.py:72:5: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ toolbox.py:463:13: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- toolbox.py:463:13: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
SIM105 12 6 6 0 0

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+6 -6 violations, +0 -0 fixes in 2 projects; 53 projects unchanged)

apache/superset (+1 -1 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview --select ALL

+ superset/migrations/versions/2015-12-04_09-42_1a48a5411020_adding_slug_to_dash.py:35:5: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- superset/migrations/versions/2015-12-04_09-42_1a48a5411020_adding_slug_to_dash.py:35:5: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`

binary-husky/gpt_academic (+5 -5 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ crazy_functions/Latex_Function.py:76:5: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- crazy_functions/Latex_Function.py:76:5: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ multi_language.py:363:9: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- multi_language.py:363:9: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ request_llms/com_qwenapi.py:57:21: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- request_llms/com_qwenapi.py:57:21: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ request_llms/oai_std_model_template.py:72:5: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- request_llms/oai_std_model_template.py:72:5: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`
+ toolbox.py:463:13: SIM105 Use `contextlib.suppress(BaseException)` instead of `try`-`except`-`pass`
- toolbox.py:463:13: SIM105 Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
SIM105 12 6 6 0 0

"Exception".to_string()
if type_.is_none() {
// case where there are no handler names provided at all
"BaseException".to_string()
Copy link

@dscorbett dscorbett May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won’t work if BaseException is shadowed. Here is an example of how to safely insert a builtin symbol:

let (import_edit, binding) = checker.importer().get_or_import_builtin_symbol(
"callable",
expr.start(),
checker.semantic(),
)?;

@VascoSch92
Copy link
Contributor Author

@ntBre I have a problem. How I could import more stuff at the same time? Do you have an example where it was made in another rule?

I'm asking because here I would like to import subprocess from contextlib and also BaseException

@MichaReiser
Copy link
Member

Would this work

let (reduce_edit, reduce_binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import("functools", "reduce"),
call.start(),
checker.semantic(),
)?;
let (iadd_edit, iadd_binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import("operator", "iadd"),
iterable.start(),
checker.semantic(),
)?;

@VascoSch92 VascoSch92 requested a review from dscorbett May 21, 2025 16:49
@VascoSch92
Copy link
Contributor Author

Hey,
thanks for the help.

I hope understood what you were asking ;-)

format!("with {binding}({exception})"),
let mut rest: Vec<Edit> = Vec::new();
let content: String;
if exception == "BaseException" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this condition correct when BaseException is shadowed and caught explicitly?

BaseException = ValueError
try:
    int("a")
except BaseException:
    pass

The fixed version should use suppress(BaseException), not suppress(builtins.BaseException).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. No, it was't. I added a new test case and fix that

@VascoSch92
Copy link
Contributor Author

It should be fine now

@ntBre ntBre added bug Something isn't working fixes Related to suggested fixes for violations labels May 29, 2025
@ntBre ntBre self-requested a review May 29, 2025 19:19
Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! The implementation looks reasonable to me, I just had a couple of vague ideas for your consideration.

I'm also kind of on the fence about whether we should offer the fix for the completely empty case. As mentioned in the issue, the fix could obscure a potential problem that would be caught by other lint rules.

I think the empty tuple case is okay because useless-contextlib-suppress (B022) will catch the empty suppress, but I'm not seeing any diagnostics on contextlib.suppress(BaseException) with all rules selected (playground).

If we still offer the fix, we could consider adding another rule similar to blind-except (BLE001) that applies to contextlib.suppress (or extend one of these existing rules).

What do you think?

@@ -115,7 +118,13 @@ pub(crate) fn suppressible_exception(
};

let exception = if handler_names.is_empty() {
"Exception".to_string()
if type_.is_none() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could collapse this check like the one below to

if handler_names.is_empty() && type_.is_none() {

because join on an empty Vec should also give the empty string. Maybe that's getting too clever though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then we lose one else or?

the complete snippet is

 let exception = if handler_names.is_empty() {
        if type_.is_none() {
            // case where there are no handler names provided at all
            "BaseException".to_string()
        } else {
            // case where handler names is an empty tuple
            String::new()
        }
    } else {
        handler_names.join(", ")
    };

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, I was suggesting this:

 let exception = if handler_names.is_empty() && type_.is_none() {
         "BaseException".to_string()
    } else {
        handler_names.join(", ")
    };

That does drop the middle else, but String::new() and handler_names.join(", ") are equivalent when handler_names is empty, so it's safe to combine the two else branches. However, I think this is evidence that your current code is more clear 😄

@ntBre
Copy link
Contributor

ntBre commented Jun 5, 2025

If we still offer the fix, we could consider adding another rule similar to blind-except (BLE001) that applies to contextlib.suppress (or extend one of these existing rules).

There's a somewhat related request for this in #4923, except it's for Exception rather than BaseException and try-except-pass (S110) instead of BLE001. There are a lot of rules about exceptions!

@VascoSch92
Copy link
Contributor Author

Thanks! The implementation looks reasonable to me, I just had a couple of vague ideas for your consideration.

I'm also kind of on the fence about whether we should offer the fix for the completely empty case. As mentioned in the issue, the fix could obscure a potential problem that would be caught by other lint rules.

I think the empty tuple case is okay because useless-contextlib-suppress (B022) will catch the empty suppress, but I'm not seeing any diagnostics on contextlib.suppress(BaseException) with all rules selected (playground).

If we still offer the fix, we could consider adding another rule similar to blind-except (BLE001) that applies to contextlib.suppress (or extend one of these existing rules).

What do you think?

I don't have strong opinions :-) let me know which solution you like and I would change the code accordingly

@ntBre
Copy link
Contributor

ntBre commented Jun 9, 2025

I'll have to think a bit more about this. I'm mostly working on the 0.12 release this week, but I'm putting this on my todo list for afterward! Thanks for following up.

Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move ahead with the fix and open an issue to add or extend a rule to catch contextlib.suppress(BaseException).

I think that means all of the questions are resolved and this is good to go?

@VascoSch92
Copy link
Contributor Author

@ntBre Yes good to go ;-)

@ntBre ntBre linked an issue Jun 23, 2025 that may be closed by this pull request
@ntBre ntBre changed the title [flake8-simplify] fix handlers corner cases (SIM105) [flake8-simplify] Preserve original behavior for except () and bare except (SIM105) Jun 23, 2025
@ntBre ntBre merged commit ca8ed35 into astral-sh:main Jun 23, 2025
34 checks passed
@VascoSch92 VascoSch92 deleted the issue-18209 branch June 23, 2025 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixes Related to suggested fixes for violations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SIM105 fix changes behavior for except (): and except:
4 participants