Skip to content

Sorting imports with isort conflicts with .pyi files #14702

Description

@sbdchd

Environment data

  • VS Code version: 1.51.1
  • Extension version (available under the Extensions sidebar): 2020.11.358366026
  • OS and version: Mac OS 10.15.6
  • Python version (& distribution if applicable, e.g. Anaconda): 3.7.0
  • Type of virtual environment used (N/A | venv | virtualenv | conda | ...): venv
  • Relevant/affected Python packages and their versions: isort=5.6.4, black=20.8b1
  • Relevant/affected Python-related VS Code extensions and their versions: Python extension
  • Value of the python.languageServer setting: pylance

Expected behaviour

Formatting a .pyi file with black and isort setup works the same as the command line

Actual behaviour

Formatting a .pyi file results in the formatting changing on each save, flipping between two different styles

Steps to reproduce:

  1. setup the example file with name main.pyi (file extension is important)
from typing import Any

class Bar:
    def foo(self, arg: Any) -> bytes: ...
  1. ensure black and isort are setup

settings.json

{
  "python.pythonPath": ".venv/bin/python",
  "python.formatting.provider": "black",
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.organizeImports": true
  },
  "python.sortImports.path": "${workspaceFolder}/.venv/bin/isort",
  "python.formatting.blackPath": "${workspaceFolder}/.venv/bin/black"
}
  1. save the file and watch

Should switch between the different formatting each save.
I think this is due to a conflict between isort and black that only appears
because isort is getting its input via stdin so it doesn't know
the file is a .pyi file, while black gets its input via a path so it knows
it's a .pyi file.

We can demonstrate this behavior manually by replicating the commands the
extension is running.

On the command line black and isort don't output a diff:

./.venv/bin/black main.pyi --diff --quiet
./.venv/bin/isort --profile=black main.pyi --diff

However, if we pass the content to isort via stdin it doesn't know
it's a .pyi file and formats it differently:

❯ cat main.pyi | ./.venv/bin/isort --profile=black - --diff
--- :before	2020-11-11 22:48:00.874612
+++ :after	2020-11-11 22:48:00.874650
@@ -1,4 +1,5 @@
 from typing import Any
+
 
 class Bar:
     def foo(self, arg: Any) -> bytes: ...

This diff can also be produced by changing the extension to .py

When this diff is applied it conflicts with black, because like isort, black has special handling for .pyi files.

conclusion

I think similar to how the python extension calls black on the file,
isort also needs to be called on the file to ensure it handles the difference
between .py and .pyi files.

rel:

// We pass the content of the file to be sorted via stdin. This avoids
// saving the file (as well as a potential temporary file), but does
// mean that we need another way to tell `isort` where to look for
// configuration. We do that by setting the working directory to the
// directory which contains the file.
const filename = '-';

rel: #9128

Logs

Output for Python in the Output panel (ViewOutput, change the drop-down the upper-right of the Output panel to Python)

> ~/projects/foo/.venv/bin/isort - --diff --profile black
cwd: ~/projects/foo/typings
> ~/projects/foo/.venv/bin/black --diff --quiet ~/projects/foo/typings/main.pyi
cwd: ~/projects/foo
> ~/projects/foo/.venv/bin/python ~/.vscode/extensions/ms-python.python-2020.11.358366026/pythonFiles/pyvsc-run-isolated.py flake8 --format=%(row)d,%(col)d,%(code).1s,%(code)s:%(text)s ~/projects/foo/typings/main.pyi
cwd: ~/projects/foo
> ~/projects/foo/.venv/bin/python ~/.vscode/extensions/ms-python.python-2020.11.358366026/pythonFiles/pyvsc-run-isolated.py flake8 --format=%(row)d,%(col)d,%(code).1s,%(code)s:%(text)s ~/projects/foo/typings/main.pyi
cwd: ~/projects/foo
> ~/projects/foo/.venv/bin/python ~/.vscode/extensions/ms-python.python-2020.11.358366026/pythonFiles/pyvsc-run-isolated.py mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers ~/projects/foo/typings/main.pyi
cwd: ~/projects/foo
> ~/projects/foo/.venv/bin/python ~/.vscode/extensions/ms-python.python-2020.11.358366026/pythonFiles/pyvsc-run-isolated.py mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers ~/projects/foo/typings/main.pyi
cwd: ~/projects/foo
##########Linting Output - flake8##########
##########Linting Output - mypy##########
Success: no issues found in 1 source file

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-formattingbugIssue identified by VS Code Team member as probable bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions