jmcantrell / vim-virtualenv

Vim plugin for working with python virtualenvs
http://www.vim.org/scripts/script.php?script_id=3486
Do What The F*ck You Want To Public License
601 stars 51 forks source link

sys.path entries get erased by :VirtualEnvDeactivate in particular scenario #53

Open solovyevn opened 8 years ago

solovyevn commented 8 years ago

Note: I use pyvenv for virtual environments, I don't know if the same problem occurs for virtualenv users.

The issues is probably related to how the sys.path is handled for activation and deactivation of virtual environment. The vim-virtualenv plugin is not always run/initialized first relative to other plugins (that may also modify sys.path), but it looks like :VirtualEnvDeactivate command's code assumes, that the venv's site-packages entry is the first in sys.path. This leads to some entries being erased from the path, when the command is run. See example and actions to repeat the issue below.

Scenario 1 (starting vim when venv is already active, the path gets erased):

  1. I activate virtual environment in bash;
  2. Run vim somefile.py;
  3. In vim I check sys.path by running :python import sys; print(sys.path);
  4. The path is a long list, WITH directories for YouCompleteMe and my virtual environment site-packages somewhere in the middle;
  5. Then, in vim I run :VirtualEnvDeactivate;
  6. And I check sys.path again by running :python import sys; print(sys.path);
  7. The path is a very short list WITHOUT directories for YouCompleteMe, and, of course, without the directory for venv's site-packages;
  8. If I run :VirtualEnvActivate venv_name, and check sys.path again there're no directories for YouCompleteMe, and the directory for venv's site-packages is the first in the list.

Scenario 2 (manual virtual environment activation in vim, works as expected):

  1. No virtual environment is active, and I run vim somefile.py;
  2. In vim I check sys.path by running :python import sys; print(sys.path);
  3. The path is a long list WITH directories for YouCompleteMe, and, of course, without the directory for venv's site-packages;
  4. I run :VirtualEnvActivate venv_name, and check sys.path again;
  5. The path is a long list WITH directories for YouCompleteMe, and the directory for venv's site-packages is the first in the list;
  6. Then, in vim I run :VirtualEnvDeactivate, and check sys.path again;
  7. The path is a long list WITH directories for YouCompleteMe, and, of course, without the directory for venv's site-packages.
jmcantrell commented 8 years ago

The reason is that sys.path is saved prior to modification, and restored after deactivation. If another plugin or script uses the same strategy or modifies it, those changes would get lost. I'm open to suggestions on how this can be handled better.

jmcantrell commented 8 years ago

What about this. The plugin can save the site-packages path that gets added during activation. On deactivation, remove the matching path from sys.path with something like remove(index(sys_path, site_pkg))

solovyevn commented 8 years ago

I'm sorry, I didn't have time to look through the code, so I just posted it as an issue I came across, and not the pull request. Your proposed solution looks like a good idea, it will work for any posistion in the sys.path and doesn't affect any other plugins. Guess it can be simplified to sys.path.remove(site_pkg).

jmcantrell commented 8 years ago

Nice one. Thanks!

solovyevn commented 8 years ago

No problem! )