Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How setup it to use the pyright installed in the environment? #95

Open
dhilst opened this issue Jul 2, 2024 · 2 comments
Open

How setup it to use the pyright installed in the environment? #95

dhilst opened this issue Jul 2, 2024 · 2 comments

Comments

@dhilst
Copy link

dhilst commented Jul 2, 2024

I have this example code:

from typing import Protocol, final

class Proto(Protocol):
    def foo(self, x: int) -> str: ...


@final
class Impl(Proto):
    def foo(self, x: int) -> int: ...

I have no errors in the editor, but if I install pyright manually and run the command I have the expected error

(mypyproject-py3.12) ➜  mypyproject poetry add pyright                                         
Using version ^1.1.369 for pyright

Updating dependencies
Resolving dependencies... (0.1s)

Package operations: 2 installs, 0 updates, 0 removals

  - Installing nodeenv (1.9.1)
  - Installing pyright (1.1.369)

Writing lock file
(mypyproject-py3.12) ➜  mypyproject pyright 
/nvme/geckos/home/code/mypyproject/mypyproject/foo.py
  /nvme/geckos/home/code/mypyproject/mypyproject/foo.py:9:9 - error: Method "foo" overrides class "Proto" in an incompatible manner
    Return type mismatch: base method returns type "str", override returns type "int"
      "int" is incompatible with "str" (reportIncompatibleMethodOverride)
1 error, 0 warnings, 0 information 

How can I tell to lsp-pyright to use the installed pyright?

I have this configuration in my .emacs

;; Required by lsp-pyright
(use-package lsp-pyright
  :ensure t
  :hook (python-mode . (lambda ()
                          (require 'lsp-pyright)
                          (lsp))))  ; or lsp-deferred

Also I'm using poetry as the package manager for my projects, and poetry.el package. I activate the environment by M-x poetry RET v and restart the lsp with lsp-workspace-restart

I guess lsp-pyright install its own version of pyright, but couldn't found by looking into the elisp code

I'm also using poetry config virtualenvs.in-project true, which make poetry create the virtual environment at .venv. When I ran M-: (lsp-pyright-locate-venv) I receive "~/code/mypyproject/.venv" in the minibuffer, but still no error reporting for the protocol implementation.

Note: This may be an Y/X problem. I want to have the proper error message (X) and I believe the problem that the plugin is using whatever other version of pyright that is not the same of the command line(Y), but maybe Y is not the case

@zipy124
Copy link
Contributor

zipy124 commented Aug 25, 2024

I guess lsp-pyright install its own version of pyright, but couldn't found by looking into the elisp code

It does not. The user must supply it.

Your problem is that lsp-pyright looks for pyright in the general $PATH, not with your environment active. That is it looks for your system pythons pyright.

I'm unsure as to the best solution to your problem, but it is likely either adding your poetries environment to the $PATH, or installing pyright into the system, itself, not in a venv. (though it would be possible to modify lsp-pyright to use your poetry version of pyright, I don't think it is the intended usecase)

@sergeyklay
Copy link

sergeyklay commented Nov 28, 2024

lsp-mode actually handles this and simplifies the process of setting up a Python Language Server like Pyright. If the server isn’t already installed, lsp-mode automatically detects this and offers to install it for you due to this code in lsp-pyright:

lsp-pyright/lsp-pyright.el

Lines 287 to 290 in dd54b3a

(lsp-dependency 'pyright
`(:system ,(concat lsp-pyright-langserver-command "-langserver"))
`(:npm :package ,lsp-pyright-langserver-command
:path ,(concat lsp-pyright-langserver-command "-langserver")))

Here’s what happens when you open a Python project without an installed server:

  1. lsp-mode displays a message in the minibuffer "Unable to find installed server supporting this file. The following servers could be installed automatically". You’ll be presented with a list of compatible servers to choose from.
  2. After selecting a server, in our case pyright, and pressing Enter, lsp-mode initiates the installation. For pyright, it runs something like this:
    /usr/bin/npm -g --prefix ~/.emacs.d/.cache/lsp/npm/pyright install pyright
    You can track progress in the buffer named like *lsp-install: /usr/bin/npm*. Once complete, the server connects to your project, and lsp-mode starts providing its features.
  3. In the *Messages* buffer, you’ll see something like this:
    LSP :: Download pyright started.
    Comint finished
    LSP :: Server pyright downloaded, auto-starting in 1 buffers.
    LSP :: Connected to [pyright:106136/starting ~/sampleproject].
    LSP :: pyright:106136 initialized successfully in folders: (~/sampleproject)
    

In rare cases where lsp-mode doesn’t offer to install pyright, or if the automatic process fails, you can install it manually:

NPM_CONFIG_PREFIX="$HOME/.local/" npm install -g pyright

Don't forget to add "$HOME/.local/bin" to your $PATH to make it easier for Emacs to find pyright. Without modifying your $PATH, it will still work, but you'll need to do additional configuration in your LSP setup to specify the search path.

For NPM_CONFIG_PREFIX usage trick during the installation with using -g see corresponding documentation page: Resolving EACCES permissions errors when installing packages globally.

As far as I can tell, lsp-pyright declares only the Node.js implementation of the (based)pyright server as a dependency for LSP. Moreover, as you can see from the code I provided above, the names of the executables that lsp-mode will look for are strictly defined. If you’ve chosen a different server implementation, you might need to configure lsp-mode first to use the Python version of the server implementation.

To properly answer the question "How can I tell lsp-pyright to use the installed pyright?", we first need to understand the search paths used by Emacs when calling executable-find. I suspect the issue lies in this area:
https://github.com/emacs-lsp/lsp-mode/blob/6b60f98eb16bb5419c55136050bb795a8d1a0e92/lsp-mode.el#L1746-L1764

It seems likely that after installing the Python version of the LSP server implementation, it ends up somewhere deep inside .venv/* (or wherever poetry installs dependencies, for example ~/.cache/pypoetry/virtualenvs), and Emacs simply can’t find it.

I’d also recommend using a more standard approach—the Node.js implementation of the server. With it, you’ll have a single, centralized installation that doesn’t need to be set up separately for each project. There’s no need to manage its updates or configure search paths manually. Additionally, as far as I can tell, the Node.js implementation is the most complete version of the server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants