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

Look into using mypy's daemon #1577

Closed
brettcannon opened this issue May 2, 2018 · 26 comments
Closed

Look into using mypy's daemon #1577

brettcannon opened this issue May 2, 2018 · 26 comments
Labels
area-editor-* User-facing catch-all area-linting feature-request Request for new features or functionality

Comments

@brettcannon
Copy link
Member

https://mypy.readthedocs.io/en/latest/mypy_daemon.html

@brettcannon brettcannon added feature-request Request for new features or functionality area-linting needs decision labels May 2, 2018
@erichiller
Copy link

Looks like as of June 2018 work has begun for Windows daemon support.
python/mypy#5019

@ethanhs
Copy link

ethanhs commented Nov 27, 2018

FYI, mypy master now has a working implementation of the mypy daemon for Windows if you want to play with it.

@erichiller
Copy link

How would we be able to use dmypy within vscode? Do you mean just for testing via the command line? Or is there a proper way to integrate this with vscode currently? If not are there plans to use the daemon or give the option?

@ethanhs
Copy link

ethanhs commented Dec 30, 2018

@erichiller Until there is more official support, as a work around you can use something like the following:

{
    "python.linting.mypyEnabled": true,
    "python.linting.mypyPath": "C:\\Python37\\Scripts\\dmypy.exe",
    "python.linting.mypyArgs": [
        "run",
        "--",
        "--ignore-missing-imports",
        "--follow-imports=skip"
    ]
}

