astral-sh / ruff-lsp

A Language Server Protocol implementation for Ruff.
Other
1.31k stars 46 forks source link

No falling back to the bundled executable #399

Closed Nefendi closed 8 months ago

Nefendi commented 8 months ago

Hi, first of all I would like to say that I love the speed of ruff so much that I have nearly forgotten that pylint exists!

I am using ruff_lsp with Mason and lspconfig in Neovim. I have been trying to create a configuration that would basically pick up a local ruff executable if it exists in the environment of the current interpreter and fall back to the bundled one otherwise. I have been playing with the path and interpreter options and arrived at this:

{
    init_options = {
        settings = { interpreter = { "python3" } },
    },
}

It works perfectly if the ruff executable is present in the environment of my current interpreter, under the assumption that I always activate my local venv when working on a project. However, if I remove it, I would expect ruff_lsp to fall back to the bundled executable as implemented in https://github.com/astral-sh/ruff-lsp/blob/782d7ac14cf778edfabd992b26d6779b797f4924/ruff_lsp/server.py#L1762 with multiple if-statements, but it seems like the bundle variable is always None and the body of the if-statement with the # Third choice comment never gets executed.

As a result, the line https://github.com/astral-sh/ruff-lsp/blob/782d7ac14cf778edfabd992b26d6779b797f4924/ruff_lsp/server.py#L1813 executes and ruff_lsp throws an exception, because there is no available ruff executable.

I have also checked that when ruff is installed globally, the second choice: https://github.com/astral-sh/ruff-lsp/blob/782d7ac14cf778edfabd992b26d6779b797f4924/ruff_lsp/server.py#L1802 works perfectly as a fallback.

I have found that this function https://github.com/astral-sh/ruff-lsp/blob/782d7ac14cf778edfabd992b26d6779b797f4924/ruff_lsp/server.py#L2008 sets the path to the bundled executable, but I think it is never called.

Thank you in advance for your time, and let me know if you need something else from me!

charliermarsh commented 8 months ago

Hey, thanks! I don't believe we ship a bundled executable with the LSP. We ship a bundled executable with the VS Code extension, which uses that set_bundle hook to tell the LSP that it exists; but for the LSP, I believe we expect that you'll install Ruff separately, alongside it.

Nefendi commented 8 months ago

I see, that would explain this behaviour :smile: So the fact that everything works without a “local” executable may be a result of Mason doing something under the hood. Here are the logs:

[INFO][2024-03-03 21:17:26] ...lsp/handlers.lua:539 "Using interpreter executable: /home/nefendi/.local/share/nvim/mason/packages/ruff-lsp/venv/bin/ruff"
[INFO][2024-03-03 21:17:26] ...lsp/handlers.lua:539 "Inferred version 0.3.0 for: /home/nefendi/.local/share/nvim/mason/packages/ruff-lsp/venv/bin/ruff"

which indicate that ruff got installed in the same venv that ruff_lsp.

Thanks for the clarification! I have one more question before I close this issue: do you know a way to achieve what I want (this fallback behaviour to the executable installed by Mason) using the path or interpreter setting? I would like to avoid modifying local configuration files such pyproject.toml.

The need for this is possibly a little stupid: basically, if I want to use ruff in a project, then I install it as a dependency, but sometimes I only write a little script and I don't create any virtual environment for it. In that case, I would like ruff_lsp to automatically pick up this executable installed by Mason.

Is it possible to give a list of paths to interpreters that can be tried one at a time, or something like that?

Nefendi commented 8 months ago

I have found a solution to my problem, albeit not an ideal one, using the path setting:

{
    init_options = {
        settings = {
            path = { "$VIRTUAL_ENV/bin/ruff" },
        },
    },
}

Thanks for all the help!

charliermarsh commented 8 months ago

Oh nice!