Git Product home page Git Product logo

python-lsp-ruff's People

Contributors

betaboon avatar ccordoba12 avatar chris-reeves avatar felix-cw avatar jhossbach avatar jspricke avatar kstrauser avatar maerteijn avatar magnuslarsen avatar martinal avatar mmcshane avatar projectgus avatar ryankask avatar shane-xb-qian avatar ttayu avatar tylerlaprade avatar tzachar avatar ultimator14 avatar vodik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-lsp-ruff's Issues

'E501 Line too long': Not showing in-line

I am using the Helix editor with pylsp as the language server and python-lsp-ruff as plugin for ruff. Most diagnostics appear inline in the editor as expected except E501 which is related to line legth. Running ruff directly on the violating file shows the error in the terminal.

ruff test.py
test.py:3:89: E501 Line too long (100 > 88 characters)

The log from pylsp is here:

2023-02-24 12:50:41,955 IST - DEBUG - pylsp.config.config -   pylsp_lint [hook]
      config: <pylsp.config.config.Config object at 0x104791f50>
      workspace: <pylsp.workspace.Workspace object at 0x104830ad0>
      document: file:///Users/rkshthrmsh/ws/sandbox/test.py
      is_saved: True

2023-02-24 12:50:41,956 IST - DEBUG - pylsp.config.config - Got user config from PyCodeStyleConfig: {}
2023-02-24 12:50:41,957 IST - DEBUG - pylsp.config.config - Got project config from PyCodeStyleConfig: {}
2023-02-24 12:50:41,957 IST - DEBUG - pylsp.config.config - With configuration: {'plugins': {'pyflakes': {'enabled': False}, 'pydocstyle': {'enabled': False}, 'rope_rename': {'enabled': False}, 'ruff': {'exclude': None, 'ignore': None, 'select': ['D'], 'lineLength': None, 'perFileIgnores': None, 'executable': 'ruff', 'config': None, 'enabled': True}, 'autopep8': {'enabled': False}, 'flake8': {'enabled': False}, 'preload': {'modules': ['OpenGL', 'PIL', 'array', 'audioop', 'binascii', 'cPickle', 'cStringIO', 'cmath', 'collections', 'datetime', 'errno', 'exceptions', 'gc', 'imageop', 'imp', 'itertools', 'marshal', 'math', 'matplotlib', 'mmap', 'mpmath', 'msvcrt', 'networkx', 'nose', 'nt', 'numpy', 'operator', 'os', 'os.path', 'pandas', 'parser', 'rgbimg', 'scipy', 'signal', 'skimage', 'sklearn', 'statsmodels', 'strop', 'sympy', 'sys', 'thread', 'time', 'wx', 'xxsubtype', 'zipimport', 'zlib']}, 'rope_autoimport': {'enabled': False, 'memory': False}, 'jedi_completion': {'fuzzy': True, 'include_class_objects': True, 'include_function_objects': True}, 'rope_completion': {'enabled': False, 'eager': False}, 'pycodestyle': {'enabled': False}, 'yapf': {'enabled': True}, 'pylint': {'enabled': False, 'args': [], 'executable': None}, 'mccabe': {'enabled': False}}, 'rope': {'extensionModules': ['OpenGL', 'PIL', 'array', 'audioop', 'binascii', 'cPickle', 'cStringIO', 'cmath', 'collections', 'datetime', 'errno', 'exceptions', 'gc', 'imageop', 'imp', 'itertools', 'marshal', 'math', 'matplotlib', 'mmap', 'mpmath', 'msvcrt', 'networkx', 'nose', 'nt', 'numpy', 'operator', 'os', 'os.path', 'pandas', 'parser', 'rgbimg', 'scipy', 'signal', 'skimage', 'sklearn', 'statsmodels', 'strop', 'sympy', 'sys', 'thread', 'time', 'wx', 'xxsubtype', 'zipimport', 'zlib']}}
2023-02-24 12:50:41,958 IST - DEBUG - pylsp_ruff.ruff_lint - Got ruff settings: {'exclude': None, 'ignore': None, 'select': ['D'], 'lineLength': None, 'perFileIgnores': None, 'line_length': 100, 'executable': 'ruff', 'config': None, 'enabled': True}
2023-02-24 12:50:41,958 IST - DEBUG - pylsp_ruff.ruff_lint - Calling ruff with args: ['--quiet', '--format=json', '--no-fix', '--force-exclude', '--stdin-filename', '/Users/rkshthrmsh/ws/sandbox/test.py', '--select=D', '--', '-'] on '/Users/rkshthrmsh/ws/sandbox/test.py'
2023-02-24 12:50:41,971 IST - DEBUG - pylsp.config.config -   finish pylsp_lint --> [[]] [hook]

2023-02-24 12:50:41,972 IST - DEBUG - pylsp_jsonrpc.endpoint - Sending notification: textDocument/publishDiagnostics {'uri': 'file:///Users/rkshthrmsh/ws/sandbox/test.py', 'diagnostics': []}
2023-02-24 12:50:43,477 IST - DEBUG - pylsp_jsonrpc.endpoint - Handling notification from client {'jsonrpc': '2.0', 'method': 'textDocument/didSave', 'params': {'text': '"""Implement CCSDS 123.0-B-2 Compression.\n\nCCSDS 123.0-B-2 specifies a standard for Low-Complexity Lossless and Near-Lossless Multispectral and\nHyper\n"""\n', 'textDocument': {'uri': 'file:///Users/rkshthrmsh/ws/sandbox/test.py'}}}
2023-02-24 12:50:43,480 IST - DEBUG - pylsp.config.config -   pylsp_document_did_save [hook]
      config: <pylsp.config.config.Config object at 0x104791f50>
      workspace: <pylsp.workspace.Workspace object at 0x104830ad0>
      document: file:///Users/rkshthrmsh/ws/sandbox/test.py

2023-02-24 12:50:43,480 IST - DEBUG - pylsp.config.config -   finish pylsp_document_did_save --> [] [hook]

2023-02-24 12:50:43,480 IST - DEBUG - pylsp_jsonrpc.endpoint - Handling request from client {'jsonrpc': '2.0', 'method': 'shutdown', 'params': None, 'id': 1}
2023-02-24 12:50:43,480 IST - DEBUG - pylsp_jsonrpc.endpoint - Got result from synchronous request handler: None
2023-02-24 12:50:43,481 IST - DEBUG - pylsp_jsonrpc.endpoint - Handling notification from client {'jsonrpc': '2.0', 'method': 'exit', 'params': None}

Set up publish action

Continuation from the conversation in #22
Actions intended for publishing for

  • PyPi
  • Anaconda

For PyPi there is a Github Action that we can use. For that I would like to change the ownership of the Pypi package to the python lsp project. Then we can store the credentials for the pylsp Pypi account in Github to be used as action. Can we do this @ccordoba12?

python-lsp-ruff is using the globally installed ruff instead of the one of the virtual environment

My setup is the following

NVIM v0.9.1
pylsp: 1.7.3
ruff: 0.0.267

The issue

Linting a file where I know there are issues does not work.

I've got the following traceback in the log:

2023-05-16 11:18:42,852 CEST - INFO - pylsp.config.config - Updated settings to {'plugins': {'mccabe': {'enabled': False}, 'ruff': {'extendSelect': ['I'], 'enabled': True}}, 'configurationSources': ['flake8']}
2023-05-16 11:18:42,853 CEST - INFO - pylsp.config.config - Disabled plugins: [<module 'pyls_isort.plugin' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pyls_isort/plugin.py'>, <module 'pylsp.plugins.flake8_lint' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/flake8_lint.py'>, <module 'pylsp.plugins.mccabe_lint' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/mccabe_lint.py'>, <module 'pylsp.plugins.pycodestyle_lint' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/pycodestyle_lint.py'>, <module 'pylsp.plugins.pydocstyle_lint' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/pydocstyle_lint.py'>, <module 'pylsp.plugins.pyflakes_lint' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/pyflakes_lint.py'>, <module 'pylsp.plugins.pylint_lint' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/pylint_lint.py'>, <module 'pylsp.plugins.rope_autoimport' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/rope_autoimport.py'>, <module 'pylsp.plugins.rope_completion' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/rope_completion.py'>, <module 'pylsp.plugins.rope_rename' from '/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/plugins/rope_rename.py'>]
2023-05-16 11:18:43,386 CEST - WARNING - pylsp.config.config - Failed to load hook pylsp_lint: While structuring typing.List[pylsp_ruff.ruff.Check] (1 sub-exception)
  + Exception Group Traceback (most recent call last):
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp/config/config.py", line 33, in _hookexec
  |     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_manager.py", line 327, in traced_hookexec
  |     return outcome.get_result()
  |            ^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_result.py", line 60, in get_result
  |     raise ex[1].with_traceback(ex[2])
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_result.py", line 33, in from_call
  |     result = func()
  |              ^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_manager.py", line 324, in <lambda>
  |     lambda: oldcall(hook_name, hook_impls, kwargs, firstresult)
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_callers.py", line 60, in _multicall
  |     return outcome.get_result()
  |            ^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_result.py", line 60, in get_result
  |     raise ex[1].with_traceback(ex[2])
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39, in _multicall
  |     res = hook_impl.function(*args)
  |           ^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp_ruff/plugin.py", line 125, in pylsp_lint
  |     checks = run_ruff_check(workspace, document)
  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/pylsp_ruff/plugin.py", line 354, in run_ruff_check
  |     return converter.structure(result, List[RuffCheck])
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/cattrs/converters.py", line 309, in structure
  |     return self._structure_func.dispatch(cl)(obj, cl)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/cattrs/converters.py", line 510, in _structure_list
  |     raise IterableValidationError(
  | cattrs.errors.IterableValidationError: While structuring typing.List[pylsp_ruff.ruff.Check] (1 sub-exception)
  +-+---------------- 1 ----------------
    | Exception Group Traceback (most recent call last):
    |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/cattrs/converters.py", line 502, in _structure_list
    |     res.append(handler(e, elem_type))
    |                ^^^^^^^^^^^^^^^^^^^^^
    |   File "<cattrs generated structure pylsp_ruff.ruff.Check>", line 35, in structure_Check
    |     if errors: raise __c_cve('While structuring ' + 'Check', errors, __cl)
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | cattrs.errors.ClassValidationError: While structuring Check (1 sub-exception)
    | Structuring typing.List[pylsp_ruff.ruff.Check] @ index 0
    +-+---------------- 1 ----------------
      | Exception Group Traceback (most recent call last):
      |   File "<cattrs generated structure pylsp_ruff.ruff.Check>", line 31, in structure_Check
      |     res['fix'] = __c_structure_fix(o['fix'], __c_type_fix)
      |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |   File "/home/nicoe/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.11/site-packages/cattrs/converters.py", line 574, in _structure_optional
      |     return self._structure_func.dispatch(other)(obj, other)
      |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |   File "<cattrs generated structure pylsp_ruff.ruff.Fix>", line 14, in structure_Fix
      |     if errors: raise __c_cve('While structuring ' + 'Fix', errors, __cl)
      |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      | cattrs.errors.ClassValidationError: While structuring Fix (1 sub-exception)
      | Structuring class Check @ attribute fix
      +-+---------------- 1 ----------------
        | Traceback (most recent call last):
        |   File "<cattrs generated structure pylsp_ruff.ruff.Fix>", line 5, in structure_Fix
        |     res['edits'] = __c_structure_edits(o['edits'], __c_type_edits)
        |                                         ~^^^^^^^^^
        | KeyError: 'edits'
        | Structuring class Fix @ attribute edits
        +------------------------------------

I tried using an older version of ruff but it didn't work (I haven't tested with older version of pylsp because uninstalling python-lsp-ruff did bring the linting back).

fixall should consider range

'fix all' of code action should consider the range,
the statement in def pylsp_code_actions( :

    range : Dict
        Range argument given by pylsp. Not used here.

should be not true, this range i guess should be used later in checks_with_fixes to filter fixes only in this range.
otherwise 'fix all' probably in the action list all the time, but that actually maybe would get action nothing from it.

Ruff 0.2.0 Support

This package currently supports ruff 0.1.* but not 0.2.0. Reading through the release blog post it looks like there are no changes that will cause problems, so it should be safe to relax the dependency to "ruff>=0.1.5, <0.3.0"

Support `ruff format`

Hi, as far as I can see, the new ruff formatter comparable to black is not yet supported by this plugin. If I understand it correctly, the term "format" in the code of this repo relates to fixing errors. Would it be possible to add formatting (in the sense of black) as a new code action?

Handling of isort-related errors and other autofix codes

With #25 being merged soon, the question remains whether formatting should be enabled by default and error codes should be given to be auto-fixed when running formatting.
I don't really mind on or the other, so I'm open to suggestions.

If e.g. isort-codes should be used for formatting per default, we should also disable pylsp-isort.

Syntax errors not being shown when `select` is present in pyproject.toml

Hello, giving this a go, and i am running into this strange situation where Syntax errors stop being shown if the pyproject.toml file contains a select = line.

without:

E class CustomFilter(PythonFilter):)))     โ– โ–  SyntaxError: Unexpected token ')'
      ignore_dirs = ["__pycache__"]

with:

  class CustomFilter(PythonFilter):)))
      ignore_dirs = ["__pycache__"]

command line version works with the config file, so it's not a typo issue.

configuration is recommended lspconfig and

local lspconfig = require('lspconfig')
lspconfig.pylsp.setup {
  plugins = {
    ruff = {
      enabled = true,
    },
  }
}

extendSelect also doesn't seem to work.

Ruff.toml support

Hi,
Is config option for this project also applies for ruff.toml or only for pyproject.toml? If not, is it possible to have possibility to pass ruff.toml instead of pyproject.toml?

Should custom config override local pyproject.toml / ruff.toml?

Currently, when custom config is set during setup, project-local configuration files are ignored. I wonder whether this behavior is the result of an explicit design decision, or if it is open for discussion and subject to change. I imagined the setting to be a default config, used not to set the same settings across all projects, but to separate the configuration of LSP and Ruff and overridden by local settings.

No diagnostics when upgrading from python-lsp-ruff 1.2.0

I've been using python-lsp-server 1.7.x and python-lsp-ruff 1.2.0 with Emacs 29 and eglot since January or thereabouts, and it's been a great experience. I recently tried upgrading to newer versions of python-lsp-ruff, but with all newer versions (1.3.0, 1.4.0, and 1.5.0) I no longer receive any diagnostics. For example, I've tested the following:

def hello():
    print('Hello')
      print('World')

for which I get a SyntaxError (E999) diagnostic on line 3 with python-lsp-ruff 1.2.0, but no diagnostics for newer versions. I've been trying to find out the underlying cause but simply can't figure it out. I experience the same behaviour whether I use older or newer versions of ruff, and older or newer versions of eglot. As far as I can tell, this appears to be due a change in python-lsp-ruff >= 1.3.0, rather than in python-lsp-server, ruff, or eglot.

Do you have any idea what might be causing this, or what information I can provide to help figure this out?

Why formatting fixes things I don't ask to fix?

Hi, I'm fairly unfamiliar with ruff and formatting in general, and so I'm trying to understand how to control its behaviour.

I have this configuration:

"pylsp.plugins.ruff.enabled": true,
"pylsp.plugins.ruff.extendSelect": ["E", "D", "C90", "I"],
"pylsp.plugins.ruff.ignore": ["E265"],
"pylsp.plugins.ruff.format": ["D"],
"pylsp.plugins.ruff.preview": true,
"pylsp.plugins.ruff.lineLength": 79,

Then, I introduce this typo: a = 1. This gets correctly signaled by ruff with E221 (this code requires preview). However, when I run the command :call CocAction('format') this error gets fixed. This is not what I expect, the error should not be fixed because this family of errors is not explicitly indicated in the ruff.format option. This does seem to work for I errors, though.

Am I doing anything wrong or is this the expected behaviour? To be honest, I'm not even sure if :call CocAction('format') is the correct way to invoke ruff format.

Thanks for the the help and more generally for this great plugin!

pylsp+ruff sometimes very slow to update an inline error

This is an example - this sort of problem doesn't happen every time, not even most of the time, but it does happen enough to shake my confidence in the errors I'm getting:

โ”‚ return (
๏™™ โ”‚ โ”‚ LockingPassthrough(NewProduct, lock)     โ–  Undefined name `Status`
โ”‚ โ”‚ .filter(NewProduct.deleted_on.is_(None))
โ”‚ โ”‚ .join(subquery, Pipeline.product_id == NewProduct.id)
โ”‚ )

As you can see, there's nothing about "Status" on that line. It's been like this for about 10 or 20 minutes. I had Status in there, but I corrected the problem; sadly, the red error never went away.

My question is twofold:

  1. For the short term, is there command/keystroke to make pylsp forget what it thinks it knows and reexamine the code? That would probably make this easier to deal with.
  2. For the long term, is there a way to make pylsp+ruff stop giving spurious (outdated) errors?

Thanks!

ruff format isn't working

I'm trying to setup python-lsp-ruff, but for some reason ruff format doesn't seem to be running.

Here is my config

Inside nvim:
image

Running ruff format --diff src:
image

Is there a way to debug these sort of issues?

Fails to install on Termux

โฏ pip install python-lsp-ruff
Collecting python-lsp-ruff
Downloading python_lsp_ruff-1.4.0-py3-none-any.whl (9.2 kB)
Collecting ruff>=0.0.260 (from python-lsp-ruff)
Using cached ruff-0.0.267.tar.gz (1.1 MB)
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... error
error: subprocess-exited-with-error

ร— Preparing metadata (pyproject.toml) did not run successfully.
โ”‚ exit code: 1
โ•ฐโ”€> [22 lines of output]
error: failed to get ruff as a dependency of package ruff_cli v0.0.267 (/data/data/com.termux/files/usr/tmp/pip-install-4ta5rki6/ruff_55c9c69c060f4940954cdd8d1f2a0b40/crates/ruff_cli)

  Caused by:
    failed to load source for dependency `ruff`

  Caused by:
    Unable to update /data/data/com.termux/files/usr/tmp/pip-install-4ta5rki6/ruff_55c9c69c060f4940954cdd8d1f2a0b40/local_dependencies/ruff

  Caused by:
    failed to parse manifest at `/data/data/com.termux/files/usr/tmp/pip-install-4ta5rki6/ruff_55c9c69c060f4940954cdd8d1f2a0b40/local_dependencies/ruff/Cargo.toml`

  Caused by:
    error inheriting `colored` from workspace root manifest's `workspace.dependencies.colored`

  Caused by:
    failed to find a workspace root
  ๐Ÿ’ฅ maturin failed
    Caused by: Cargo metadata failed. Does your crate compile with `cargo build`?
    Caused by: `cargo metadata` exited with an error:
  Error running maturin: Command '['maturin', 'pep517', 'write-dist-info', '--metadata-directory', '/data/data/com.termux/files/usr/tmp/pip-modern-metadata-osjlu_8g', '--interpreter', '/data/data/com.termux/files/usr/bin/python3']' returned non-zero exit status 1.
  Checking for Rust toolchain....
  Running `maturin pep517 write-dist-info --metadata-directory /data/data/com.termux/files/usr/tmp/pip-modern-metadata-osjlu_8g --interpreter /data/data/com.termux/files/usr/bin/python3`
  [end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

ร— Encountered error while generating package metadata.
โ•ฐโ”€> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.

Allow disabling formatter

As someone only needing the linting part of ruff, I'd like to be able to disable the formatter, which conflicts with the formatter I do use.

I spent the better part of the day trying to figure out why black always broke the formatting when running inside of my editor but not when running from our pre-commit hook or manually in the terminal... Now I finally figured out that it was actually this plugin having formatting enabled by default.
Ruff formatting is not 100% compatible with black, which basically stops me from using this plugin entirely in my workflow. Which sucks because I do actually want the linting part of ruff.

Otherwise I guess I'll need to setup another language server for which I can then entirely disable document formatting

Please add this package to conda forge

Thank you all for this package. I find it very useful for linting code in jupyter notebooks via jupyterlab-lsp.

As a conda user, I would find it useful if the package was available to install with conda, not just pip.

Thanks again!

Can't set ignored error codes

I'm sending the following configuration to pylsp via the didChangeConfiguration notification but I don't get the desired effect of disabling error code D101:

{
  "pylsp": {
    "plugins": {
      "pycodestyle": {
        "enabled": false
      },
      "pyflakes": {
        "enabled": false
      },
      "ruff": {
        "enabled": true,
        "ignore": [
          "D101"
        ]
      }
    }
  }
}

However, if I switch pylsp.ruff.enabled to false, the plugin is disabled, so the editor part of my setup must be working.

How is python-lsp-ruff updated in Neovim?

I use python-lsp-server in Neovim and also have python-lsp-ruff installed. I wonder, how I receive updates of Ruff because it used as a plugin and Mason doesn't know explicitly about python-lsp-ruff.

Not working with Helix Editor

The plugin does not seem to be working with the Helix Editor. Here is my languages.toml file. I have tried to explicitly disable the other linters. Is there anything missing here?

[[language]]
name = "python"

# Disable flake8 (disabled by default), pycodestyle, 
# pydocstyle, pyflakes, and mccabe for ruff
[language.config.pylsp.plugins.pycodestyle]
enabled = false 

[language.config.pylsp.plugins.pydocstyle]
enabled = false
convention = 'pep257'

[language.config.pylsp.plugins.pyflakes]
enabled = false

[language.config.pylsp.plugins.mccabe]
enabled = false

[language.config.pylsp.plugins.ruff]
enabled = true

`per-file-ignores` doesn't seem to be working

This works in both ruff via CLI and with python-lsp-ruff; none of the listed errors are visible in __init__.py files:

Edit: No it doesn't, please see comment below.

[tool.ruff]
ignore = [
	"E501", # line length violations
	"E722", # bare except
]
per-file-ignores = {
	# Ignore import violations in all `__init__.py` files
	"__init__.py" = ["E402", "F401", "F403"]
}

This works when invoking ruff via CLI, but not in python-lsp-ruff; the per-file-ignores are visible in the editor but not in the command line (the global ignored errors are still invisible in both):

[tool.ruff]
ignore = [
	"E501", # line length violations
	"E722", # bare except
]

# Ignore import violations in all `__init__.py` files
[tool.ruff.per-file-ignores]
"__init__.py" = ["E402", "F401", "F403"]

It seems like python-lsp-ruff doesn't parse sub-tables specified via headers somehow?

Thank you for this project!

Code action tests fail when global pyproject file exists

I get the following in test_ruff_code_actions:

workspace = <pylsp.workspace.Workspace object at 0x7f0938b57130>

    def test_ruff_code_actions(workspace):
        _, doc = temp_document(codeaction_str, workspace)

        diags = ruff_lint.pylsp_lint(workspace, doc)
        range_ = cattrs.unstructure(
            Range(start=Position(line=0, character=0), end=Position(line=0, character=0))
        )
        actions = ruff_lint.pylsp_code_actions(
            workspace._config, workspace, doc, range=range_, context={"diagnostics": diags}
        )
        actions = converter.structure(actions, List[CodeAction])
        for action in actions:
>           assert action.title in codeactions
E           AssertionError: assert 'Ruff: Organize imports' in ['Ruff (F401): Remove unused import: `os`', 'Ruff (F401): Disable for this line', 'Ruff (F841): Remove assignment to unused variable `a`', 'Ruff (F841): Disable for this line', 'Ruff: Fix All']
E            +  where 'Ruff: Organize imports' = CodeAction(title='Ruff: Organize imports', kind=<CodeActionKind.SourceOrganizeImports: 'source.organizeImports'>, diag...range=1:0-2:0, new_text='import os\n\n\n')]}, document_changes=None, change_annotations=None), command=None, data=None).title

tests/test_code_actions.py:76: AssertionError

ruff command line is missing subcommand when specifying executable in config

If the executable is specified in the LSP config, the command line to run ruff is constructed and executed in

cmd = [executable]
cmd.extend(arguments)
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

This call is missing the subcommand to actually execute with ruff. Compare to the call constructed for the fallback usage of the Python module in

cmd = [sys.executable, "-m", "ruff", str(subcommand)]
cmd.extend(arguments)
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

which includes str(subcommand).

Without the subcommand ruff seems to fallback to linting and does nothing to the buffer when trying to format through the LSP. Just adding str(subcommand) to the executable command fixes this for me.

Ruff stops working when I indicate a config file in CocConfig

Hi there. I am wondering what I am doing wrong here. I have several rules I like to change for nearly all my projects, like line-length, single vs double quotes, etc. I have made a .ruff.toml in my dotfiles folder and in my CocConfig I added "pylsp.plugins.ruff.config": "~/dotfiles/ruff.toml" to link to it for use.

I can see linting errors when I remove the line, and when I add it they go away. Am I doing this wrong?

If it matters I'm using VIm, not NeoVim. I also have the following pylsp settings:

{
	"pylsp.enable": true,
	"pylsp.builtin.enableInstallPythonLspRuff": true,
	"pylsp.plugins.pycodestyle.enabled": false,
	"pylsp.plugins.pyflakes.enabled": false,
	"pylsp.plugins.mccabe.enabled": false,
	"pylsp.plugins.ruff.format": [
		"I"
	],
	"pylsp.plugins.ruff.config": "~/dotfiles/ruff.toml"
}

Unable to disable plugin

Setting enabled key here does not affect anything.
However, setting ignore key causes ruff to ignore the specified key.

pylsp settings

    local lspconfig = require("lspconfig")
    lspconfig["pylsp"].setup({
        settings = {
            pylsp = {
                plugins = {
                    ruff = {
                        enabled = false,
                        ignore = {
                            "E741",
                        },
                    },
                },
            },
        },

Without ignore key
image

With ignore key
image

Virtual environment not respected with `pipx`

I'm not sure how reproducible this will be on other environments (although it might not be too hard to replicate with a Dockerfile, especially if there's a pipx - ready image), but currently I'm running into this (on MacOS, fwiw), after

pipx install --force "ruff>=0.1"

And it goes away after

pipx install --force "ruff<0.1"

Some info about versions:

$ pipx list | rg 'ruff|lsp'
   package python-lsp-server 1.8.2, installed using Python 3.11.6
    - pylsp
   package ruff 0.0.292, installed using Python 3.11.6
    - ruff
$ pipx runpip python-lsp-server freeze | rg ruff
python-lsp-ruff==1.5.2
ruff==0.1.0

Based on the above, even though I've got the incompatible ruff version in my python-lsp-server environment, I can avoid this issue if ruff --version is compatible. Conversely (?), if I had a good version range in the python-lsp-server venv, it wouldn't matter if my globally-installed ruff had breaking changes.

change to sys.executable

Limited testing with my pipx environments:

at 10:12:30 ๐ŸŽ โฏ ~/.local/pipx/venvs/python-lsp-server/bin/python -c 'import sys; import os; os.system(sys.executable + " -m ruff --version")'
ruff 0.1.0

at 10:12:54 ๐ŸŽ โฏ ~/.local/pipx/venvs/ruff/bin/python -c 'import sys; import os; os.system(sys.executable + " -m ruff --version")'
ruff 0.0.292

I'd hope that testing in a CPython python -m venv environment would be sufficient, but it's possible that different python distributions (e.g. circuitpython) or project tools (pdm, poetry, etc.) might behave differently.

Based on personal anecdotal evidence, I haven't run into issues with using sys.executable like this in the past, but there are a lot of environments I haven't worked in yet (embedded, WASM, etc.)

Originally posted by @znd4 in #49 (comment)

Message is not JSON serializable.

I want to use python-lsp-server and python-lsp-ruff with neovim, but I get the following error.
Other plugins such as python-lsp-black work.

LspLog

[ERROR][2023-11-19 23:17:03] .../vim/lsp/rpc.lua:734 "rpc" "/home/Ttayu/.local/share/nvim/mason/bin/pylsp" "stderr" "2023-11-19 23:17:03,317 JST - ERROR - pylsp_jsonrpc.streams - Failed to write message to output file {'jsonrpc': '2.0', 'method': 'textDocument/publishDiagnostics', 'params': {'uri': 'file:///home/Ttayu/sample.py', 'diagnostics': [{'range': {'start': {'line': 1, 'character': 7}, 'end': {'line': 1, 'character': 13}}, 'message': 'shutil imported but unused', 'severity': 1, 'code': 'F401', 'source': 'ruff', 'tags': [1], 'data': Fix(edits=[Edit(content='', location=Location(row=2, column=1), end_location=Location(row=3, column=1))], message='Remove unused import: shutil', applicability='safe')}, {'range': {'start': {'line': 15, 'character': 0}, 'end': {'line': 15, 'character': 14}}, 'message': 'Module level import not at top of file', 'severity': 2, 'code': 'E402', 'source': 'ruff', 'tags': []}, {'range': {'start': {'line': 15, 'character': 7}, 'end': {'line': 15, 'character': 14}}, 'message': 'pathlib imported but unused', 'severity': 1, 'code': 'F401', 'source': 'ruff', 'tags': [1], 'data': Fix(edits=[Edit(content='', location=Location(row=16, column=1), end_location=Location(row=17, column=1))], message='Remove unused import: pathlib', applicability='safe')}, {'source': 'mypy', 'range': {'start': {'line': 9, 'character': 15}, 'end': {'line': 9, 'character': 38}}, 'message': '"filter[Any]" has no attribute "exists"', 'severity': 1, 'code': 'attr-defined'}]}}\nTraceback (most recent call last):\n File "/home/Ttayu/.local/share/nvim/mason/packages/python-lsp-server/venv/lib/python3.10/site-packages/pylsp_jsonrpc/streams.py", line 97, in write\n body = json.dumps(message, **self._json_dumps_args)\nTypeError: Fix(edits=[Edit(content='', location=Location(row=2, column=1), end_location=Location(row=3, column=1))], message='Remove unused import: shutil', applicability='safe') is not JSON serializable\n"

import shutil
from pathlib import Path
import Path

Environment

python-lsp-ruff: 1.6.0
ruff: 0.1.6
OS:

  • WSL-Ubuntu-22.04
    Linux 5.15.133.1-microsoft-standard-WSL2
  • Ubuntu-22.04.3 LTS
    5.15.0-88-generic

NeoVim: NVIM v0.9.4, v0.10.0-dev-09a17f9

Build type: Release
LuaJIT 2.1.1692716794

pip list

/home/Ttayu/.local/share/nvim/mason/packages/python-lsp-server/venv/bin/pip list

Package               Version
--------------------- --------
astroid               3.0.1
attrs                 23.1.0
autopep8              2.0.4
cattrs                23.2.1
dill                  0.3.7
docstring-to-markdown 0.13
flake8                6.1.0
importlib-metadata    6.8.0
isort                 5.12.0
jedi                  0.19.1
lsprotocol            2023.0.0
mccabe                0.7.0
packaging             23.2
parso                 0.8.3
pip                   23.2.1
platformdirs          4.0.0
pluggy                1.3.0
pycodestyle           2.11.1
pydocstyle            6.3.0
pyflakes              3.1.0
pylint                3.0.2
python-lsp-jsonrpc    1.1.2
python-lsp-ruff       1.6.0
python-lsp-server     1.9.0
pytoolconfig          1.2.6
rope                  1.11.0
ruff                  0.1.6
setuptools            65.5.0
snowballstemmer       2.2.0
tomli                 2.0.1
tomlkit               0.12.3
ujson                 5.8.0
whatthepatch          1.0.5
yapf                  0.40.2
zipp                  3.17.0

lsp_format_on_save deleting entire file contents

When hitting ctrl+s to save a file, the LSP action to format a file is invoked. I found the ruff plugin to be the cause, here's the log file from python-lsp-server:

2023-10-18 08:41:40,113 CEST - ERROR - pylsp_ruff.plugin - Error running ruff: error: unexpected argument '--format' found

  tip: to pass '--format' as a value, use '-- --format'

Usage: ruff check <--verbose|--quiet|--silent> [FILES]...

For more information, try '--help'.

Seems like this option is deprecated in 0.1.0: astral-sh/ruff#7984

python-lsp-ruff does not act like ruff-lsp (at least in neovim)

I currently use ruff-lsp inside of neovim and I decided to install python-lsp-server in addition to get all the nice lsp stuff like 'go to definition' and such. I tried using python-lsp-ruff instead of ruff-lsp because I thought it made more sense to have everything in one language server, but I was sad to find it does not act the same as ruff-lsp. Is that normal?

The main pain points for me are:

  1. Some things that are displayed as warnings by ruff-lsp are displayed as errors by python-lsp-ruff, e.g. unused imports or Redefinition of unused...
  2. I don't have any code actions, whereas with ruff-lsp I have things like organize imports

I am not entirely sure if that's a neovim thing or if that's a python-lsp-ruff thing, but I thought I would post it here first, feel free to redirect me if this is out of your hands ๐Ÿ™‚

BTW, I tried two different methods to install python-lsp-ruff, both yielded the same outcome. The first one was a direct pip install, the second one was through Mason using the :PylspInstall command I discovered in this issue.

Auto-disabling flake8 doesn't seem possible

If the client configuration contains pylsp.plugins.flake8.enabled = true (which is necessary for flake8 to enable in pylsp), then this seems to always override the documented python-lsp-ruff behaviour of auto-disabling flake8.

I think this applies for all the linters that are auto-disabled by python-lsp-ruff, although in the other cases they are enabled by default so leaving enabled = true out of the client config will solve the problem.

What I observe with my LSP client (eglot) is the following sequence of events:

  1. LSP client sends initialize
  2. pylsp loads all plugins, including python-lsp-ruff and flake8_lint.
  3. pylsp runs the ruff plugin pylsp_settings hook. It will merge 'flake8': {'enabled': False} into the plugins settings (along with the same for other other auto-disabled plugins.)
  4. pylsp will also run the flake8_lint plugin pylsp_settings hook, which also sets 'flake8': {'enabled': False} (not sure if these happen in a guaranteed order, but the outcome is the same - flake8 is definitely disabled!)
  5. At this point, pylsp -v will log a Disabled plugins: line that includes pylsp.plugins.flake8_lint.
  6. LSP client sends 'workspace/didChangeConfiguration' with 'params': {'settings': {'pylsp': {'plugins': [...] 'flake8': {'enabled': True} [...]
  7. At this point, pylsp -v will log a Disabled plugins: line that no longer includes pylsp.plugins.flake8_lint.
  8. LSP sends linter results for both ruff and flake8.

This may be an eglot bug(?) but from what I've seen it seems likely most clients will send these events in this sequence.

Workarounds

  1. Making sure there's no flake8 binary on the PATH of the venv works, as then the plugin enables but never produces any results.
  2. Writing per-project pylsp configs obviously will work, although I jump around a lot of Python codebases so it's undesirable for me (and I'm guessing python-lsp-ruff authors have the same preference, given the auto-disabling logic.)
  3. Depending on LSP client implementations, it may be possible to hook the client and have it do some checks before it sends didChangeConfiguration. However this seems counter to the overall architecture of LSP, where the language-specific implementation is delegated to the server.

Idea for fix

The best idea I've come up with for a fix would actually be a python-lsp feature, not a python-lsp-ruff change. Although hopefully there's a simpler way to solve this in python-lsp-ruff, I'm pretty unfamiliar with LSP.

The idea is, pylsp could support a setting like pylsp.plugins.NAME.enabled = 'project' setting that will call a hook in the plugin that checks for the configuration files or keys used by that plugin's linter in the project, and only enables the plugin if some configuration is found. Most of this logic already exists in the plugins.

If this does seem like a good feature then I'm happy to raise it on the main pylsp repo, and potentially raise some PRs.

Suggestion on code actions for unsafe rules

With the introduction of the unsafe auto-fixes in ruff, I feel having a single toggle in pylsp for enabling/disabling them are quite too inefficient or "too safe", as either make all unsafe fixes disappear, or making the Fix all-code action quite unsafe in nature

My idea is instead, if you leave pylsp.plugins.ruff.unsafeFixes as False then the Fix all-code-action should fix all safe rules, but still make the individual unsafe rules available and actionable on the respective diagnostic/location

This strikes the balance of being safe with the Fix all-code-action, and still being able to discover and make a choice on the unsafe fix

(If you instead set pylsp.plugins.ruff.unsafeFixes to True, then the plugin should work exactly as now (because then you signed up for the "unsafety-ness"))

With that being said, the unsafe-code actions should probably indicate they are unsafe somehow

If this isn't too crazy of an idea, I'd happily try to implement it :-)

Wrong code action range for sort import action

When I try to "Organize imports" via code actions, I observe the following unexpected behaviour:

Before organizing imports:
image

After organizing import with python-lsp-ruff:
image

Expected behaviour (below screenshot is obtained by using code actions with ruff-lsp):
image

As you can see, a random i is inserted at the beginning, and the c from the class statement disappeared.

Performing the code action with ruff-lsp and running ruff --fix file.py --extendSelect "I" on the command line provide the expected result.

For reference, I am on WSL Ubuntu using Emacs (29) with eglot.

Not sure if this an issue something with Emacs/eglot or my setup, but as I don't have the issue with ruff-lsp I thought it might be worth checking here if anyone else has the same issue?

Unable to set specific ignore rules

I'm running emacs with lsp-mode, and have pylsp set up with this plugin

I'm having an issue setting specific ignore rules. for example:

(lsp-register-custom-settings '(
    ("pylsp.plugins.ruff.enabled" t)
    ("pylsp.plugins.ruff.lineLength" 88)
    ("pylsp.plugins.ruff.ignore" "D215")
))

I get this error:
ERROR - pylsp_ruff.plugin - Error running ruff: error: invalid value '2' for '--ignore <RULE_CODE>'

But if I change my config to use the more general D category ("pylsp.plugins.ruff.ignore" "D") instead of a specific rule then everything works fine

test failure at last commits

FAILED tests/test_code_actions.py::test_ruff_code_actions - ValueError: Position.character should be in range [0:2147483647], but was -1.
FAILED tests/test_code_actions.py::test_import_action - ValueError: Position.character should be in range [0:2147483647], but was -1.

tests/test_code_actions.py:78:
tests/test_code_actions.py:103:

Missing ruff executable breaks other linters

If the executable configuration param is specified but points to an executable that does not exist then run_ruff() throws an exception and prevents other python-lsp-server linters from running. With a valid executable specified multiple lint errors are flagged from multiple linters (including ruff). With an invalid executable specified no lint errors are flagged (not even from other linters).

For example:

2023-12-22 13:21:14,431 GMT - DEBUG - pylsp_ruff.plugin - Calling ruff with args: ['--quiet', '--exit-zero', '--output-format=json', '--extension=ipynb:python', '--no-fix', '--force-exclude', '--stdin-filename=<redacted>', '--preview', '--extend-select=E,W,F', '--', '-'] on '<redacted>''
2023-12-22 13:21:14,439 GMT - ERROR - pylsp_ruff.plugin - Can't execute ruff with given executable 'ruff'.
2023-12-22 13:21:14,440 GMT - WARNING - pylsp.config.config - Failed to load hook pylsp_lint: cannot access local variable 'p' where it is not associated with a value
Traceback (most recent call last):
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pylsp/config/config.py", line 40, in _hookexec
    return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pluggy/_manager.py", line 457, in traced_hookexec
    return outcome.get_result()
           ^^^^^^^^^^^^^^^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pluggy/_result.py", line 114, in get_result
    raise exc.with_traceback(exc.__traceback__)
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pluggy/_result.py", line 76, in from_call
    result = func()
             ^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pluggy/_manager.py", line 454, in <lambda>
    lambda: oldcall(hook_name, hook_impls, caller_kwargs, firstresult)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pluggy/_callers.py", line 113, in _multicall
    raise exception.with_traceback(exception.__traceback__)
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pluggy/_callers.py", line 77, in _multicall
    res = hook_impl.function(*args)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pylsp_ruff/plugin.py", line 172, in pylsp_lint
    checks = run_ruff_check(document=document, settings=settings)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pylsp_ruff/plugin.py", line 442, in run_ruff_check
    result = run_ruff(
             ^^^^^^^^^
  File "/<redacted>/.config/coc/extensions/@yaegassy/coc-pylsp-data/pylsp/venv/lib/python3.11/site-packages/pylsp_ruff/plugin.py", line 525, in run_ruff
    (stdout, stderr) = p.communicate(document_source.encode())
                       ^
UnboundLocalError: cannot access local variable 'p' where it is not associated with a value

Versions:

  • python: 3.11.6
  • python-lsp-server: 1.9.0
  • python-lsp-ruff: 2.0.0

Prior to commit ea5f874a, python-lsp-ruff would silently (apart from a debug message) fall back to running ruff via the python module if the specified executable was not found. Now an error message is logged following the Popen() failure, but the code still attempts to use the pipe (which is not defined following the exception). That throws an exception which is not caught and as a result any subsequent linters aren't run (so not only do we not se

I see two options for resolving this (other than making sure the executable config param is set correctly :-p):

  • return an empty string after logging the error on line 520;
  • fall back to running ruff via the python module (similar to previous behaviour, but with the option to not even attempt to run the executable if it's not specified).

I'd suggest the second option as that will provide a better user experience. That assumes commit ea5f874a was simply intended to shortcut the attempt to call the executable if it was not set, rather than intended to remove the fallback behaviour.

This issue was discovered while investigating yaegassy/coc-pylsp#24.

Add option for quote-style

class PluginSettings doesn't seem to support quote-style ? Seems inefficient to add ruff.toml just for that config

Do you think its okay to add that option as well ? or maybe some dynamic options handler ?

If ruff is not exists in the environment, all lint processes in pylsp will stop working

Description

python-lsp-ruff gives the following error if ruff is not in the environment. This error appears to cause all lint processes served by pylsp to stop.

2023-01-06 19:02:47,691 JST - WARNING - pylsp.config.config - Failed to load hook pylsp_lint: [Errno 2] No such file or directory: 'ruff'
Traceback (most recent call last):
// ...snip
FileNotFoundError: [Errno 2] No such file or directory: 'ruff'

I think it might be necessary to make some adjustments, such as checked the exists of a ruff command.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.