Though this is rather hackish. (It won't kill the daemon when VS Code closes, which likely is not the behavior you want). Also this is rather abusing the whole "set an executable and args" settings system...

Do note you must change the argument for following imports to either skip or error for now.

@brettcannon
Copy link
Member Author

@erichiller we would like to add support, but we don't have any ETA on when this will get prioritized high enough for us to get around to it.

@ethanhs thanks for the work-around!

@DonJayamanne
Copy link

DonJayamanne commented May 9, 2019

@ilevkivskyi

Thanks for connecting with us at PyCon, looking forward to landing this in the extension.

Lets get the ball rolling.
A few questions (there'll be a few more, but lets start with a few simple ones):

  • How do we start multiple daemons for different repositories? The docs don't cover that.
    • Assume user opens two instances of VS Code, both instances of VSC will now run dmypy start.
    • My assumption is, this will result in two instances of the daemon.
  • Will shutting down the parent process kill the daemon automatically or is it a detached sub process?
    • I.e. if we were to kill vscode (non-graceful shutdown), will this result in the daemon evetually killing itself, or will it stay alive and never die?
  • Silyy question:
    • Assume we have two instances of vscode, one using Python 2.7 another using python 3.7. When Python2.7 sends requests to the daemon, will it send the messages to the daemon that it started.
    • I guess the answer is obviously yes, just don't want to make assumptions here.
  • Cancellation,
    • Assume we send a command to lint a large file, and immediately after that we send the same file (but with some changes). Will mypy cancel the previous request or will it simply queue the request. I.e. wait for previous request to complete.
  • Multiple requests
    • Assume we send a command to lint a large file
    • While we're waiting for that request to be processed we send another request to the same daemon to process a large file, will the daemon block on the previous request or somehow process this in parallel?

@ilevkivskyi
Copy link

@DonJayamanne

How do we start multiple daemons for different repositories?

I think the simplest way is to set current working directory to the repo root when calling dmypy start command.

[...] I.e. if we were to kill vscode (non-graceful shutdown), will this result in the daemon evetually killing itself, or will it stay alive and never die?

No it will not die. Process created by dmypy start (client) exits immediately, but it leaves the daemon (server) "detached". The daemon however will shut down after a timeout if it receives no requests (configurable, default is 24 hours). Also calling dmypy kill unconditionally kills the server.

Assume we have two instances of vscode, one using Python 2.7 another using python 3.7. When Python2.7 sends requests to the daemon, will it send the messages to the daemon that it started.

Mypy only supports Python 3.5+, it can type check older versions (including 2.7), but you need to have Python 3 installed to run it. If you want to type check a repo in Python 2 mode and then in Python 3 mode, I think the best way is to start two daemons each one configured with --python-version=x.y (you will also need to pass --status-file XXX to each daemon when starting the server, and when communicating with them using dmypy client to distinguish them).

Assume we send a command to lint a large file, and immediately after that we send the same file (but with some changes). Will mypy cancel the previous request or will it simply queue the request. I.e. wait for previous request to complete

Currently this is not possible. dmypy check and dmypy recheck are blocking calls, i.e. they don't exit before the server responds with the checking, and then they print checking results to stdout and exit. From user point of view dmypy check behaves essentially the same as mypy. You can of course issuer another dmypy check (i.e. create another client process) before previous exits, but I am not sure this is going to end well currently. We discussed the possibility to add dmypy cancel to gracefully abort last type checking request, and it may be not so easy to implement. But potentially we can do this if it is important.

Assume we send a command to lint a large file.

It is not how mypy normally works (not only the daemon), see #5587. I actually believe we should figure out that issue first before continuing here.

@brettcannon brettcannon added needs proposal Need to make some design decisions and removed needs PR labels May 10, 2019
@matangover
Copy link

matangover commented May 15, 2019

For anyone wanting this now I actually made two extensions (though I'm very happy to see this will be integrated into the Python extension).

  1. Mypy extension that runs a language server (mypyls) that embeds the mypy server (unsupported by mypy team). Done as an exercise to see if I can do hovers / go to definition using mypy analysis (in addition to type checking) -- works pretty nicely.

  2. A simpler extension that runs dmypy on the command line.

@brettcannon
Copy link
Member Author

And the daemon is now hit GA: https://mypy-lang.blogspot.com/2019/11/mypy-0.html

@ijstokes
Copy link

ijstokes commented Jan 6, 2020

I would love to be using the mypy daemon with VS Code. If I can get this to work it will likely become standard for 500+ data scientists at my current employer. VS Code & MyPy are already recommended "best practice", but having the two play nicely together with the daemon would be great (yes, standard MyPy linting response times are a problem for us). I have experimented with the @matangover language server variant but abandoned it an hour ago due to various complexities & problems.

FWIW I've been using MyPy extensively for about 18 months and have run several internal trainings on its use within my current organization. We've also seen a general shift from PyCharm to VS Code. In this setting my user-centric view of what I'd like to happen:

  1. MyPy tooling is part of the conda environment currently selected for a particular workspace (including any language server parts). This could also be a pipenv environment for people who go that route, but I'm only interested in conda (which is what we widely use).

  2. The daemon runs once per workspace in the currently selected Python environment . The daemon runs from the Python environment, not some other location. If the environment is changed then the daemon needs to restart from the new environment. Understand this means the extension/process will fail if the tooling is not available in the new environment -- extension warnings seem to cope with that eventuality already.

  3. Multiple open workspaces (multiple open/active projects) would mean multiple daemons running.

  4. By default shutdown the daemon when VS-Code workspace is closed. Optionally configure this to keep the daemon running even after shutdown via VS-Code extension configuration file.

  5. When a workspace starts or the environment changes, check to see if there is a currently running daemon for that workspace with that environment, and use it if possible.

  6. Nice to have: Any independent CLI execution (e.g. pre-commit checks) that run in the same conda environment for the same code base could use the same already-running mypy Python LS daemon, assuming the associated VS-Code workspace is still active.

@ijstokes
Copy link

ijstokes commented Jan 6, 2020

In parallel to my input on what I'd like best from VSCode-Python listed above, I posted on SO to ask for clarification on the current options around Python + MyPy + LanguageServer in VS Code:

https://stackoverflow.com/questions/59605882/how-to-choose-between-vs-code-language-server-options-for-python-mypy-linting

@brettcannon
Copy link
Member Author

@ijstokes thanks for the feedback! Please make sure to 👍 the opening comment to make sure your preferences of how we prioritize our time are taken into consideration.

@luabud luabud added needs spike Label for issues that need investigation before they can be worked on. and removed needs proposal Need to make some design decisions labels Sep 1, 2020
@JosXa
Copy link

JosXa commented Dec 31, 2020

In parallel to my input on what I'd like best from VSCode-Python listed above, I posted on SO to ask for clarification on the current options around Python + MyPy + LanguageServer in VS Code:

https://stackoverflow.com/questions/59605882/how-to-choose-between-vs-code-language-server-options-for-python-mypy-linting

@ijstokes Your link is broken. Would love to read that

@samestep
Copy link

@ijstokes Your link is broken. Would love to read that

@JosXa here is the text from that deleted SO question:

The built-in Python language server in VS Code does not appear to perform any caching. As a result it takes 10s of seconds to re-process all code that is in a Workspace for a medium size project if MyPy type hint verification is turned on for linting. This makes VSCode unusably slow and blocks other operations from working properly while the back-ground parsing is happening.

I have read about alternative Python language servers that use a daemon process in order to cache the already parsed (but unchanged) code in a project, however I cannot figure out how to get these configured and setup. Any guidance on this is appreciated.

In case it is helpful, here are some of the references to this issue that I have drawn on in my own quest to solve this problem. The last one is from a Microsoft engineer working on VSCode Python plugin acknowledging that this is an open issue with the Microsoft-provided Python Language Server:

@rben01
Copy link

rben01 commented Feb 19, 2021

@erichiller Until there is more official support, as a work around you can use something like the following:

{
    "python.linting.mypyEnabled": true,
    "python.linting.mypyPath": "C:\\Python37\\Scripts\\dmypy.exe",
    "python.linting.mypyArgs": [
        "run",
        "--",
        "--ignore-missing-imports",
        "--follow-imports=skip"
    ]
}

This doesn't work for me. Here's the Python extension's output:

> ~/Library/Caches/pypoetry/virtualenvs/env-name-py3.8/bin/python ~/.vscode/extensions/ms-python.python-2021.2.576481509/pythonFiles/pyvsc-run-isolated.py -c "import dmypy"

Linter 'mypy' is not installed. Please install it or select another linter".
Error: Module 'dmypy' not installed.

Looks like it's changed how it does mypy linting so that you can't just pass it arbitrary command line arguments.

@adam-grant-hendry
Copy link

At the risk of asking a dumb question, if I can get mypy linting using the right json settings per @ethanhs ... why do I need to run the daemon? What added benefit does the daemon give me that I'm not already getting by linting?

@rben01
Copy link

rben01 commented Mar 5, 2021

At the risk of asking a dumb question, if I can get mypy linting using the right json settings per @ethanhs ... why do I need to run the daemon? What added benefit does the daemon give me that I'm not already getting by linting?

I believe that (non daemon) mypy must start up and re-read any cached data before beginning to work on the files you pass it, which takes some time. In contrast the daemon remains in memory and has no startup cost for runs after the first, so it should return results much faster.

@reporter123
Copy link

@rben01 Your not even getting that far.

Linter 'mypy' is not installed. Please install it or select another linter".
Error: Module 'dmypy' not installed.

This means mypy is not being found at all. Like because it isn't installed in the python virtual environment you are running in. Ran into the same thing myself under different circumstances.

@matangover
Copy link

@ijstokes FWIW I implemented most of what you asked for in my mypy extension a few months ago. It now runs the mypy daemon directly for each workspace folder. I also added the runUsingActiveInterpreter option which I think you were asking for.

@lithammer
Copy link

lithammer commented Oct 28, 2021

I opened a ticket to upgrade dmypy to a language server a while back. I guess that could be relevant for this as well:

@KholdStare
Copy link

Any updates?

@JamesHutchison
Copy link

JamesHutchison commented Apr 11, 2023

This dev container template uses the daemon:

https://github.com/JamesHutchison/python-dev-container-template

I agree that the daemon makes more sense in general, however the daemon has also been somewhat "semi-experimental" as it runs a different code path so I can understand being hesitant to use it by default.

If your repo is very large and has a very large number of errors, both mypy and dmypy are atrociously slow. This is because the daemon uses errors as a signal to reprocess a file, even if it wasn't touched.

@karthiknadig
Copy link
Member

We now have a preview version of mypy extension that uses dmypy for linting. Please give it a try:
https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker

@tusharsadhwani
Copy link

@karthiknadig just a heads up, using dmypy by default for vscode may cause bugs like this to surface, causing users problems: python/mypy#12249

@karthiknadig
Copy link
Member

karthiknadig commented Jun 14, 2023

@tusharsadhwani The extension allows you to configure it to run using mypy as well using mypy-type-checker.path setting. You can point it to the mypy executable to use that. You can use variable resolution support to configure the mypy-type-checker.path like "${workspaceFolder}.venv\bin\mypy", or if you have mypy globally or from an activated environment, you could even just say "mypy-type-checker.path": ["mypy"]

@karthiknadig
Copy link
Member

Closing this against https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker

FYI, that extension allows you to switch between dmypy or mypy using the mypy-type-checker.preferDaemon setting. Default is dmypy.

@github-actions github-actions bot removed the needs spike Label for issues that need investigation before they can be worked on. label Oct 19, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-editor-* User-facing catch-all area-linting feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests