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

F841 (unused-variable) false positives in Jupyter notebooks #8094

Open
tdulcet opened this issue Oct 20, 2023 · 7 comments
Open

F841 (unused-variable) false positives in Jupyter notebooks #8094

tdulcet opened this issue Oct 20, 2023 · 7 comments
Labels
bug Something isn't working notebook Related to (Jupyter) notebooks wish Not on the current roadmap; maybe in the future

Comments

@tdulcet
Copy link

tdulcet commented Oct 20, 2023

  • A minimal code snippet that reproduces the bug.
var = "World"
!echo "Hello $var"

or

var = "World"
!echo "{'Hello ' + var}"

(Note that one can put arbitrary Python expressions/code in the above brackets, which is not currently linted.)

Ruff actual output:

test.ipynb:cell 1:1:3: F841 Local variable `var` is assigned to but never used

Ruff expected output: None

  • The command you invoked (e.g., ruff /path/to/file.py --fix), ideally including the --isolated flag.
ruff --select F841 --isolated test.ipynb
  • The current Ruff settings (any relevant sections from your pyproject.toml).
    None
  • The current Ruff version (ruff --version).
ruff 0.1.1

There is a public notebook here that currently triggers three of these false positives, if you want some real world examples.

Possibly related to #5188 and #1079.

@charliermarsh charliermarsh added bug Something isn't working wish Not on the current roadmap; maybe in the future labels Oct 20, 2023
@dhruvmanila
Copy link
Member

Thanks for opening this issue. Yes, this is the current limitation of linting Notebooks because Ruff considers everything past the IPython escape token (! in this case) as string. The reason being that there's no defined grammar on what can occur in that position and there could be any non-Python syntax as well. This is seen in your first example where bash syntax is being used instead (!echo "Hello $var").

@dhruvmanila
Copy link
Member

Closing in favor of #8354

@tdulcet
Copy link
Author

tdulcet commented Jan 4, 2024

Perhaps this issue should be reopened since #8354 has now been closed, but this bug still exists in Ruff.

@charliermarsh charliermarsh reopened this Jan 4, 2024
@dhruvmanila dhruvmanila added the notebook Related to (Jupyter) notebooks label Feb 12, 2024
@dhruvmanila
Copy link
Member

@tdulcet Can you help me understand the mentioned code? Is it that there can be any valid Python code between the curly braces?

!echo "{<any valid Python code can go here>}"

And, does that need to be wrapped in quotes?

var = "/path/to/foo"
# Does this need to be wrapped in quotes?
!ls {var}

@dhruvmanila
Copy link
Member

dhruvmanila commented Feb 12, 2024

Ok, I just tried this and it seems that it does need to be quoted which makes me wonder if it's treated as format expression with the global scope passed in:

"!ls {var}".format(globals())

I'll look at the source code later to check this.

@tdulcet
Copy link
Author

tdulcet commented Feb 12, 2024

Is it that there can be any valid Python code between the curly braces?

Yes, any valid Python code can be between the braces, except code that contains more braces, so no f-strings or format strings.

And, does that need to be wrapped in quotes?

This specific example does not need to be wrapped in quotes, but in general it does if the variable could contain whitespace or other special characters, to prevent globbing and word splitting by the shell:

var = "/path/to/foo bar" # Variable with whitespace
# This needs to be wrapped in quotes
!ls "{var}"

Note that this is obviously not a robust solution against potenchally malicious inputs, where the string contains quote characters itself:

var = '/path/to/foo"; rm -rf /"'
# Oh no!
!ls "{var}"

In this case, one would likely need to use shlex.quote:

import shlex
var = "/path/to/foo; rm -rf /"
# No quotes needed
!ls {shlex.quote(var)}

@jpmckinney
Copy link

The same issue can can ARG001 e.g.

def foo(var="World"):
    !echo "Hello $var"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working notebook Related to (Jupyter) notebooks wish Not on the current roadmap; maybe in the future
Projects
None yet
Development

No branches or pull requests

4 participants