The startup logic and instructions have been updated for simplicity in
pyenv 2.3.0. The workaround for pyenv init is no longer necessary.
Signed-off-by: Indrajit Raychaudhuri <irc@indrajit.com>
The desired logic is:
For the `pyenv` plugins `virtualenv-init` and `virtualenvwrapper`:
1. If either plugin is present, activate it
2. If `virtualenvwrapper` plugin is not present, then
[fallback to standard
`virtualenvwrapper`](https://github.com/sorin-ionescu/prezto/pull/1414#issuecomment-320306421).
3. If `virtualenvwrapper` plugin is present, then [don't fallback to
standard `virtualenvwrapper`, regardless of whether `virtualenv-init`
is
present](https://github.com/sorin-ionescu/prezto/pull/1981#issue-1123766676).
Previously, if the `virtualenv` command was present but `pyenv` was
missing, then the fallback wouldn't be hit. This bug was introduced by
https://github.com/sorin-ionescu/prezto/pull/1981/ which ensured that
the `pyenv` `virtualenvwrapper` plugin was activated if present,
regardless of the presence of the `virtualenv-init` plugin.
As an optimization, the check for the `pyenv` plugins are skipped if
`pyenv` itself isn't found.
Since we only want to fallback if the `pyenv` `virtualenvwrapper` plugin
is missing, but that's buried within the `pyenv` logic and we also need
to handle when `pyenv` itself is missing, this switches to using a flag
variable.
I also renamed the `virtualenv_sources` var to
`virtualenvwrapper_sources` as `virtualenv` is distinct from
`virtualenvwrapper`, so using one name for a var that is really about
the other is confusing.
Looking at `git blame`, there's a _lot_ of prior art here around trying
to support all the permutations of `pyenv` and various plugins:
* https://github.com/sorin-ionescu/prezto/issues/1413
* https://github.com/sorin-ionescu/prezto/pull/1414
* https://github.com/sorin-ionescu/prezto/pull/1433
* https://github.com/sorin-ionescu/prezto/pull/1434
So we need to be extremely careful to continue to support all these
permutations.
Fix https://github.com/sorin-ionescu/prezto/issues/2022
This is needed to find python.
It is often already set because a user has the directory or completion module loaded before this, but that's not always true.
See extensive debugging / further explanation here: https://github.com/sorin-ionescu/prezto/issues/1949
This does not fully resolve that issue, as there's another enhancement that I'll put up as a separate PR.
If conda is not in the list of requirements, the scripts exit too early in case pyenv is not installed and the module is configured with:
zstyle ':prezto:module:python' skip-virtualenvwrapper-init 'on'
zstyle ':prezto:module:python' conda-init 'on'
Tested on Amazon EC2 Linux for Deeplearning AMI 47.0 and MacOS 11.4
In pyenv 2.0 onwards, it is not enough anymore to initialize pyenv in
shell by just calling `pyenv init -`. We also need to update `path` to
include pyenv shims by calling `pyenv init --path`.
Also, honor `$PYENV_ROOT` if set but, no need to set it explicitly if
not set. Instead, let the initialization script take care of that.
Move `pip` to separate completion definition delegating to pip to do
all the completion work.
Since the completion is loaded lazily on-demand, it avoids the
performance overhead during Zsh initialization.
Implementation note:
The helper function `_pip_completion` implementation is based on the
official pip completion function (which can be generated with
`pip completion --zsh`) adhering to the newer compsys style.
See: 'man zshcompsys' for more details.
Changes:
- Fallback to `virtualenvwrapper` without `pyenv` wrapper if `python` is
available in path, regardless of whether `brew` is available.
- Look up for availability of `python2` and `python3`, not just `python`.
- Check for existence of path before adding to global `$path` array.
- Adhere to more idiomatic Zsh operation and minimize redundant syntaxes.
- Prefer looking up `$functions` for fully initialized `pyenv`.
When $WORKON_HOME is not set and $ENV_NAME is equal to
$PROJECT_ROOT/.venv which contains bin/activate then
the code wrongly assumes workon is available.
It should execute the second branch to source bin/activate.
Pyenv will install shims for commands that exist in any interpreter, even if it is not the current one. This means that a command may technically exist, but when executed will tell the user to try a different interpreter. The original check for pip in the Python module can fail for this reason, in particular on Ubuntu 20.04.
This change checks with pyenv whether pip really exists in the current interpreter to work around this problem and fixes a bug in pip command detection.
Just use brace expansion only (and not a mix of brace expansion and
path expansion) to expand `sed` match for more variants of 'pip*' (pip,
pip2, pip3, pip2.7, pip3.7 etc.) in `compctl` assignment
While mangling cached completion file, we cannot just assume that
`$pip_command` would resolve to `pip` -- it might be `pip2` or `pip3`
depending on the relative position in zsh `$commands` array. Thus
replace the whole of 'pip*' with 'pip pip2 pip3' for compctl assignment.
After profiling startup time, I found that "pyenv rehash" is
by far the slowest piece. This change skips rehashing on init.
See https://github.com/pyenv/pyenv/issues/784#issuecomment-404850327
Also pass the shell explicitly, as suggested in
https://github.com/pyenv/pyenv/issues/784#issuecomment-404944318,
which provides a modest improvement.
In total, this improves startup time from 1s to 0.3s on my machine.
Using the following command:
python -m timeit "__import__('subprocess').Popen(['zsh', '-i', '-c', 'echo']).communicate()"
Result before this change:
10 loops, best of 3: 1 sec per loop
Result after this change:
10 loops, best of 3: 334 msec per loop
* Added conda virtualenv support to python module
* Added instructions for Python module options to README
Thanks to @egpbos for the original feature and @ickc for fixing the merge conflicts.
Now that pyenv plugins availability is detected by directly probing
'pyenv', we need to rely on the same mechanism consistently.
Further, we perform available pyenv plugin scan with native zsh
techniques instead of relying on external commands.
If the pyenv virtualenv plugin is installed using the [pyenv-installer][1]
app script or directly via a [Git clone][2], then the pyenv-virtualenv-init
executable, that the `pyenv virtualenv-init` command uses, will not
exist in the user's PATH and therefore cannot be found using
`$commands[pyenv-virtualenv-init]`.
Installing the pyenv-virtualenv plugin in this manner is common among Linux users.
Using the pyenv `commands` command, which lists all commands pyenv can
run, we can find if the virtualenv-init command is available to pyenv
and subsequently the virtualenv plugin, without relying on
pyenv-virtualenv-init to exist in the user's PATH.
[1]: https://github.com/pyenv/pyenv-installer
[2]: https://github.com/pyenv/pyenv-virtualenv#installing-as-a-pyenv-plugin
Just having 'pyenv' available doesn't imply availability of virtualenv pyenv
plugins. Check for availability of virtualenv plugins as well before attempting
to use pyenv wrapper for virtualenv.
Changes:
* Simplify zstyle name `skip-virtualenvwrapper-init` to `initialize`
avoiding double negation in name
* Always perform `eval (pyenv virtualenv-init -)` at initialization
* Prefer `virtualenvwrapper_lazy` over `virtualenvwrapper` when available
* Honor `VIRTUALENVWRAPPER_VIRTUALENV` if it is defined.
* Document about `VIRTUALENVWRAPPER_PYTHON` and `VIRTUALENVWRAPPER_VIRTUALENV`
(this would be particularly important in macOS after recent homebrew update)
* Add additional documentation for `initialize` in _README.md_ and _zpreztorc_
* Add aliases `py2`, `py3` as shortcut for `python2`, `python3` respectively
We cannot always assume availability of `pip`, it can be `pip2` or `pip3`
instead. We detect the first available one and use it for generating the
completion cache.
* Command to activate virtualenvs on changing directory
Enables automatic activation of a virtualenv when jumping into a directory
This is done by looking in the current directory for a file or directory
named `.venv`. If it's not found in the current directory its parents will
also be examined. `.venv` can be either:
1. A file containing the name of a virtualenv found in $WORKON_HOME
2. A directory containing bin/activate (meaning that the directory is
assumed to be a virtualenv.)
If $WORKON_HOME is set it is assumed that virtualenvwrapper is installed
and the `workon` command will be issued.
This shouldn't cause problems for anyone and should improve startup times for
anyone using python with virtualenvwrapper because it will wait for the first
command to load rather than right away.
* Support skip-virtualenvwrapper-init zstyle in python module to avoid auto-sourcing of virtualenvwrapper.sh
* Don't overwrite the WORKON_HOME env var if the user has already set it