ruff-pycharm-plugin icon indicating copy to clipboard operation
ruff-pycharm-plugin copied to clipboard

Wrong sorting of imports

Open hexvolt opened this issue 1 year ago • 25 comments
trafficstars

Describe the bug The sorting of imports is not consistent with ruff CLI output.

The plugin is awesome but when it is enabled, it highlights the imports that are sorted properly by categories. If I reformat the code using the plugin, it rearranges the imports in some weird order (3rd party packages being mixed with the local code packages), which is totally different from what ruff check --select I --fix does. So if sort imports properly with the external command ruff check --select I --fix, then the plugin complains on my imports and tries to rearrange them back.

So in order to use the plugin I have to either cope with seeing yellow highlights on all (properly sorted) imports, or give up proper sorting and let plugin do the weird sorting.

To Reproduce Steps to reproduce the behavior:

  1. Open a python file of any project, that has imports of 3rd party packages, as well as Python built-ins, and imports of local code
  2. Reformat the code using the plugin.
  3. See how the order of imports are mixed up, and the categories are NOT maintained properly (built-ins, 3rd-party, local)
  4. Now in the CLI run the official ruff command for sorting imports ruff check --select I --fix
  5. See how the imports got sorted properly.

Expected behavior The plugin should yield the same results of imports sorting as the official ruff command ruff check --select I --fix.

Screenshots image You can see how imports sorted properly by the ruff check --select I --fix command are highlighted by the plugin with yellow, while it shouldn't.

image

And this is the order plugin thinks is correct but it's not.

Environments (please complete the following information):

  • IDE: PyCharm 2024.1 (Professional Edition)
  • OS: MacOS Sonoma 14.4
  • Ruff Version 0.1.15
  • Plugin version 0.0.33

Notes:

  • The plugin sees the pyproject.toml file (specified in the settings).
  • There is nothing in my pyproject.toml file about custom sorting rules or anything like that.

UPDATE Noteworthy is that if I remove the reference to the pyproject.toml file in the plugin settings, it does sorting correctly. But in that case it ignores all other settings like line length etc.

hexvolt avatar Apr 16 '24 17:04 hexvolt

I had this issue when using ruff-lsp. Disabling that option in the plugin settings fixed this.

It seemed that somehow the lsp was not picking up (some of) the options which I set in my pyproject.toml file. I suspect the version of lsprotocol has to do with this, although I did not test this very extensively.

I had the following packages installed (managed by Poetry):

  • ruff: 0.3.7
  • ruff-lsp: 0.0.53
  • lsprotocol: 2023.0.1

Perhaps this could give a starting point for fixing this bug.

jellehierck avatar Apr 18 '24 22:04 jellehierck

Thanks. As to my setup, ruff-lsp is not used.

hexvolt avatar Apr 22 '24 16:04 hexvolt

I'm also seeing this behaviour. @hexvolt Did you find a workaround?

TimChild avatar May 10 '24 20:05 TimChild

