Skip to content

Auto-disabling flake8 doesn't seem possible#46

@projectgus

Description

@projectgus

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions