Pyright unable to resolve imports that are in my PYTHONPATH

I’m running neovim with nvim-lspconfig plugin with pyright. The structure of the repo is a little strange, so I’ve got a PYTHONPATH environment variable set up to help python find all the code. Here’s a simple example:

$ mkdir demo; cd demo
$ git init  # necessary to get lspconfig's root_dir automatically set, this is discussed later
$ cat test.py
import foo

print(foo)
$ cat subdir/foo.py
PI=22/7

Note how that import foo shouldn’t work (without a custom PYTHONPATH) because foo.py is in a subdirectory. And indeed, it doesn’t:

$ pyright
No configuration file found.
No pyproject.toml file found.
Assuming Python platform Linux
Searching for source files
Found 2 source files
/home/jeremy/tmp/pyright-demo/test.py
  /home/jeremy/tmp/pyright-demo/test.py:1:8 - error: Import "foo" could not be resolved (reportMissingImports)
1 error, 0 warnings, 0 infos
Completed in 0.625sec

Fortunately, pyright does know how to read the PYTHONPATH env var: Support for PYTHONPATH · Issue #8 · microsoft/pyright · GitHub), so if I set one, things work fine:

$ PYTHONPATH=./subdir pyright
No configuration file found.
No pyproject.toml file found.
Assuming Python platform Linux
Searching for source files
Found 2 source files
0 errors, 0 warnings, 0 infos
Completed in 0.621sec

However, when I’m in neovim (with the PYTHONPATH env var set!), I get an error about the “Import “foo” could not be resolved”!

I poked around /proc/ and could see that the PYTHONPATH environment variable is set correctly:

$ pstree -apl 335756
zsh,335756
  └─vim,337568
      ├─node,337621 /usr/bin/pyright-langserver --stdio
      │   ├─{node},337622
      │   ├─{node},337623
      │   ├─{node},337624
      │   ├─{node},337625
      │   ├─{node},337626
      │   └─{node},337628
      ├─python3,337615 -c import sys; sys.path = list(filter(lambda x: x != "", sys.path)); import neovim; neovim.start_host() script_host.py
      └─{vim},337569
$ grep -Eao 'PYTHONPATH.{50}' /proc/337621/environ
PYTHONPATH=./subdir_=/usr/bin/vimVIMRUNTIME=/usr/share/nvi

But I also noticed that the cwd of the pyright process is not what I’d expect:

$ ls -alh /proc/337621/cwd
lrwxrwxrwx 1 jeremy jeremy 0 Oct 26 17:54 /proc/337621/cwd -> /usr/lib/node_modules/pyright/dist

So I think this explains it: pyright is looking for files relative to my /usr/lib/node_modules/pyright/dist directory rather than my project’s directory.

I did some more reading on lspconfig, and I learned about this root_dir setting. I checked that by running :lua print(vim.inspect(vim.lsp.buf_get_clients())), and do see that the root_dir is correctly set to the root of the folder. I very briefly poked around the nvim-lspconfig source code, and couldn’t figure out what the root_dir setting actually is used for. Maybe it’s just so we know if we should start a fresh language server as we open more files?

For the record, I can work around this issue by creating a pyrightconfig.json file at the root of my repo with the following contents:

{
    "extraPaths": ["./subdir"],
}

This also uses a relative path, but I think this works because pyright is smart enough to resolve any paths in the config relative to the location of the config file.

Am I understanding this all correctly? Is there some config setting for lspconfig to get it to start pyright with a working directory equal to the root_dir?

Pyright picks up PYTHONPATH fine for me.

  • podman run --rm -it quay.io/mjlbach/debug-containers:pyright-python-path
  • nvim main.py
  • PYTHONPATH is respected
  • unset PYTHONPATH
  • PYTHONPATH is not respected

picks up the import set with PYTHONPATH (you can read the dockerfile to see the exact reproduction)

Thanks for the response, and containerized repro, @mjlbach!

You’re totally correct that Pyright does pick up PYTHONPATH. The problem for me is that I’m using relative paths in my PYTHONPATH, and lspconfig is starting pyright in a totally random working directory, so it cannot resolve the relative paths. I submitted a PR to hopefully demonstrate this clearly: Repro relative PYTHONPATH issues with nvim and pyright. by jfly · Pull Request #1 · mjlbach/user_questions · GitHub

I see that lspconfig has some concept of root_dir. My problems would go away if it would start pyright in that very root_dir. Is there some way to configure lspconfig to start pyright using that directory? IMO, that would actually be a pretty sane default behavior, but I am am very new to neovim and lspconfig and am not really clear what the purpose of the root_dir is.

Why can you not use an absolute pythonpath? You can use something like direnv to set it.

I could start using absolute pythonpaths if that’s what I have to do.

I guess I’m trying to understand what lspconfig’s root_dir setting is all about, and if it’s intentionally starting pyright in some random directory rather than my project’s root directory.

This may not be relevant, but some light searching leads me to believe that ale has tried to make things “Just Work”, and it seems like lspconfig is 90% of the way there: we know the project’s root directory already, we just need to start pyright in that directory and everything will just work

see :help lspconfig-root-dir for a full explanation

In the meantime, I did file a PR, it’s a 1 line change.

1 Like