26

I installed yapf using:

conda install yapf

and add next lines in my .vscode/settings.json file:

{
    //"python.linting.pylintEnabled": true,
    //"python.linting.pycodestyleEnabled": false,
    //"python.linting.flake8Enabled": true,
    "python.formatting.provider": "yapf",
    "python.formatting.yapfArgs": [
        " — style",
        "{based_on_style: pep8, indent_width: 4}"
    ],
    "python.linting.enabled": true,
}

But I can't understand how to use it - it doesn't show any error in a bad-formatted script:

import pandas as pd

class MyClass(object):
    def __init__(self, some_value: int):
        self.value = some_value
    def one_more_function(self, another_value):
        print(another_value)
myObject = MyClass(45)
myObject.one_more_function(2)
my__object2 = MyClass(324)

    print('ok')
def some_foo():
    """
    """
    pass
Mikhail_Sam
  • 10,602
  • 11
  • 66
  • 102

4 Answers4

37

The problem was in wrong settings. To use yapf, black or autopep8 you need:

  1. Install yapf / black / autopep8 (pip install black)
  2. Configure .vscode/settings.json in the next way:

part of the file:

{
    "python.linting.enabled": true,
    "python.linting.pylintPath": "pylint",
    "editor.formatOnSave": true,
    "python.formatting.provider": "yapf", // or "black" here
    "python.linting.pylintEnabled": true,
}

Key option - "editor.formatOnSave": true, this mean yapf formats your document every time you save it.

Mikhail_Sam
  • 10,602
  • 11
  • 66
  • 102
  • 6
    About the yapfArgs, it should be typed like this `"python.formatting.yapfArgs": ["--style={based_on_style: pep8, indent_width: 4}"],` – fredrik Apr 28 '20 at 08:42
  • 1
    I agree that the key solution was you needed `"editor.formatOnSave": true`, but want to point out your question was on using yapf is vscode and then your solution uses black, a different autoformatter. Glad you got autoformatting on save up in a way that works for you though. Black is great too. – Max Power Jul 30 '20 at 14:00
  • 1
    @MaxPower Hi! You are right, looks like I tried black and then post the answer :) I suppose, changing "black" to "yapf" should works. – Mikhail_Sam Jul 30 '20 at 14:15
  • This didn't work for me (on Linux). `Ctrl + Shift + I` formats, but not using the rules I define. For example, using `"python.formatting.yapfArgs": ["--style={column_limit: 80}"],` breaks a long line at the first `(`, but the newly created, indented line passes the 80 character mark. I can't think of any extension that would be prohibiting my intended behavior. – Matt McCarthy Oct 21 '20 at 22:53
  • I also tried defining a config file at `~/.config/yapf/style`, which allows files to be formatted correctly at the command line, but not within VS Code. Omitting the `settings.json` line above has no effect. – Matt McCarthy Oct 21 '20 at 23:00
  • the `,` in `"python.linting.pylintEnabled": true,` should be removed – Paolo Oct 31 '20 at 23:54
20

Extending @Mikhail_Sam answer. You might want to use a separate config file as I like. This way you are decoupling your project settings from VS Code IDE. To do this you need to create .style.yapf:

type null > .style.yapf   (for windows environment)
touch .style.yapf    (for MacOS, Linux environments)

Add rules to .style.yapf, for example:

[style]
based_on_style = google
spaces_before_comment = 4
indent_width: 2
split_before_logical_operator = true
column_limit = 80

Don't forget to remove from your VS code settings.json the following setting. They override .style.yapf:

"python.formatting.yapfArgs": [
  "--style={based_on_style: google, column_limit: 80, indent_width: 2}"
],

My other VS Code settings in settings.json:

"[python]": {
  "editor.defaultFormatter": "ms-python.python",
  "editor.formatOnSave": true
},
"python.formatting.provider": "yapf",
"python.formatting.yapfPath": "C:\\ProgramData\\envCondaPy379\\Scripts\\yapf.exe",
"python.formatting.blackPath": "C:\\ProgramData\\envCondaPy379\\Scripts\\black.exe",
"python.linting.lintOnSave": true,
"python.linting.enabled": true,
"python.linting.pylintPath": "pylint",
"python.linting.pylintEnabled": true,

According to the YAPF documentation: YAPF will search for the formatting style in the following manner:

  1. Specified on the command line >> VS Code settings.json
  2. In the [style] section of a .style.yapf file in either the current directory or one of its parent directories.
  3. In the [yapf] section of a setup.cfg file in either the current directory or one of its parent directories.
  4. In the [style] section of a ~/.config/yapf/style file in your home directory.
  5. If none of those files are found, the default style is used (PEP8).
Roman
  • 19,236
  • 15
  • 93
  • 97
  • 1
    This was very helpful for me. Is there a way to see what will be changed before saving? I prefer to make the changes myself so that in time I get used to just writing it correctly in the first place instead of relying on a formatter that does it on saving... – Dieter Vansteenwegen ON4DD May 05 '21 at 08:40
  • I did not research this matter – Roman May 05 '21 at 13:10
  • 1
    Mine was broken because the linter wasn't working until I installed `pylint` and told it to use `pylint`. Thanks for the help. – Andria Sep 12 '21 at 23:51
  • 1
    @DieterVansteenwegenON4DD in VS Code editor you can click right-click and choose from context menu "Format Document" or if you've selected some code "Format Selection" menu option. These two commands will format code with 'yapf' settings. You can cancel formatting by pressing Ctrl + Z – hotenov Nov 01 '21 at 06:06
  • It started working after installing `pylint` – gdf31 Nov 25 '22 at 19:28
  • limitation: [yapf does not format quotes](https://github.com/google/yapf/issues/399) – milahu Mar 23 '23 at 17:32
4

Answer from 2022

If you prefer a 'GUI', you can also enter these values under settings (File->Preferences->Settings) directly:

enter image description here

tkazik
  • 919
  • 3
  • 12
  • 27
0

May be another reason.

About this part code:

import pandas as pd

class MyClass(object):
    def __init__(self, some_value: int):
        self.value = some_value
    def one_more_function(self, another_value):
        print(another_value)
myObject = MyClass(45)
myObject.one_more_function(2)
my__object2 = MyClass(324)

    print('ok')
def some_foo():
    """
    """
    pass

I directly format it with yapf CLI, it says:

yapf: t.py:12:4: unexpected indent

That means: the print('ok') line has wrong indent, which causes the yapf not work.

When I change the right indent, it worked.

SWHL
  • 1
  • 1