ruff icon indicating copy to clipboard operation
ruff copied to clipboard

F821 (undefined imports) false positives (?) in notebooks when using the %run magic

Open tvatter opened this issue 2 years ago • 3 comments

Context

I have a setup file (e.g., IPython magic, display options for pandas, Seaborn visualization settings, etc) which I then import with the %run magic to avoid copy-pasting and making sure my settings are consistent between the different notebooks. Unfortunately, it leads to F821 (undefined imports) in the notebooks, which kinda defeats the purpose.

Question

Is it a false positive? And if not, what is the proper way of achieving this sort of setup across a collection of notebooks while avoiding lintter/formatter errors?

MWE

Let's say I have a file called mwe_setup.py that contains:

import matplotlib.pyplot as plt

And then a file called mwe.ipynb that contains a single code cell

%run mwe_setup.py
fig, ax = plt.subplots()

Then running ruff check mwe.ipynb results inF821 Undefined name `plt`.

tvatter avatar Jan 26 '24 09:01 tvatter

@charliermarsh Is the fix you wrote for #9648 also supposed to deal with my issue? I still see the false positives unfortunately.

Or had @MichaReiser labelled this as "wish" because imports through the %run magic are known to not be supported by ruff? In which case, what would be a good workaround?

tvatter avatar Jan 30 '24 07:01 tvatter

The challenge is that it requires multi file analysis that ruff doesn't support yet. The analyzer needs to stop when seeing %run mwe_setup.py, analyze the file (if it hasn't done so already) and merge the scope of the current file with the scope of mwe_setup.py. We aren't there yet.

For now, you can try to use https://docs.astral.sh/ruff/settings/#builtins and define plt as a builtin. This has the downside that ruff will never warn about plt not being defined, even if the %run mwe_setup.py is missing.

MichaReiser avatar Jan 30 '24 08:01 MichaReiser

I'm guessing that my issue is similar to star imports (#8569) as I had also tried this. Looking forward to see the multi file analysis in ruff, this tool is awesome!

Anyway, for my set of notebooks, I use a ruff.toml file containing e.g.

[lint.per-file-ignores]
"mwe_setup.py" = ["F401"]

to avoid having ruff erase the imports I make in the setup file. Thus, your solution seems like OK as a temporary workaround. I just have to make sure my mwe_setup.py and ruff.toml are "synced", but it's less work than updating every notebook in a collection.

tvatter avatar Jan 30 '24 08:01 tvatter