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:
- setup the example file with name
main.pyi (file extension is important)
from typing import Any
class Bar:
def foo(self, arg: Any) -> bytes: ...
- 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"
}
- 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 (View→Output, 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
Environment data
python.languageServersetting: pylanceExpected behaviour
Formatting a
.pyifile withblackandisortsetup works the same as the command lineActual behaviour
Formatting a
.pyifile results in the formatting changing on each save, flipping between two different stylesSteps to reproduce:
main.pyi(file extension is important)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" }Should switch between the different formatting each save.
I think this is due to a conflict between
isortandblackthat only appearsbecause
isortis getting its input via stdin so it doesn't knowthe file is a
.pyifile, whileblackgets its input via a path so it knowsit's a
.pyifile.We can demonstrate this behavior manually by replicating the commands the
extension is running.
On the command line
blackandisortdon't output a diff:However, if we pass the content to
isortvia stdin it doesn't knowit's a
.pyifile and formats it differently:This diff can also be produced by changing the extension to
.pyWhen this diff is applied it conflicts with black, because like
isort,blackhas special handling for.pyifiles.conclusion
I think similar to how the python extension calls
blackon the file,isortalso needs to be called on the file to ensure it handles the differencebetween
.pyand.pyifiles.rel:
vscode-python/src/client/providers/importSortProvider.ts
Lines 168 to 173 in 329292c
rel: #9128
Logs
Output for
Pythonin theOutputpanel (View→Output, change the drop-down the upper-right of theOutputpanel toPython)