williamboman / mason.nvim

Portable package manager for Neovim that runs everywhere Neovim runs. Easily install and manage LSP servers, DAP servers, linters, and formatters.
Apache License 2.0
7.27k stars 261 forks source link

Pylint "Unable to import <module>" error #1336

Closed memeLordo closed 1 year ago

memeLordo commented 1 year ago

I've searched open issues for similar requests

I've manually reviewed logs to find potential errors

I've recently downloaded the latest plugin version of mason.nvim

Problem description

It's not a critical issue, but an annoying one. Basically, I have an import error of my Python code for my Pylint module. And for some cases it solvable by just writing a path to .pylintrc or using nul-ls package. But whatever I try, the problem can’t be solved by me or I just ran out of ideas.

Expected behavior

No "Unable to import " error as with other linters (like Pylama, Flake8 and so on) Same code with Flake8 изображение

Steps to reproduce

  1. Install the module via Mason on latest Astrovim configuration.
  2. Create a Python file using neovim (ex. nvim main.py)
  3. Import any non-base Python library, installed with pip
  4. Get an error.

Affected packages

Pylint, mypy (getting the same error)

Neovim version (>= 0.7)

NVIM v0.8.3 Build type: Release LuaJIT 2.1.0-beta3

Operating system/version

Ubuntu 22.04.2 LTS

Healthcheck

ERROR: No healthcheck found for "mason" plugin.

Screenshots or recordings

изображение

williamboman commented 1 year ago

Hello! So pip packages (which pylint is) will be installed to a separate virtual environment by Mason. pylint will by default only look for packages inside that virtual environment, which is a bit problematic.

It seems like you have three options (either first two if you want to use pylint via Mason): 1) Set the $PYTHONPATH environment variable to point to the location you have your dependencies installed, for example:

$ export PYTHONPATH="$PWD/.venv/lib/python3.8/site-packages"
$ nvim

Note that you only need to set this PYTHONPATH variable for the pylint process itself, if you use null-ls you can instead do something like:

    null_ls.builtins.diagnostics.pylint.with({
        env = function(params)
            return { PYTHONPATH = vim.fn.expand(params.root .. "/.venv/lib/*/site-packages") }
        end,
    }),

2) Use the --init-hook configuration in pylint:

# .pylintrc
[MASTER]
init-hook='import sys; import os; sys.path.append(os.path.join(os.getcwd(), ".venv", "lib", "python3.8", "site-packages"))'

3) Install pylint in the same environment where your dependencies exist, likely in a project-local virtual environment. In this case you'll want to uninstall pylint from Mason.

williamboman commented 1 year ago

The same can be achieved for mypy but through a different command flag, --python-executable (should be configurable in null-ls via extra_args, similar to pylint example above).

dbatten5 commented 6 months ago

I'm having a similar issue whereby I have a mypy installed via Mason (as I want to have it for all projects on my laptop) and in a virtual environment for a currently active work project (since it's part of the dependencies for the project). If I run :!which mypy, it points to the mason installation as the mason bin folder appears ahead of the /Users/{my_username"/.virtualenvs/{work_project}/bin folder. Specifying the --python-executable arg isn't ideal as I would have to specify the {work_project} name in the path which would then break for other projects using mypy. Is there any way to ensure that virtual envs appear ahead of mason in my $PATH? Ideally I'd have a way for mason to append to $PATH, not prepend.

EDIT: just found there's a config option to do exactly that. Should have read the docs 🤦