Cannot change LSP with Python module

Problem description:
In a repl with the Python module (found in the .replit file), you are unable to change the lsp via [languages.python.languageServer]

Expected behavior:

The default LSP (pyright-extended) to be disabled and my specified LSP to be enabled.

Actual behavior:

pyright-extended remains enabled.

Steps to reproduce:

  1. Create a new Python repl
  2. Check the LSP. It’s pyright-extended.

  3. Set the [languages.python.languageServer] property to have a custom LSP in the .replit file like so:
entrypoint = "main.py"
modules = ["python-3.10:v18-20230807-322e88b"]

hidden = [".pythonlibs"]

[languages]

[languages.python]
pattern = "**/*.py"

[languages.python.languageServer]
start = "ruff-lsp"

[nix]
channel = "stable-23_05"

[unitTest]
language = "python3"

[deployment]
run = ["python3", "main.py"]
deploymentTarget = "cloudrun"
  1. Create a replit.nix file with the following contents to install the LSP (or use the System Dependencies tool and add ruff-lsp. Current version is 0.0.27 whilst writing this)
{pkgs}: {
  deps = [
    pkgs.python310Packages.ruff-lsp
  ];
}
  1. Run kill 1 to fully reload the repl
  2. Going back to your Python file, check the LSP in the linting and the indicator. It will still say pyright-extended and Ruff will not appear.

Fixing it

  1. Comment out modules = ['python-....'] inside of .replit
  2. Run kill 1 again.
  3. Check the LSP. You can see that pyright-extended is not loaded and instead your completions are coming from Ruff (The indicator will not specify Ruff, just Python Language Server. Thelinting will say Ruff)

Of course, you now lack the benefits of the Python module such as auto poetry installation, upm compatibility, etc.

Plan (Free, Replit Core): Core

3 Likes

Interesting.
But I’m curious, for what reason are you changing from pyright-extended to ruff-lsp? Is it for higher ruff version or no typechecking?

1 Like

From my experience, Ruff is a more reliable and faster LSP. I also use Ruff locally and in my GitHub actions so I’d like to use the same on Replit. It’s really configurable, works well with types (I like typechecking) and has a nice CLI tool which will fix the issues in the LSP (ruff main.py --fix)
My main issue is just the difference in ignoring errors. In pyright it’s # type: ignore (substituting type). In ruff it’s # NOQA: E501 (substituting E501) E501 is the line length error.

Additionally if you have a formatted longstring that’s multiline (f"""...""") you cannot ignore errors inside of it with pyright (at least, not that I’m aware of), but you can with ruff by putting it at the end.

1 Like

but pyright is an actual typechecker, used alongside a linter such as Ruff.

in many cases it’s better practice anyhow, to explicitly ignore the specific typing error by typing.casting, for example:

g = None
f"""
{cast(Any, g).member}
"""

see my .config/bashrc for the workaround, disabling only the default LSP.

2 Likes

From my understanding, pyright-extended (created by replit) is a combination of pyright (typechecker by Microsoft) and ruff (hence the “extended”). Both ruff and pyright are configurable in pyproject.toml.
All warnings and errors show up as pyright-extended, but really it is either ruff or pyright (sometimes they share warnings for certain things). Since pyright is mainly a typechecker, most warnings (usually styling) are from ruff, and the type errors are from pyright.
# type: ignore works on both ruff and pyright, but ruff also has the NOQA: code. And according to google, pyright has # pyright: ignore[code]

To my knowledge, ruff is NOT a typechecker, it’s a linter (as Umar has said), which is why replit created pyright-extended.

Right now, there are no CLI options for the default LSP for python repls.

1 Like

I never specified type errors. Actually, E501 is my curse (line length)

Anyway, I want a consistent development experience so I’d like identical LSPs wherever I’m working. And, ruff can be a typechecker - I have it setup as such locally.

Regardless, I appreciate the responses but this is getting off-topic. Replit should still allow me to configure the LSP when they have a field for it in .replit.

I agree that the LSP (and formatter) should be configurable, perhaps by fixing .replit configuration or by introducing a new Tool.

Ruff by itself is not a type checker, but usually there is also a complementary type checker.
Ruff configuration can be transferred over to replit, so that the LSPs are similar, because python repls already use ruff.

Almost all of ruff’s features are available in the default code intelligence (pyright is the type checker), except that its shell commands aren’t available which is too bad.

2 Likes