Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format on save with black isn't working #229

Closed
eulertour opened this issue Dec 30, 2020 · 36 comments
Closed

Format on save with black isn't working #229

eulertour opened this issue Dec 30, 2020 · 36 comments

Comments

@eulertour
Copy link

When saving a file, [coc.nvim] Formatted with black is printed, but the file isn't changed. Running call CocAction('format') also prints the message, but the file is then updated. The output from :CocCommand workspace.showOutput is as follows:

########## active formattor: black
execPath:   black
moduleName: black
args:       --diff,--quiet,/home/devneal/github/manim/manim/mobject/mobject.py.2c210016803c1db7200eb6ec681835ba.py

########## black output:
--- /home/devneal/github/manim/manim/mobject/mobject.py.2c210016803c1db7200eb6ec681835ba.py	2020-12-30 05:10:36.386043 +0000
+++ /home/devneal/github/manim/manim/mobject/mobject.py.2c210016803c1db7200eb6ec681835ba.py	2020-12-30 05:10:37.032054 +0000
@@ -1317,8 +1317,10 @@
 
         self.method = getattr(self.mobject.generate_target(), method_name)
 
         def build(*method_args, **method_kwargs):
             self.method(*method_args, **method_kwargs)
-            return _MethodAnimation(self.mobject, self.method, method_args,                method_kwargs)
+            return _MethodAnimation(
+                self.mobject, self.method, method_args, method_kwargs
+            )
 
         return build

It seems like a temp file may be being formatted instead of the actual file, but I don't know if this is expected.

@fannheyward
Copy link
Owner

It's expected, a temp file is created and formatted with black. coc-pyright will parse and apply the output to the origin file and delete the temp file.

Looks like there is something block format-on-save.

@eulertour
Copy link
Author

eulertour commented Dec 30, 2020

The file is updated when running call CocAction('format') and when saved with coc-python. Do you have any pointers on how to start debugging?

@eulertour
Copy link
Author

All of the characteristics in the first comment are still present when running nvim -u mini.vim <file>, where mini.vim is

  set nocompatible
  set runtimepath^=/path/to/coc.nvim
  set runtimepath^=/path/to/coc-pyright
  filetype plugin indent on
  syntax on
  set hidden

@fannheyward
Copy link
Owner

@eulertour format on save does the same thing as call CocAction('format').

@eulertour
Copy link
Author

eulertour commented Dec 31, 2020

I've found that the formatting consistently fails when editing the original file (which is around 1300 lines), but will consistently format when it's around 10 lines. There's also a length around 850 lines where saving will sometimes format and sometimes not. call CocAction('format') works regardless of length.

This leads me to believe there's some sort of race occurring, does that sound possible?

@fannheyward
Copy link
Owner

I think I found the reason, here is the formatting steps:

  1. coc checks whether there is a formatProvider
  2. coc requests formattingEdits
  3. language server returns formattingEdits. Pyright doesn't support formatting, so coc-pyright runs Black/X with Python to get the formatted document, returns formattingEdits
  4. coc applies the edits to document

The different between format-onsave and CocAction('format') is: format-onsave has a timer cancel token, timer is 1000ms, when the timer fired, coc will cancel the formatting request. Black formatter properly not finished in 1000ms, it's canceled
. https://github.com/neoclide/coc.nvim/blob/master/src/handler/format.ts#L50

The time limit is needed because it's called on save.

@eulertour
Copy link
Author

Would adding an option to disable the creation and deletion of the temp file and instead format the file directly help with the runtime? This issue never occurred using coc-python.

@fannheyward
Copy link
Owner

@eulertour
Copy link
Author

Would adding an option to disable it help with the runtime? Or is there anything else coc-pyright does differently that might contribute to a longer runtime?

@fannheyward
Copy link
Owner

The formatting works properly same as coc-python, and I don't think it will make any improvement to disable the temp file. I'll dig and improve the formatting.

@climbus
Copy link

climbus commented Jan 3, 2021

I have same issue on raspberrypi. On save i get only message but call ... works fine (with any file length).

@nautilor
Copy link

nautilor commented Jan 3, 2021

I solved the issue of formatting on save by installing pyls-black

pip3 install --user pyls-black

in my coc-settings.json I also have

