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

IPython mode: load cell magics from configuration #13977

Open
minrk opened this issue Oct 29, 2024 · 3 comments
Open

IPython mode: load cell magics from configuration #13977

minrk opened this issue Oct 29, 2024 · 3 comments
Labels
configuration Related to settings and configuration notebook Related to (Jupyter) notebooks

Comments

@minrk
Copy link

minrk commented Oct 29, 2024

  • Searched for: cell magics, Jupyter, IPython, configuration, pyproject.toml
  • ruff version: 0.7.1

In handling IPython magics, the list of magics that contain Python code to be checked/formatted is currently hard-coded.

Since loads of extensions (especially profiling, etc.) and even users can define these magics interactively, it seems like the list of cell magics that should be treated as containing Python code should be loaded from configuration, so users can lint their notebooks without a patch to ruff itself.

nbqa has this feature and can be used to run ruff on the contents of arbitrary cell magics, with the same default of assuming unrecognized cell magics don't contain Python code. A similar feature in ruff itself would be great!

Example notebook with the cells:

from IPython import get_ipython


def decorate_cell(line, cell):
    print("before")
    get_ipython().run_cell(cell)
    print("after")

get_ipython().register_magic_function(decorate_cell, "cell")
%%decorate_cell
x = 5
print(x) # <- F821 false positive
@dhruvmanila
Copy link
Member

This seems like a reasonable request to me.

Unlike nbqa, Ruff is able to differentiate between line magics and cell magics. Ruff is able to parse out the line magics and continue parsing any other lines surrounding these line magics. The hard coded values are specific to cell magics and Ruff ignores them because they're applied on the entire cell. I'm sure you're aware of this but just re-iterating for context.

I'd prefer to have an alternate option name like allowed_cell_magics / cell_magics along with the extend_* version to make it clear that this is related to the "cell magics". This option should be at the top level [tool.ruff] because both the linter and the formatter will consider them as is done so today. The non-extend option would have the default value that is hard coded today.

@minrk
Copy link
Author

minrk commented Oct 30, 2024

I'm also not sure if ruff handles it, but cell magics can be arbitrarily nested because the code-running cell magics (many of them anyway) call run_cell, which in turn may call cell magics, etc.. This is a valid cell containing Python code that should be recognized as a candidate for Python formatting assuming prun, time, and timeit are understood to be cell magic functions that accept code:

%%prun
%%time
%%timeit
for i in range(5):
    _env = %env

whereas this one should not format the contents, since sql is not a Python-code cell magic:

%%prun
%%sql
SELECT * FROM TABLE

@dhruvmanila
Copy link
Member

dhruvmanila commented Oct 30, 2024

I think we should handle it correctly because we check if any of the lines contains a cell magic which might not have valid Python code:

// Detect cell magics (which operate on multiple lines).
lines.any(|line| {

So, the two cells that you've provided works fine.

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 notebook Related to (Jupyter) notebooks
Projects
None yet
Development

No branches or pull requests

2 participants