Make Vim detect Pipenv based Python environment
Vim can be a great IDE. If I could you use just one word to describe it, that word would be “fast”. Vim can be easily configured to be a powerful IDE for Python development. However, as times change, as does the official recommended packaging tool for Python – it was Pip before, now it’s Pipenv, a high level wrapper around pip
and virtualenv
.
Setting up a proper integration between Vim and Pipenv may seem like a cumbersome task. It entirely depends on what you want to achieve. This article focuses on integration between Vim, Pipenv, and YouCompleteMe – a fast, fuzzy-search code completion engine for Vim. But some of the options described in the article are suitable for other setups as well.
Vim as a Python IDE
I could talk about Vim all day, if I had a chance. Vim requires less resources to run than most of the modern IDEs. It’s faster in many ways, even when it comes to syntax verification, file reading, and handling of large repositories. Vim has a tremendously large amount of commands, plugins, and shortcuts which are all configurable and allow you to navigate and edit in a blink of an eye. And last but not least, you can usually find an instance of Vim (or at least vi
) on any Unix based OS, which proves to be especially useful for DevOps engineers. Same powerful editor on a server and on your workstation.
Here is a small list of plugins you could install to turn Vim into a Python IDE:
Obviously, there is so much more to Vim than just a list of plugins. Vim’s configuration file – .vimrc
– can become quite large, just because there are so many things you can configure in Vim. However, complete configuration of Vim for Python development is a topic of a different article.
VirtualEnv Support
One of the issues you can discover is that by default Vim has no notion of a virtual environment in which you are supposed to run. In order to perform any auto-completion or syntax checking tasks Vim utilizes the default python interpreter found in the PATH
environment variable.
The classic way to make Vim aware of project’s virtual environment is to check the list of environment variables to detect whether we are running inside a virtual environment and activate it. This approach is documented on the realpython.com:
Unfortunately, this no longer works if we deal with Pipenv based virtual environments. The environment itself might not even be in the same directory, or not even under default path ~/.local/share/virtualenvs/
.
However, we can take advantage of Pipenv’s own commands to determine if we are supposed to be running in a virtual environment.
When we have a PyEnv installed it will detect our call to pipenv
. Let’s take a look at possible situations:
Directory is not configured for PyEnv or Pipenv
In this case both python interpreter and Pipenv are not configured for the current directory. PyEnv reports that it could, theoretically, run pipenv
, which is available in the 3.6.5
installation, but would need you to indicate that explicitly.
The same behavior will be observed if pipenv
is not installed as a package in the interpreter of choice. Let’s say, we specify a python version 3.4.3
in a .python-verison
file, which has no pipenv
installed. Same error will be thrown out by PyEnv in that case.
Directory is configured for PyEnv, but no virtual environment is created yet
Here, .python-version
file exists for PyEnv to detect. And the python interpreter that we specified in the file has Pipenv installed as a package. In that case Pipenv will indicate that no virtual environment has been created yet.
Directory is configured for PyEnv and virtual environment exists
In this case pyenv --venv
returns full path to the virtual environment utilized in this project.
Making it work in .vimrc
We can take advantage of the fact that whenever we call pipenv --venv
its return code will indicate successful (sys.exit(0)
) or unsuccessful (sys.exit(1)
) run.
There is a variable named shell_error
in Vim, and, as you probably figured out, it contains the last exit code of the executed shell command.
If we make a call to pipenv --venv
from .vimrc
, we will either get a correct path, or one of the error messages we observed earlier. In order to make a call we can use the system()
function of Vim:
Then, simply by checking the value of shell_error
variable, we can find out if the call was successful.
Since in this article we set up Python’s auto-completion for YouCompleteMe engine, we will use YCM’s global variable g:ycm_python_binary_path
to point it to the correct executable of proper virtual environment.
The final script that we’ll add to the .vimrc
will lok like this:
This script can be further modified to support different completion engines or even other types of plugins, but the essence remains the same – determine whether Vim is running in the correctly configured Pipenv directory.