{
   "python.formatting.provider": "black",
   "languageserver": {
     "python": {
       "formatting": {
         "provider": "black"
      },
    "black": {
      "enabled": true
    }
}

don't know if the config helps, but with this config and pyls-black installed when I save the file gets formatted without manually having to call call CocAction('format')

@danielfalbo
Copy link

On my machine, with minimal init.vim

call plug#begin('~/.config/nvim/autoload/plugged')
Plug 'neoclide/coc.nvim', { 'branch': 'release' }
call plug#end()

let g:coc_global_extensions = [ 'coc-pyright' ]

and no coc-settings.json, if I open a .py file and run :call CocAction('format'), it says [coc.nvim] Formatted with autopep8 but it does not really format the file.... and the funny thing is that I don't even have autopep8 on my machine 😅

which autopep8 prints autopep8 not found and pip3 uninstall autopep8 prints WARNING: Skipping autopep8 as it is not installed.

I also tried installing autopep8 with both pip3 install autopep8 and pip3 install autopep8 --user but none of them worked... I always get [coc.nvim] Formatted with autopep8 but without really formatting the document

@swizzard
Copy link

swizzard commented Jan 4, 2021

aug python
  au!
  au BufWrite *.py call CocAction('format')
aug END

in my .nvimrc file worked for me

@danielfalbo
Copy link

danielfalbo commented Jan 4, 2021 via email

@swizzard
Copy link

swizzard commented Jan 4, 2021 via email

@danielfalbo
Copy link

I think I'll keep both coc-pyright and coc-python until formatting with autopep8 is fixed here: autopep8 with coc-python works as expected and does not affect coc-pyright's other features like CocActionAsync('highlight') that do not work with coc-python

@swizzard
Copy link

swizzard commented Jan 4, 2021 via email

@danielfalbo
Copy link

Tried the aug solution but didn't work :/

Anyway, this is the :CocCommand workspace.showOutput-> coc-pyright-formatting output:

########## active formattor: autopep8
execPath:   autopep8
moduleName: autopep8
args:       --diff,/Users/danielfalbo/Downloads/codewars/sol.py.06efb6cfab4b97027ddb4f1e19495c64.py
########## Formatting with autopep8 failed
Formatting with autopep8 failed. autopep8 module is not installed.
Module 'autopep8' not installed.

seems like it doesn't find autopep8, but this time it is in my PATH so I don't know where could the bug be...

@yaegassy
Copy link
Contributor

yaegassy commented Jan 5, 2021

@danielfalbo

I usually use black, but it's been a while since I've tried autopep8.

It worked fine in my environment.

Install autopep8 in your project's "venv", or try setting python.formatting.autopep8Path correctly

Example: coc-settings.json

{
  // ...snip
  "python.formatting.provider": "autopep8",
  "python.formatting.autopep8Path": "~/.local/bin/autopep8",
  // ...snip
}

As a supplement, I also tried yapf, and it worked fine.


If there are any other problems with autopep8, it may be better to open a new issue. (Since this issue is about "black formatter")

@danielfalbo
Copy link

Setting "python.formatting.autopep8Path" in the coc-settings.json solves my issue, thank you 👍

@yaegassy
Copy link
Contributor

yaegassy commented Jan 5, 2021

In my environment, I tried black in [deprecated] coc-python and the same symptoms occurred.

To make it easier to share the situation, I verified it with this python file of about 700 lines from django. https://github.com/django/django/blob/master/django/http/request.py

The same is true for black in "coc-python", so you may need to refer to the vscode-python source. https://github.com/microsoft/vscode-python/blob/main/src/client/formatters/baseFormatter.ts

@yaegassy
Copy link
Contributor

yaegassy commented Jan 5, 2021

It's a "workaround".

Adding --fast to python.formatting.blackArgs worked fine on my environment, even on save.

{
  // ...snip
  "python.formatting.provider": "black",
  "python.formatting.blackPath": "~/.local/bin/black",
  "python.formatting.blackArgs": ["--diff", "--quiet", "--fast"],
  // ...snip
}

@yaegassy
Copy link
Contributor

yaegassy commented Jan 5, 2021

Oh..., I added --fast, but it still didn't work for a file of about 1200 lines. :(
Ref: https://github.com/django/django/blob/master/django/contrib/admin/checks.py

@fannheyward
Copy link
Owner

I'm working on add blackd as formatter, #296. In my tests, blackd is about 25% faster than black.

@yaegassy
Copy link
Contributor

yaegassy commented Feb 4, 2021

I tried the feat/blackd branch.

I have confirmed that POST with 'X-Fast-Or-Safe': 'fast' in the headers is even faster.

@yaegassy
Copy link
Contributor

yaegassy commented Feb 4, 2021

There was a behavior in blackd that bothered me.

I don't know if this is a bug in blackd itself or a specification, but even if I put pyproject.toml in the project root, blackd didn't seem to respect that setting. https://black.readthedocs.io/en/stable/pyproject_toml.html

e.g. pyproject.toml

[tool.black]
line-length = 120

@yaegassy
Copy link
Contributor

yaegassy commented Feb 4, 2021

Oh... It seemed to be a specification of blackd. https://github.com/psf/black#where-black-looks-for-the-file

Please note blackd will not use pyproject.toml configuration.

@fannheyward
Copy link
Owner

blackd support has been merged into master.

@fannheyward
Copy link
Owner

I'm going to close this.

@metal3d
Copy link

metal3d commented Feb 21, 2021

I also have the problem. Note that black now hides the string split with a special option.

My confinguration is:

{
//...
    "python.formatting.provider": "black",
    "python.formatting.blackArgs": ["--quiet" , "--experimental-string-processing"]
//...
}

Whatever I do, the only way to autoformat is to use call CocAction('format'). It doesn't work "on save" (and it's very disapointing)

PS: blackd isn't the choice I want as it doesn't respect 88 chars for line length.

@metal3d
Copy link

metal3d commented Feb 21, 2021

blackd doesn't changes anything, the autoformat isn't made on save

@metal3d
Copy link

metal3d commented Feb 21, 2021

OK. actually there isn't any autoformat for python which works on save...

@fannheyward
Copy link
Owner

@metal3d check :CocCommand workspace.showOutput - coc-pyright-formatting. It's because coc runs formatOnSave with a time limit, formatter like black doesn't finish in the limit, coc cancels formatting.

Use something like this au au BufWrite *.py call CocActionAsync('format').

@metal3d
Copy link

metal3d commented Feb 24, 2021

This is what I finally did @fannheyward - but unfortunately, I had got other problems to use coc-pyright that made me use coc-jedi instead :(
Thanks for your answers

@fannheyward
Copy link
Owner

The latest coc has added coc.preferences.willSaveHandlerTimeout, you can increase this time limitation.

klaseskilson pushed a commit to klaseskilson/dotfiles that referenced this issue May 22, 2023
Manually triggering the save seems to have done the trick.

Workaround sourced here: fannheyward/coc-pyright#229 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants