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

extend-immutable-calls doesn't work on Python scripts (as opposed to modules) #10960

Closed
fofoni opened this issue Apr 15, 2024 · 4 comments · Fixed by #10965
Closed

extend-immutable-calls doesn't work on Python scripts (as opposed to modules) #10960

fofoni opened this issue Apr 15, 2024 · 4 comments · Fixed by #10965
Assignees
Labels
configuration Related to settings and configuration

Comments

@fofoni
Copy link

fofoni commented Apr 15, 2024

Keywords: extend-immutable-calls, B008, script, module, __main__
Ruff version: 0.3.7

Working MWE

In a directory containing just the file test.py:

from other_module import A

def f(a=A()):
    pass

checking with:

ruff check --isolated --select=B008 \
    --config 'lint.flake8-bugbear.extend-immutable-calls=["other_module.A"]' \
    test.py

yields no errors.

Buggy MWE

If I declare A in the script instead of importing it:

class A: pass

def f(a=A()):
    pass

now ruff will find a B008 error in the def line, no matter what I configure in extend-immutable-calls. I tried A, test.A, __main__.A, and even builtins.A and __builtins__.A. Nothing makes it recognize A() as an immutable call.

@charliermarsh
Copy link
Member

Hmm yeah... We need some way to identify A, and if you pass a script, we probably can't find a module root against which to resolve the path.

@charliermarsh
Copy link
Member

__main__.A is kind of interesting.

@charliermarsh charliermarsh added the configuration Related to settings and configuration label Apr 16, 2024
@fofoni
Copy link
Author

fofoni commented Apr 16, 2024

(Updated the OP to note that I also tried with test.A.)

__main__.A is kind of interesting.

I tried __main__.A because I didn't know what would work and was exploring possibilities, but I'm not sure if like it: after all, depending on how you invoke Python, any .py file could be the __main__ module. In the end, fully-qualified names aren't really well-defined statically -- you need to look them up in sys.path and follow import hooks etc (mypy can sometimes run into a similar problem).

Since ruff interprets module paths statically, I think the best thing to do in this case would be to check that test.py is not contained in an import package (i.e. not alongside an __init.__.py) and then accept test.A as A's fully-qualified name.

@charliermarsh
Copy link
Member

That seems reasonable to me.

@charliermarsh charliermarsh self-assigned this Apr 16, 2024
charliermarsh added a commit that referenced this issue Apr 18, 2024
## Summary

If the user is analyzing a script (i.e., we have no module path), it
seems reasonable to use the script name when trying to identify paths to
objects defined _within_ the script.

Closes #10960.

## Test Plan

Ran:

```shell
check --isolated --select=B008 \
    --config 'lint.flake8-bugbear.extend-immutable-calls=["test.A"]' \
    test.py
```

On:

```python
class A: pass

def f(a=A()):
    pass
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
configuration Related to settings and configuration
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants