#diagnostics #lsp #python #ide #language-server #mypy

app dmypyls

A language server to support editor agnostic usage of the dmypy daemon

4 releases

new 0.2.2 Nov 14, 2024
0.2.1 Nov 14, 2024
0.2.0 Nov 14, 2024
0.1.0 Nov 12, 2024

#22 in Text editors

Download history 315/week @ 2024-11-11

315 downloads per month

MIT license

26KB
565 lines

dmypyls

/ˈdɪmpəlz/

dmypyls is a language server for mypy that leverages the dmypy daemon. dmypyls manages the life-cycle of the dmypy daemon and provides a language server interface to it.

I'm following this issue for more info on a straight mypy language server implementation.

Installing dmypyls

  1. Get Rust.
  2. cargo install dmypyls.
  3. Add dmypyls to your editor's language server configuration. (See below for Neovim example.)

Running from Source

Consider using dmypyls-debug-runner to run from source, which is helpful for development purposes.

Project Configuration

In order to allow dmypyls to find the correct mypy configuration, you should place a dmypyls.yaml file in the root of your project as a sibling to mypy.ini or pyproject.toml. Here are some example configurations:

If you manage your python environment with venv or uv, you'll probably want your configuration to look like this:

# dmypyls.yaml
dmypy_command:
  - .venv/bin/dmypy

If you manage your virtual environment with pipenv:

# dmypyls.yaml
dmypy_command:
  - pipenv
  - run
  - dmypy

Or uv:

# dmypyls.yaml
dmypy_command:
  - uv
  - --quiet
  - run
  - dmypy

Or pdm:

# dmypyls.yaml
dmypy_command:
  - pdm
  - --quiet
  - run
  - dmypy

User-level Configuration

You can place a dmypyls.yaml in your "$HOME"/.config/dmypyls directory to configure a fallback behavior for all projects.

Neovim Config

vim.api.nvim_create_autocmd({ "BufRead" }, {
  pattern = { "*.py" },
  group = vim.api.nvim_create_augroup("dmypyls-bufread", { clear = true }),
  callback = function(_)
    if vim.fn.executable("dmypyls") ~= 0 then
      -- We found an executable for dmypyls.
      vim.lsp.set_log_level(vim.log.levels.INFO)
      vim.lsp.start({
        name = "dmypyls",
        cmd = { "dmypyls", vim.api.nvim_buf_get_name(0) },
        root_dir = vim.fs.root(0, {
          ".git",
          "pyproject.toml",
          "setup.py",
          "mypy.ini"
        })
      }, { bufnr = 0, reuse_client = function(_, _) return false end })
    end
  end
})

Strict Mypy config

In order for mypy usage to be helpful, I recommend ramping up the strictness of its checks. Here is an example mypy.ini with relatively strict configuration.

[mypy]
strict_optional = True
show_error_codes = True
pretty = True
warn_redundant_casts = True
warn_unused_ignores = True
ignore_missing_imports = False
check_untyped_defs = True
disallow_untyped_defs = True
disallow_any_unimported = True
no_implicit_optional = True
warn_return_any = True

Dependencies

~11–20MB
~269K SLoC