ruff icon indicating copy to clipboard operation
ruff copied to clipboard

Potential inconsistency between Ruff's ``I`` and isort

Open AA-Turner opened this issue 2 years ago • 6 comments

I believe this is distinct from https://github.com/charliermarsh/ruff/issues/1718; cross-linking in case there are similarities, though.

isort version: 5.11.4 Ruff version: 230

isort config:

[tool.isort]
line_length = 95
profile = "black"
remove_redundant_aliases = true

Commands:

(sphinx) PS I:\Development\sphinx> ruff -V        
ruff 0.0.230
(sphinx) PS I:\Development\sphinx> type bug.py                                   
from operator import add  # NoQA: F401
from operator import mul, sub
(sphinx) PS I:\Development\sphinx> ruff --isolated --select I bug.py
bug.py:1:1: I001 Import block is un-sorted or un-formatted
Found 1 error(s).
1 potentially fixable with the --fix option.
(sphinx) PS I:\Development\sphinx> isort --check bug.py 

Note Ruff wants to re-format to:

from operator import (
    add,  # NoQA: F401
    mul,
    sub,
)

whereas isort wants to reformat to:

from operator import add  # NoQA: F401
from operator import mul, sub

This appeared in the Sphinx project where some imports are type-comment only (e.g. in giving type annotations to iterators, where the pattern is for item in items: # type: blah`, should MyPy not be able to deduce the type of item``).

A

AA-Turner avatar Jan 23 '23 08:01 AA-Turner

This does look like an incompatibility. I think the thing to decide is whether it's a known and accepted deviation, or not :)

Do you have a preference between the outputs? Did it cause any problems, or the issue is more that it deviated at all?

charliermarsh avatar Jan 23 '23 17:01 charliermarsh

Personally, I like Ruff's variant more as it keeps imports from a specific module in one statement. I don't know if the noqa comment applies properly in both cases though.

Jackenmen avatar Jan 23 '23 18:01 Jackenmen

Ruff will respect that noqa in both cases, but I don't think Flake8 respects the version that Ruff outputs.

charliermarsh avatar Jan 23 '23 18:01 charliermarsh

the issue is more that it deviated at all?

This is the case for me, we run both isort and Ruff in continuous integration testing so either will fail unless an ungainly isort: skip or ruff-specific NoQA comment were added.

I don't particularly mind which style 'wins'.

A

AA-Turner avatar Jan 24 '23 00:01 AA-Turner

I prefer isort's output here as it is more granular for the ignores/disables to work. pylint for example cannot work with inlined-disables. Take this code for example, from a codebase that I work with:

from dvc.api.data import open  # pylint: disable=redefined-builtin
from dvc.api.data import read

__all__ = ["read", "open"]

ruff changes it to:

--- script.py
+++ script.py
@@ -1,4 +1,6 @@
-from dvc.api.data import open  # pylint: disable=redefined-builtin
-from dvc.api.data import read
+from dvc.api.data import (
+    open,  # pylint: disable=redefined-builtin
+    read,
+)
 
 __all__ = ["read", "open"]

And, pylint now fails:

script.py:1:0: W0622: Redefining built-in 'open' (redefined-builtin)

skshetry avatar Jan 29 '23 11:01 skshetry

Yeah I think we should likely change this going forward given the handling of action comments.

charliermarsh avatar Jan 29 '23 17:01 charliermarsh

pylint for example cannot work with inlined-disables.

Sure it can, you just need to move the comment to the right line.

from dvc.api.data import (  # pylint: disable=redefined-builtin
    open,
    read,
)

__all__ = ["read", "open"]

Ruff can’t be sure in advance which line the comment belongs on (and honestly, its first guess makes more sense), but once you put it on the right line, Ruff will leave it there.

andersk avatar Aug 02 '23 22:08 andersk

I'm going to close this for now as an intentional deviation. If we receive more reports or more feedback on it, as always, I'll reconsider.

charliermarsh avatar Jan 10 '24 21:01 charliermarsh