@TimChild Nope, unfortunately I have to live with yellow warning around every import block:( To me, this is clearly a pretty major bug, idk why it is not labeled as such yet

hexvolt avatar May 28 '24 16:05 hexvolt

Happens to me as well. Since my imports are now always out of order, I always have to use the command line as well to fix it before I commit any files :(

cm253 avatar Jun 12 '24 09:06 cm253

disabling ruff-lsp option eliminated the massive warning block (thanks @jellehierck). it still organizes on save, so I can make do with that for now.

dpgraham4401 avatar Aug 30 '24 14:08 dpgraham4401

Same issue here, saving/reformatting files changes the import order. Currently I'm just running a tiny script that does a ruff check --fix and ruff format when I'm done changing files. It would be great if the plugin behaviour could be aligned with the CLI interface.

Environments (please complete the following information): IDE: PyCharm 2024.2.1 (Professional Edition) OS: MacOS Sonoma 14.6.1 Ruff Version 0.6.4 Plugin version 0.0.36

jeroenbrouwer avatar Sep 10 '24 08:09 jeroenbrouwer

For me and my team this bug is currently most annoying because we have to reformat the files with the command line, and can not solely rely on the IntelliJ plugin :(

cm253 avatar Sep 11 '24 08:09 cm253

@cm253 I feel your pain. It's a shame @JetBrains haven't implemented their own solution, they seem to have some half-assed integration of ruff, but the way everything works together is we have the entire project flooded with warnings just because of the bug in the imports check. I'm considering disabling code check tools altogether since there is no proper integration with ruff, and I need to use CLI anyway. The fact such a fundamental feature of IDE still does not work properly after ruff being around for 2 years is such a shame.

hexvolt avatar Sep 11 '24 21:09 hexvolt

I wonder if this format support is managed with LSP?

If yes the problem comes from the ruff language server or from LSP4IJ.

If it comes from LSP4IJ I could investigate the problem.

angelozerr avatar Sep 12 '24 11:09 angelozerr

This is my IntelliJ configuration, I don't use Ruff LSP:

image

cm253 avatar Sep 12 '24 11:09 cm253

I wonder if this format support is managed with LSP?

If yes the problem comes from the ruff language server or from LSP4IJ.

If it comes from LSP4IJ I could investigate the problem.

The problem is that the plugin wrongly re-orders imports, the highlighting and detection of the errors is done correctly at all times.

jeroenbrouwer avatar Sep 12 '24 11:09 jeroenbrouwer

Ok thanks for your feedback, I though it was a problem from LSP4IJ and in this case I though I could investigate the problem.

angelozerr avatar Sep 12 '24 11:09 angelozerr

Ok thanks for your feedback, I though it was a problem from LSP4IJ and in this case I though I could investigate the problem.

At least that's the case for me, other users might have a slightly different issue.

jeroenbrouwer avatar Sep 12 '24 11:09 jeroenbrouwer

The problem is that the plugin wrongly re-orders imports, the highlighting and detection of the errors is done correctly at all times.

@jeroenbrouwer no, for me that's not the case unfortunately, please see the screenshots ^

You can see how imports sorted properly by the ruff check --select I --fix command are highlighted by the plugin with yellow, while it shouldn't.

Correctly sorted imports are wrongly highlighted, until I disable the plugin altogether. Which essentially means, either you have no ruff in PyCharm at all (if you don't want false positive highlighting), or you have ruff but wrong highlights.

hexvolt avatar Sep 12 '24 16:09 hexvolt

The problem is that the plugin wrongly re-orders imports, the highlighting and detection of the errors is done correctly at all times.

@jeroenbrouwer no, for me that's not the case unfortunately, please see the screenshots ^

You can see how imports sorted properly by the ruff check --select I --fix command are highlighted by the plugin with yellow, while it shouldn't.

Correctly sorted imports are wrongly highlighted, until I disable the plugin altogether. Which essentially means, either you have no ruff in PyCharm at all (if you don't want false positive highlighting), or you have ruff but wrong highlights.

Then there seem to be multiple issues related to the ordering of imports, hopefully they can all be fixed 🤞

jeroenbrouwer avatar Sep 13 '24 11:09 jeroenbrouwer

I found a workaround that works for my setup. I have a .ruff.toml file at the root of my Python project that looks like this:

line-length = 120

[lint]
select = ["E4", "E7", "E9", "F", "I"]
ignore = ["E721"]

When I click "Reformat Code" in PyCharm, I see the imports being changed twice! First pass is ruff, second pass is PyCharm. I went ahead and disabled "Optimize imports" in the "Reformat File..." dialog. image

Now, whenever I hit "Reformat Code", only ruff re-orders the imports. Seems like the plugin should disable PyCharm's built-in reorder feature whenever it's installed.

jlheureux-omni avatar Oct 10 '24 16:10 jlheureux-omni

I found a workaround that works for my setup. I have a .ruff.toml file at the root of my Python project that looks like this:

line-length = 120

[lint]
select = ["E4", "E7", "E9", "F", "I"]
ignore = ["E721"]

When I click "Reformat Code" in PyCharm, I see the imports being changed twice! First pass is ruff, second pass is PyCharm. I went ahead and disabled "Optimize imports" in the "Reformat File..." dialog. image

Now, whenever I hit "Reformat Code", only ruff re-orders the imports. Seems like the plugin should disable PyCharm's built-in reorder feature whenever it's installed.

This doesn't fix it for me. I also don't see the reordering happening twice.

jeroenbrouwer avatar Oct 18 '24 07:10 jeroenbrouwer

I found a workaround that works for my setup. I have a .ruff.toml file at the root of my Python project that looks like this:

This doesn't fix it for me. I also don't see the reordering happening twice.

Also not for me. I'm using IntelliJ 2024.2.1.

cm253 avatar Oct 18 '24 09:10 cm253

Same issue here - everything formats + sorts correctly until you specify a config file, at which point the import order is incorrectly ordered when reformatted

SerenityCode avatar Oct 24 '24 15:10 SerenityCode

To still get the benefits of ruff integration but disabling the incorrect import checking / fix, create a seperate config file e.g. ruff_pycharm.toml that excludes (or doesn't include) "I", and set this in Pycharm settings > Tools > Ruff > Ruff config file.

It doesn't fix the problem but it makes it more pleasing visually without the nag on the imports section. Use ruff pre-commit to fix the imports.

ctrmcubed avatar Nov 28 '24 12:11 ctrmcubed

If anyone wants to investigate this, I created a shell script that logs the commands sent by the plugin and the results returned by ruff. Save it to the project root (e.g. as log_ruff.sh), make it executable, then configure it as the ruff executable in the plugin:

#!/bin/bash

# Log file path
LOG_FILE="./ruff.log"

# Append the arguments to the log file
echo "Arguments: $@" >> "$LOG_FILE"

# Forward the arguments to .venv/bin/ruff and capture the output
RESULT=$(.venv/bin/ruff "$@")

# Log the result
echo "Result: $RESULT" >> "$LOG_FILE"

# Return the result to the original caller
echo "$RESULT"

Equivalently for Windows (save as e.g. log_ruff.bat):

@echo off
setlocal enabledelayedexpansion

:: Log file path
set LOG_FILE=.\ruff.log
set TEMP_FILE=.\ruff_output.tmp

:: Append the arguments to the log file
echo Arguments: %* >> %LOG_FILE%

:: Forward the arguments to .venv\Scripts\ruff.exe and capture the output
.venv\Scripts\ruff.exe %* > %TEMP_FILE%

:: Log the result
echo Result: >> %LOG_FILE%
type %TEMP_FILE% >> %LOG_FILE%

:: Clean up the temporary file
del %TEMP_FILE%

It helped me notice that the Ruff config file setting was pointing to a different project's pyproject.toml. Perhaps at some point the plugin shared the settings between projects? Who knows...

Dev-iL avatar Dec 24 '24 11:12 Dev-iL

This fixed it for me (in pyproject.toml):

[tool.ruff.lint.isort]
known-first-party = ["your_root_module_name"]

source: https://pycqa.github.io/isort/docs/configuration/options.html#known-first-party

Nomelas avatar Jan 17 '25 19:01 Nomelas

This fixed it for me (in pyproject.toml):

[tool.ruff.lint.isort]
known-first-party = ["your_root_module_name"]

source: https://pycqa.github.io/isort/docs/configuration/options.html#known-first-party

I tested it, and it looks like it also fixed it for me. Will do some more testing.

cm253 avatar Jan 20 '25 09:01 cm253

While this works for me too ...

(ruff.toml equivalent to pyproject.toml

[lint.isort]
known-first-party = [
    "your_module_1",
    "your_module_2",
    # ...
]

Quote from the ruff docs:

A list of modules to consider third-party, regardless of whether they can be identified as such via introspection of the local filesystem.

source: https://docs.astral.sh/ruff/settings/#lint_isort_known-third-party

... it seems to me that this introspection works fine when using ruff format via cli and for the linter but not when using the riff plugin for formatting. At least I didn't specify the "known-first-party" modules anywhere else, but they are detected correctly when using the cli.

robinzachmann avatar Feb 03 '25 09:02 robinzachmann